Skip to content

Create initial implementation for a2ui_agent. - #1020

Open
polina-c wants to merge 21 commits into
flutter:mainfrom
polina-c:implement-lib
Open

Create initial implementation for a2ui_agent.#1020
polina-c wants to merge 21 commits into
flutter:mainfrom
polina-c:implement-lib

Conversation

@polina-c

@polina-c polina-c commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Prompt:

Use this blueprint to implement the library a2ui_agent: https://github.com/a2ui-project/a2ui/blob/main/blueprints/modules/a2ui_agent.blueprint.md

Next steps:

  • test coverage
  • use in genui and create migration plan
  • port to g3
  • migrate users

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the a2ui_agent package, which provides the A2UI Agent SDK including support for the Direct JSON inference format, streaming parsers, catalog document utilities, and payload validation. The review feedback highlights a critical syntax error in catalog_document.dart where invalid null-aware map syntax is used, and a medium-severity issue in streaming.dart regarding the use of a literal null character in a string literal.

Note: Security Review did not run due to the size of the PR.

Comment thread packages/a2ui_agent/lib/src/utils/catalog_document.dart
@polina-c
polina-c marked this pull request as ready for review August 11, 2026 20:26
@polina-c

Copy link
Copy Markdown
Collaborator Author

If looks ok, I will resolve circlular dependencies.

@jacobsimionato jacobsimionato left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey this is looking great - nice work Polina and Gemini! It is a lot of code!

I'm actually finding it okay to review, because it's mostly about the interfaces. But I do wonder about trying to split it a little... e.g. you could probably omit the express format completely in the first PR for example.

I like Nan's idea of trying to do conformance tests up front too. Though they will only really test the implementation, and the more interesting part to review as a human is the APIs and how you've translated them to Dart. So maybe we can human-review the APIs here and not worry too much about the implementation, then add conformance tests and have an agent fix the implementations where necessary.

I dunno, curious about @nan-yu 's thoughts on the best process also. I'd like to make sure that both of us get a proper chance to review the APIs here, because they are important and difficult to change later.

/// currently being streamed. Formats only implement [emitDelta], which is
/// handed the whole raw block accumulated so far and returns the messages that
/// have not been emitted yet.
abstract class IncrementalStreamProcessor {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a useful utility - I wonder if it should be in the shared design!

/// Client functions execute on the renderer, so the agent side carries the
/// signature but cannot run it. [execute] throws to make an accidental
/// server-side invocation loud instead of silently wrong.
class DeclaredFunction extends FunctionImplementation {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should instead handle FunctionApi and FunctionImplementation similar to how we handle ComponentApi and ComponentImplementation in the core library.

E.g. FunctionApi does not declare execute at all, and FunctionImplementation extends FunctionApi.

Then we have Catalog<C extends ComponentApi, F extends FunctionApi> perhaps.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also be moved to the a2ui_core layer.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gspencergoog used ANTLR to generate the core parts of this for Python and Kotlin, based on some language definition file. Can we do that for Dart too? It seems supported - https://github.com/antlr/antlr4

See https://github.com/a2ui-project/a2ui/tree/main/agent_sdks/python/a2ui_agent/src/a2ui/inference_formats/experimental/express/generated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, feel free to omit the express stuff from the initial PR if you like - it's easy to add as a followup because it's behind a well-defined narrow interface (InferenceFormatFactory, InferenceFormat).

/// [protocolVersion] and [catalogId], when given, must agree with what the
/// document declares; a conflict throws [A2uiValidationError] rather than
/// silently loading a catalog the renderer did not ask for.
Catalog<ComponentApi> catalogFromDocument(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the protocol version and catalog Id should be declared in the document anyway, right?

I think this should be implemented in the core library, possibly on the Catalog and Component classes / interfaces themselves.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the Catalog class is designed to have from_json and catalog_schema, which builds a Catalog class from a JSON schema, and returns the catalog schema in JSON representation.

///
/// The key of the surrounding map describes the example turn; the value is the
/// A2UI payload the model is expected to produce for it.
typedef PromptExamples = Map<String, List<AgentToRendererMessage>>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it!

/// Optional few-shot example turns, keyed by a description of the turn.
final PromptExamples? examples;

const PromptGenerator(this.catalogs, {this.examples});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't remember what is in the standard design, but I'm wondering if we maybe don't need to expose the catalogs or examples or define a constructor here. Instead, we just expose generate() and each inference format can implement this however it wants.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nan-yu if we don't have them already, let's add conformance tests requiring that each prompt generator implementation returns exactly the same prompt for a given catalog. Then we know that the eval work we do will translate across library implementations.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have it already in https://github.com/a2ui-project/a2ui/blob/a70e0ebc7ec37d848f1bd6194d10cc135efb5ab0/agent_sdks/conformance/suites/inference_format.yaml#L191.

Just a heads up, we're planning to restructure the conformance suite to be more modularized, but it will have same coverage.

@jacobsimionato

Copy link
Copy Markdown
Collaborator

Also, I think we reached consensus to do this in the A2uI repo, right? I know that was after you created this PR though!

@polina-c

Copy link
Copy Markdown
Collaborator Author

Also, I think we reached consensus to do this in the A2uI repo, right? I know that was after you created this PR though!

I am confused.

I thought we have agreement to copy it to a2ui repo after a2ui repo is ready, together with a2ui_core, that is in monorepo with this code (see a2ui-project/a2ui#2234).

Do you suggest to hold development?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should belong to the Dart a2ui_core library, which maps the web_core version, https://github.com/a2ui-project/a2ui/blob/main/renderers/web_core/src/v0_9/schema/client-capabilities.ts#L55.

It actually brings up a broader issue. Should we update the Dart a2ui_core library first, and then build the a2ui_agent on the latest a2ui_core?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation layer should also reside in the a2ui_core layer.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have it already in https://github.com/a2ui-project/a2ui/blob/a70e0ebc7ec37d848f1bd6194d10cc135efb5ab0/agent_sdks/conformance/suites/inference_format.yaml#L191.

Just a heads up, we're planning to restructure the conformance suite to be more modularized, but it will have same coverage.


@override
Catalog<ComponentApi> load() {
if (protocolVersion == ProtocolVersion.v09) return MinimalCatalog();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why MinimalCatalog? Do we have a BasicCatalog in Dart?

/// `package:a2ui_core` bundles the minimal catalog for `v0.9`. Other versions
/// have no bundled catalog in Dart yet, so asking for one is an error rather
/// than a silent fallback to a catalog the renderer never agreed to.
class BundledCatalogProvider extends CatalogProvider {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot to update the blueprint when we decided to remove the BundledCatalogProvider class. Nothing needs to be bundled with the SDK. We can use the BasicCatalog directly from a2ui_core. I'll update the blueprint separately.

/// Client functions execute on the renderer, so the agent side carries the
/// signature but cannot run it. [execute] throws to make an accidental
/// server-side invocation loud instead of silently wrong.
class DeclaredFunction extends FunctionImplementation {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also be moved to the a2ui_core layer.

/// [protocolVersion] and [catalogId], when given, must agree with what the
/// document declares; a conflict throws [A2uiValidationError] rather than
/// silently loading a catalog the renderer did not ask for.
Catalog<ComponentApi> catalogFromDocument(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the Catalog class is designed to have from_json and catalog_schema, which builds a Catalog class from a JSON schema, and returns the catalog schema in JSON representation.

import '../utils/schema_utils.dart';

/// A single problem found in an A2UI payload.
class A2uiValidationIssue {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename to A2uiValidationError? It should also go to the a2ui_core layer.

/// This is the agent SDK's validation layer. The A2UI agent specification
/// delegates it to `A2uiValidator` in the core package;
/// `package:a2ui_core` does not ship one yet, so the checks live here and
/// operate on the `v0.9` envelopes that package models.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validator in a2ui_core should support validation against all protocol versions.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of these unit tests should be moved to conformance spec, so we don't repeat for each implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants