Skip to content

feat: add state bag and ServerCallContextBuilder to ServerCallContext#364

Open
ikubicki wants to merge 2 commits intoa2aproject:mainfrom
ikubicki:feat/server-call-context-engancements
Open

feat: add state bag and ServerCallContextBuilder to ServerCallContext#364
ikubicki wants to merge 2 commits intoa2aproject:mainfrom
ikubicki:feat/server-call-context-engancements

Conversation

@ikubicki
Copy link
Copy Markdown

@ikubicki ikubicki commented Mar 19, 2026

Description

Motivation

The Python A2A SDK exposes a state property
on ServerCallContext
— an arbitrary MutableMapping[str, Any] used to pass metadata through the call pipeline.
The Python app layer actively uses it (e.g.
call_context.state['method'] = method),
and op-SDK implementations rely on it to carry request-scoped data such as tenant IDs,
auth tokens, or raw headers.

The TypeScript SDK was missing this capability, making it impossible to faithfully port
Python-based agent implementations to TypeScript without architectural workarounds.

Changes

ServerCallContext

  • Added a state property — a Map<string, unknown> key/value bag, directly mirroring
    Python's state: MutableMapping[str, Any].
  • Added withRequestedExtensions() method that returns a new context with updated extensions
    while preserving user, state, and activatedExtensions.
  • Extended the constructor to accept an optional state map.

ServerCallContextBuilder

  • Added ServerCallContextBuilder factory function type, mirroring Python's abstract
    CallContextBuilder.build(request) pattern.
  • Added defaultServerCallContextBuilder — the default implementation that pre-populates
    state with raw request headers under the headers key, mirroring Python's
    DefaultCallContextBuilder.
  • Added STATE_HEADERS_KEY constant for the headers key.
  • Added RequestHeaders type — transport-agnostic representation of request headers.

Express handlers (jsonRpcHandler, restHandler)

  • Added optional contextBuilder?: ServerCallContextBuilder to JsonRpcHandlerOptions
    and RestHandlerOptions, falling back to defaultServerCallContextBuilder.
  • Both handlers now pass raw req.headers into the context builder.

gRPC handler

  • Updated grpc_service.ts to pass request metadata as headers into the context builder.

Exports

  • ServerCallContextBuilder, RequestHeaders, defaultServerCallContextBuilder,
    and STATE_HEADERS_KEY are now exported from @a2a-js/sdk/server.

Tests & samples

  • Added unit tests for the new ServerCallContext API in test/server/context.spec.ts.
  • Added src/samples/authentication/server_call_context.ts demonstrating custom context usage.

Impact

This change enables direct migration of Python A2A agent implementations to TypeScript —
any code relying on context.state in the Python SDK will have a direct equivalent in the
TypeScript SDK with the same semantics.

Checklist

@ikubicki ikubicki requested a review from a team as a code owner March 19, 2026 14:53
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a state bag to the TypeScript A2A SDK's ServerCallContext, enabling the passing of request-scoped metadata throughout the call pipeline. This change directly addresses a capability gap compared to the Python A2A SDK, allowing for a more faithful and straightforward migration of Python-based agent implementations to TypeScript by providing an equivalent mechanism for handling data like tenant IDs or auth tokens. It provides flexibility for custom context creation and ensures header information is readily available.

Highlights

  • ServerCallContext Enhanced: Introduced a state property (a Map<string, unknown>) to ServerCallContext for passing arbitrary request-scoped metadata, directly mirroring the Python SDK's state functionality.
  • Context Builder Introduced: Added a ServerCallContextBuilder type and a defaultServerCallContextBuilder function to allow for custom context creation and pre-population of the state bag with raw request headers.
  • Handler Integration: Express (jsonRpcHandler, restHandler) and gRPC handlers were updated to accept an optional contextBuilder and now pass raw request headers (or gRPC metadata converted to headers) to it for context creation.
  • New Sample and Tests: Included a new sample demonstrating custom context usage for reading request headers and added comprehensive unit tests for the new ServerCallContext API and defaultServerCallContextBuilder.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 19, 2026

🧪 Code Coverage

⬇️ Download Full Report

Base PR Delta
src/server/express/json_rpc_handler.ts 90.62% 91% 🟢 +0.38%
src/server/express/rest_handler.ts 85.6% 85.71% 🟢 +0.11%
src/server/grpc/grpc_service.ts 68.78% 69.08% 🟢 +0.30%
src/server/request_handler/default_request_handler.ts 79.69% 79.65% 🔴 -0.04%
Total 81.12% 81.23% 🟢 +0.11%

Generated by coverage-comment.yml

Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

Code Review

The pull request introduces a state property to ServerCallContext and a ServerCallContextBuilder pattern, effectively mirroring the Python A2A SDK's capabilities. The implementation is robust, including a default builder that populates request headers into the state, and a withRequestedExtensions method that correctly handles context immutability. The changes are well-integrated into existing Express and gRPC handlers, and the new sample and comprehensive unit tests demonstrate and validate the new functionality. The code quality is high, and the changes align perfectly with the stated motivation and objectives.

@ikubicki ikubicki force-pushed the feat/server-call-context-engancements branch from 87c04bd to 1a25ae6 Compare March 21, 2026 22:46
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.

1 participant