Skip to content

feat(typescript): call renderer functions from the agent - #3940

Open
nan-yu wants to merge 13 commits into
feat/ts-agent-function-rpcfrom
feat/ts-renderer-function-calls
Open

nan-yu wants to merge 13 commits into
feat/ts-agent-function-rpcfrom
feat/ts-renderer-function-calls

Conversation

@nan-yu

@nan-yu nan-yu commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #3862. Review the top eleven commits: feat(typescript): call renderer functions from the agent (#3535), followed by the review-fix and conformance commits covering RendererFunctionCalls.resolve declining unknown responses, catalog target checks, the shared validation order, isPending, and routing conformance responses through RendererToAgentMessageProcessor. Draft until #3862 lands and the open questions below are settled.
Part of #3535.

Description

#3862 first shipped the agent's calls to renderer functions (callRendererFunction) together with agent functions, as the Python stack did. The review on #3793 questioned whether in-memory pending calls fit stateless HTTP servers, where the rendererFunctionResponse can arrive in a later request on another replica. To keep agent functions moving, renderer function calls were split out of #3862 into this PR in every SDK (Python #3939, Dart #3941). The code is the code that was on #3862, renamed to fit RendererToAgentMessageProcessor, with the review fixes below.

  1. RendererFunctionCalls in @a2ui/agent, one per conversation. call({catalogId, name, args?, surfaceId?, timeoutMs?, functionCallId?}) checks the call and returns the callRendererFunction message to send and a cancellable promise of the result, as a tuple or by name. resolve settles the matching promise with the renderer's value, or rejects it with A2uiRpcError carrying the renderer's code. It returns true when it settled or failed a pending call, and false when the functionCallId isn't pending (unknown, late or a duplicate).

  2. A call times out after DEFAULT_RENDERER_CALL_TIMEOUT_MS (30 seconds, as on the renderer side) unless defaultTimeoutMs (which null disables) or timeoutMs says otherwise. Cancelling a call rejects it with CANCELLED and frees its slot. Unknown, duplicate and late responses are ignored, and resolve returns false for them. maxPending limits the calls in flight (TOO_MANY_PENDING), and dispose rejects the pending calls with CANCELLED and refuses later calls with DISPOSED.

  3. @a2ui/web_core gets RpcErrorCode.TOO_MANY_PENDING.

  4. How it plugs into the processor: resolve is a bound function, passed to RendererToAgentMessageProcessor as onRendererFunctionResponse, so the processor validates the response and hands it over. Since callbacks may return false to decline (from the second review of feat(python-agent): answer agent functions through RendererToAgentMessageProcessor #3793), a response resolve doesn't own, such as one to a call the model wrote, comes back handled: false and can go on to the model. The processor's API from feat(typescript): agent functions and RendererToAgentMessageProcessor #3862 doesn't change:

    const calls = new RendererFunctionCalls({defaultTimeoutMs: 10_000});
    const messages = new RendererToAgentMessageProcessor({
      catalogs: [catalog],
      onRendererFunctionResponse: calls.resolve,
    });
  5. The README gets a "Calling renderer functions" section, and both CHANGELOGs list the API.

Review fixes from #3793, applied here as in Python:

  1. An empty function name is rejected with A2uiRpcError (INVALID_FUNCTION_CALL), like an empty catalogId.
  2. An empty surfaceId counts as omitted: the message leaves it out.
  3. A malformed rendererFunctionResponse that carries a pending call's functionCallId fails that call right away with UNKNOWN_ERROR, instead of leaving it to time out.
  4. The test for settling a call checks that its timer is cleared (vi.getTimerCount() drops to 0), the counterpart of Python's timer.cancelled() assertion.

Open design questions, kept for discussion on #3939:

  1. maxPending and the TOO_MANY_PENDING code, which the protocol doesn't define. The agent's own code starts these calls, so a limit may not be needed.
  2. Stateless servers. Each instance keeps its pending calls in memory, so a response must reach the instance that made the call, over a connection that stays open such as a WebSocket. A stateless multi-replica server would handle rendererFunctionResponse in its own onRendererFunctionResponse callback instead. The README says so.

Catalog checks (after review on #3793, #3793 (comment)): RendererFunctionCalls takes an optional catalogs argument. With it, call() checks the target before it builds a message, registers a pending call or starts a timer. An unknown catalogId, or a name that isn't one of that catalog's renderer functions (agent functions included), gets UNKNOWN_FUNCTION. A rendererOnly function (or one that leaves out allowedCallers) gets INVALID_FUNCTION_CALL, and so does one with requiresUserActivation: true, since a call from the agent has no user gesture. Two catalogs with the same ID are a catalog error. Without catalogs, nothing changes. The conformance runner supports the new catalogs cases. Checked locally against renderer_function_calls.yaml from #3939: 31/31 (30 cases and the non-empty check). call() runs its checks in the same order in all three SDKs:

  1. an invalid timeout
  2. disposed
  3. an empty given functionCallId
  4. a duplicate id
  5. max_pending
  6. an empty name, then an empty catalogId
  7. a name that isn't an identifier
  8. the args checks: a JSON object, identifier keys, and JSON values (no NaN or infinity)
  9. these catalog checks

Only the instance default timeout can be "no limit". isPending(functionCallId) inspects whether a call is awaiting a response without settling it, matching Python and Dart.

Changes after the latest review: Review: removed the seconds-based DEFAULT_RENDERER_CALL_TIMEOUT; one consolidated CHANGELOG entry with the #3940 link, and the link on TOO_MANY_PENDING. Aligned with #3939 and #3941: resolve fails a pending call with UNKNOWN_ERROR for error: null, neither value nor error, extra keys or another version; a late response after dispose() settles nothing; the conformance runner enforces the closed RendererCallError and RendererCallsBuildError shapes.

Tests

  1. renderer-function-calls.test.ts: options and call validation (including an empty name), duplicate IDs and maxPending, tuple and named results, cancellation, an empty surfaceId, ignored responses, a malformed response that fails its pending call, timers cleared on settle, timeouts and dispose, null defaultTimeoutMs, resolve as the processor's onRendererFunctionResponse, and what resolve returns for pending and other responses. Fake timers are reset in an afterEach hook.
  2. renderer-function-calls.test.ts (conformance) runs conformance/agent/renderer_function_calls.yaml. That suite lands with feat(python-agent): call renderer functions from the agent #3939, so on this branch the runner registers one skipped test saying the suite isn't in the checkout. With the suite from feat(python-agent): call renderer functions from the agent #3939 copied into a copy of this branch, all 30 cases and the non-empty check pass (31 tests), delivering responses through RendererToAgentMessageProcessor and checking calls.isPending.
  3. yarn --cwd typescript/agents/a2ui_agent build && yarn --cwd typescript/agents/a2ui_agent test && yarn --cwd typescript/agents/a2ui_agent lint && yarn --cwd typescript/agents/a2ui_agent format:check: 1428 passed, 69 skipped.

@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 "RendererFunctionCalls" class to manage agent-to-renderer function calls, handling pending calls, timeouts, cancellations, and response correlation, alongside adding the "TOO_MANY_PENDING" error code to "RpcErrorCode". The review feedback suggests refactoring the unit tests to use an "afterEach" hook for resetting fake timers instead of wrapping assertions in redundant "try...finally" blocks, which reduces boilerplate and prevents test pollution.

@nan-yu
nan-yu added this pull request to stack #3971 November 4, 2026 05:17
@nan-yu
nan-yu marked this pull request as ready for review November 4, 2026 05:22
@nan-yu
nan-yu force-pushed the feat/ts-renderer-function-calls branch from 9ebf225 to 175ad53 Compare November 4, 2026 18:21
@nan-yu
nan-yu force-pushed the feat/ts-renderer-function-calls branch from 175ad53 to 4cd64f5 Compare November 4, 2026 19:22
nan-yu added a commit that referenced this pull request Nov 4, 2026
Audit the agent functions feature blueprint against the Python, TS and Dart
branches and fix the drift:
- The version check runs first for every message kind, so a
  callAgentFunction with a missing or other version raises even with a
  functionCallId; a schema-failing call with a readable id still gets an
  INVALID_FUNCTION_CALL reply in all three SDKs.
- The timeout option is agent_function_timeout (seconds) in Python,
  agentFunctionTimeoutMs in TypeScript and Duration agentFunctionTimeout in
  Dart; the sketch now uses a neutral name.
- The callback signatures per SDK, including Dart's FutureOr<void>
  callbacks that still decline with false.
- Only Python's a2ui.rpc re-exports the message classes; a validation error
  raised by a handler is INVALID_FUNCTION_CALL in Dart only.

Replace the follow-up note with section 5, the agent calling renderer
functions as implemented by #3939, #3940 and #3941: RendererFunctionCalls,
its checks and error codes, timeouts, resolve returning whether it owned
the response, malformed responses, disposal, the optional catalog checks,
the in-memory limitation on stateless servers, and the ADK integration.
Requirements, links, conformance (renderer_function_calls.yaml, 23 cases)
and implementation steps follow. The Python agent codebase blueprint says
renderer calls come in the follow-up #3939.

Signed-off-by: Nan Yu <nanyu@google.com>
@nan-yu
nan-yu force-pushed the feat/ts-renderer-function-calls branch from 4cd64f5 to ad272c1 Compare November 4, 2026 20:23
nan-yu added a commit that referenced this pull request Nov 4, 2026
Audit the agent functions feature blueprint against the Python, TS and Dart
branches and fix the drift:
- The version check runs first for every message kind, so a
  callAgentFunction with a missing or other version raises even with a
  functionCallId; a schema-failing call with a readable id still gets an
  INVALID_FUNCTION_CALL reply in all three SDKs.
- The timeout option is agent_function_timeout (seconds) in Python,
  agentFunctionTimeoutMs in TypeScript and Duration agentFunctionTimeout in
  Dart; the sketch now uses a neutral name.
- The callback signatures per SDK, including Dart's FutureOr<void>
  callbacks that still decline with false.
- Only Python's a2ui.rpc re-exports the message classes; a validation error
  raised by a handler is INVALID_FUNCTION_CALL in Dart only.

Replace the follow-up note with section 5, the agent calling renderer
functions as implemented by #3939, #3940 and #3941: RendererFunctionCalls,
its checks and error codes, timeouts, resolve returning whether it owned
the response, malformed responses, disposal, the optional catalog checks,
the in-memory limitation on stateless servers, and the ADK integration.
Requirements, links, conformance (renderer_function_calls.yaml, 23 cases)
and implementation steps follow. The Python agent codebase blueprint says
renderer calls come in the follow-up #3939.

Signed-off-by: Nan Yu <nanyu@google.com>
nan-yu added a commit that referenced this pull request Nov 4, 2026
Audit the agent functions feature blueprint against the Python, TS and Dart
branches and fix the drift:
- The version check runs first for every message kind, so a
  callAgentFunction with a missing or other version raises even with a
  functionCallId; a schema-failing call with a readable id still gets an
  INVALID_FUNCTION_CALL reply in all three SDKs.
- The timeout option is agent_function_timeout (seconds) in Python,
  agentFunctionTimeoutMs in TypeScript and Duration agentFunctionTimeout in
  Dart; the sketch now uses a neutral name.
- The callback signatures per SDK, including Dart's FutureOr<void>
  callbacks that still decline with false.
- Only Python's a2ui.rpc re-exports the message classes; a validation error
  raised by a handler is INVALID_FUNCTION_CALL in Dart only.

Replace the follow-up note with section 5, the agent calling renderer
functions as implemented by #3939, #3940 and #3941: RendererFunctionCalls,
its checks and error codes, timeouts, resolve returning whether it owned
the response, malformed responses, disposal, the optional catalog checks,
the in-memory limitation on stateless servers, and the ADK integration.
Requirements, links, conformance (renderer_function_calls.yaml, 23 cases)
and implementation steps follow. The Python agent codebase blueprint says
renderer calls come in the follow-up #3939.

Signed-off-by: Nan Yu <nanyu@google.com>
@nan-yu
nan-yu force-pushed the feat/ts-renderer-function-calls branch from ad272c1 to a75ec61 Compare November 4, 2026 22:06
nan-yu added a commit that referenced this pull request Nov 4, 2026
Audit the agent functions feature blueprint against the Python, TS and Dart
branches and fix the drift:
- The version check runs first for every message kind, so a
  callAgentFunction with a missing or other version raises even with a
  functionCallId; a schema-failing call with a readable id still gets an
  INVALID_FUNCTION_CALL reply in all three SDKs.
- The timeout option is agent_function_timeout (seconds) in Python,
  agentFunctionTimeoutMs in TypeScript and Duration agentFunctionTimeout in
  Dart; the sketch now uses a neutral name.
- The callback signatures per SDK, including Dart's FutureOr<void>
  callbacks that still decline with false.
- Only Python's a2ui.rpc re-exports the message classes; a validation error
  raised by a handler is INVALID_FUNCTION_CALL in Dart only.

Replace the follow-up note with section 5, the agent calling renderer
functions as implemented by #3939, #3940 and #3941: RendererFunctionCalls,
its checks and error codes, timeouts, resolve returning whether it owned
the response, malformed responses, disposal, the optional catalog checks,
the in-memory limitation on stateless servers, and the ADK integration.
Requirements, links, conformance (renderer_function_calls.yaml, 23 cases)
and implementation steps follow. The Python agent codebase blueprint says
renderer calls come in the follow-up #3939.

Signed-off-by: Nan Yu <nanyu@google.com>
@nan-yu
nan-yu force-pushed the feat/ts-renderer-function-calls branch from a75ec61 to ee83c0d Compare November 4, 2026 22:56
nan-yu added a commit that referenced this pull request Nov 4, 2026
Audit the agent functions feature blueprint against the Python, TS and Dart
branches and fix the drift:
- The version check runs first for every message kind, so a
  callAgentFunction with a missing or other version raises even with a
  functionCallId; a schema-failing call with a readable id still gets an
  INVALID_FUNCTION_CALL reply in all three SDKs.
- The timeout option is agent_function_timeout (seconds) in Python,
  agentFunctionTimeoutMs in TypeScript and Duration agentFunctionTimeout in
  Dart; the sketch now uses a neutral name.
- The callback signatures per SDK, including Dart's FutureOr<void>
  callbacks that still decline with false.
- Only Python's a2ui.rpc re-exports the message classes; a validation error
  raised by a handler is INVALID_FUNCTION_CALL in Dart only.

Replace the follow-up note with section 5, the agent calling renderer
functions as implemented by #3939, #3940 and #3941: RendererFunctionCalls,
its checks and error codes, timeouts, resolve returning whether it owned
the response, malformed responses, disposal, the optional catalog checks,
the in-memory limitation on stateless servers, and the ADK integration.
Requirements, links, conformance (renderer_function_calls.yaml, 23 cases)
and implementation steps follow. The Python agent codebase blueprint says
renderer calls come in the follow-up #3939.

Signed-off-by: Nan Yu <nanyu@google.com>
@nan-yu
nan-yu force-pushed the feat/ts-renderer-function-calls branch from ee83c0d to d0f7198 Compare November 4, 2026 23:18
nan-yu added a commit that referenced this pull request Nov 5, 2026
Audit the agent functions feature blueprint against the Python, TS and Dart
branches and fix the drift:
- The version check runs first for every message kind, so a
  callAgentFunction with a missing or other version raises even with a
  functionCallId; a schema-failing call with a readable id still gets an
  INVALID_FUNCTION_CALL reply in all three SDKs.
- The timeout option is agent_function_timeout (seconds) in Python,
  agentFunctionTimeoutMs in TypeScript and Duration agentFunctionTimeout in
  Dart; the sketch now uses a neutral name.
- The callback signatures per SDK, including Dart's FutureOr<void>
  callbacks that still decline with false.
- Only Python's a2ui.rpc re-exports the message classes; a validation error
  raised by a handler is INVALID_FUNCTION_CALL in Dart only.

Replace the follow-up note with section 5, the agent calling renderer
functions as implemented by #3939, #3940 and #3941: RendererFunctionCalls,
its checks and error codes, timeouts, resolve returning whether it owned
the response, malformed responses, disposal, the optional catalog checks,
the in-memory limitation on stateless servers, and the ADK integration.
Requirements, links, conformance (renderer_function_calls.yaml, 23 cases)
and implementation steps follow. The Python agent codebase blueprint says
renderer calls come in the follow-up #3939.

Signed-off-by: Nan Yu <nanyu@google.com>
@nan-yu
nan-yu force-pushed the feat/ts-renderer-function-calls branch from d0f7198 to 716de18 Compare November 5, 2026 00:21
nan-yu added a commit that referenced this pull request Nov 5, 2026
Audit the agent functions feature blueprint against the Python, TS and Dart
branches and fix the drift:
- The version check runs first for every message kind, so a
  callAgentFunction with a missing or other version raises even with a
  functionCallId; a schema-failing call with a readable id still gets an
  INVALID_FUNCTION_CALL reply in all three SDKs.
- The timeout option is agent_function_timeout (seconds) in Python,
  agentFunctionTimeoutMs in TypeScript and Duration agentFunctionTimeout in
  Dart; the sketch now uses a neutral name.
- The callback signatures per SDK, including Dart's FutureOr<void>
  callbacks that still decline with false.
- Only Python's a2ui.rpc re-exports the message classes; a validation error
  raised by a handler is INVALID_FUNCTION_CALL in Dart only.

Replace the follow-up note with section 5, the agent calling renderer
functions as implemented by #3939, #3940 and #3941: RendererFunctionCalls,
its checks and error codes, timeouts, resolve returning whether it owned
the response, malformed responses, disposal, the optional catalog checks,
the in-memory limitation on stateless servers, and the ADK integration.
Requirements, links, conformance (renderer_function_calls.yaml, 23 cases)
and implementation steps follow. The Python agent codebase blueprint says
renderer calls come in the follow-up #3939.

Signed-off-by: Nan Yu <nanyu@google.com>
@nan-yu
nan-yu force-pushed the feat/ts-renderer-function-calls branch from 716de18 to 4715e54 Compare November 5, 2026 00:39

@gspencergoog gspencergoog 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.

This change adds RendererFunctionCalls to @a2ui/agent (and RpcErrorCode.TOO_MANY_PENDING to @a2ui/web_core) for v1.0 agent-to-renderer function calls (callRendererFunction -> rendererFunctionResponse), complete with pre-flight catalog permission and JSON argument validation, timeouts, cancellation, disposal, and 78 unit tests plus the 30-case conformance runner. Before merging, remove the unused seconds-based DEFAULT_RENDERER_CALL_TIMEOUT = 30.0 constant (which creates a unit-mismatch hazard alongside millisecond-based defaultTimeoutMs and timeoutMs options) and consolidate the ## Unreleased changelog entries with [#3940] pull request links.

🤖 Agent-generated

Comment thread typescript/core/web_core/CHANGELOG.md Resolved
nan-yu added a commit that referenced this pull request Nov 5, 2026
Audit the agent functions feature blueprint against the Python, TS and Dart
branches and fix the drift:
- The version check runs first for every message kind, so a
  callAgentFunction with a missing or other version raises even with a
  functionCallId; a schema-failing call with a readable id still gets an
  INVALID_FUNCTION_CALL reply in all three SDKs.
- The timeout option is agent_function_timeout (seconds) in Python,
  agentFunctionTimeoutMs in TypeScript and Duration agentFunctionTimeout in
  Dart; the sketch now uses a neutral name.
- The callback signatures per SDK, including Dart's FutureOr<void>
  callbacks that still decline with false.
- Only Python's a2ui.rpc re-exports the message classes; a validation error
  raised by a handler is INVALID_FUNCTION_CALL in Dart only.

Replace the follow-up note with section 5, the agent calling renderer
functions as implemented by #3939, #3940 and #3941: RendererFunctionCalls,
its checks and error codes, timeouts, resolve returning whether it owned
the response, malformed responses, disposal, the optional catalog checks,
the in-memory limitation on stateless servers, and the ADK integration.
Requirements, links, conformance (renderer_function_calls.yaml, 23 cases)
and implementation steps follow. The Python agent codebase blueprint says
renderer calls come in the follow-up #3939.

Signed-off-by: Nan Yu <nanyu@google.com>
nan-yu added a commit that referenced this pull request Nov 5, 2026
Remove DEFAULT_RENDERER_CALL_TIMEOUT (30.0, in seconds), which passed to
defaultTimeoutMs or timeoutMs would set a 30 ms timeout; keep
DEFAULT_RENDERER_CALL_TIMEOUT_MS. Consolidate the RendererFunctionCalls
changelog entries into one net entry and link #3940 from it and from
the TOO_MANY_PENDING entry.

Signed-off-by: Nan Yu <nanyu@google.com>
@nan-yu
nan-yu force-pushed the feat/ts-renderer-function-calls branch from 4715e54 to 0bc471e Compare November 5, 2026 18:01
nan-yu added 13 commits November 5, 2026 18:13
…calls conformance test

Signed-off-by: Nan Yu <nanyu@google.com>
The renderer function calls tests wrapped each fake-timer test in
try/finally to restore real timers. An afterEach hook in each describe
does that once, even when an assertion fails.

Signed-off-by: Nan Yu <nanyu@google.com>
… the response

resolve returns true when it settled or failed a pending call and false
when the functionCallId isn't pending (unknown, late or a duplicate).
Used as onRendererFunctionResponse, it so declines the responses it
doesn't own, such as those to calls the model wrote, and they reach the
model.

Signed-off-by: Nan Yu <nanyu@google.com>
RendererFunctionCalls takes an optional catalogs option. With it, call
rejects a call before anything is registered or sent: UNKNOWN_FUNCTION
for a catalog or function the catalogs don't have, INVALID_FUNCTION_CALL
for a function the agent may not call (rendererOnly, allowedCallers
omitted, or requiring user activation). Two catalogs with the same id
are an A2uiCatalogError.

Signed-off-by: Nan Yu <nanyu@google.com>
…cases

The call_renderer_function runner builds each args.catalogs entry as a
v1.0 catalog in code and passes it to RendererFunctionCalls, and a case
with a top-level expect_error checks that building the helper fails.

Signed-off-by: Nan Yu <nanyu@google.com>
…ctions

An agent function in the agent's catalog (for example one built with
AgentFunction.fromApi from a rendererOrAgent declaration) runs on the
agent, so a call to it is rejected with UNKNOWN_FUNCTION.

Signed-off-by: Nan Yu <nanyu@google.com>
… SDKs use

RendererFunctionCalls.call checks the name before the catalogId, rejects
a name starting with @, and checks the args (now including that every
value is a JSON value, recursively, so NaN and Infinity are rejected)
before the catalogs. timeoutMs is a plain optional number: a runtime
null counts as omitted, and only defaultTimeoutMs: null disables
timeouts.

Signed-off-by: Nan Yu <nanyu@google.com>
The call step's args may be any JSON value, such as a list, for the
cases that check args that aren't an object.

Signed-off-by: Nan Yu <nanyu@google.com>
Signed-off-by: Nan Yu <nanyu@google.com>
…rocessor

Signed-off-by: Nan Yu <nanyu@google.com>
Remove DEFAULT_RENDERER_CALL_TIMEOUT (30.0, in seconds), which passed to
defaultTimeoutMs or timeoutMs would set a 30 ms timeout; keep
DEFAULT_RENDERER_CALL_TIMEOUT_MS. Consolidate the RendererFunctionCalls
changelog entries into one net entry and link #3940 from it and from
the TOO_MANY_PENDING entry.

Signed-off-by: Nan Yu <nanyu@google.com>
RendererFunctionCalls.resolve settled a call with its value when the
response also carried error: null. Like the processor's schema and the
Python SDK, a response now needs exactly one of value and error, so
error: null fails the call with UNKNOWN_ERROR; value: null still
settles it with null. Test that a response after dispose settles
nothing.

The renderer call conformance runner checks each expect_error against
its shape: a call step's {code, message?} and a case's
{category: CatalogError, message?}, with no other keys, and matches
message as a literal substring.

Signed-off-by: Nan Yu <nanyu@google.com>
@nan-yu
nan-yu force-pushed the feat/ts-renderer-function-calls branch from 0bc471e to 2e0f52d Compare November 5, 2026 18:13
@nan-yu
nan-yu requested a review from gspencergoog November 5, 2026 18:33

@gspencergoog gspencergoog 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.

This pull request adds RendererFunctionCalls to @a2ui/agent and RpcErrorCode.TOO_MANY_PENDING to @a2ui/web_core to support v1.0 agent-to-renderer function calls (callRendererFunction and rendererFunctionResponse), along with unit and conformance tests, README usage documentation, and changelog entries. All Round 1 review threads have been resolved (DEFAULT_RENDERER_CALL_TIMEOUT removed, changelog entries consolidated with #3940 links, and response validation tightened), and all CI checks pass.

🤖 Agent-generated

This branch has not been deployed

No deployments
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.

2 participants