Skip to content

feat: handle tenant in a2aclient and a2asrv#237

Merged
yarolegovich merged 15 commits intorelease/spec-v1from
yarolegovich/handle-tenant-client
Feb 27, 2026
Merged

feat: handle tenant in a2aclient and a2asrv#237
yarolegovich merged 15 commits intorelease/spec-v1from
yarolegovich/handle-tenant-client

Conversation

@yarolegovich
Copy link
Copy Markdown
Member

@yarolegovich yarolegovich commented Feb 24, 2026

  • If tenant is specified on AgentInterface and not provided in requests a2aclient will be attaching it to request automatically.
  • Rest client transport prepends path with tenant if provided.
  • Added a2asrv.NewTenantRESTHandler which takes a prefix template which it strips and injects the part captured by {} into the regular REST handler.
  • InterceptedRequestHandler takes tenant from the request to set it on a2asrv.CallContext.
  • Tenant also gets set on a2asrv.ExecutorContext (previously known as RequestContext).

nahapetyan-serob and others added 8 commits February 3, 2026 15:08
The spec was unspecified, so the implementation restricts task
continuation to TaskStateInputRequired. However, TCK tests expect
continuation for any non-terminal state. Added an interceptor to the SUT
agent so 2 of TCK tests would pass.
# Description

This PR fixes typos across code comments. No functional changes.

## Changes

| File | Before | After |
|---|---|---|
| `a2a/core.go` | `TastState defines a set of...` | `TaskState defines a
set of...` |
| `a2aclient/doc.go` | `agentcard.DefaultResolved.Resolve` |
`agentcard.DefaultResolver.Resolve` |
| `a2aclient/agentcard/doc.go` | `but custom this can be configured` |
`but this can be customized` |

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Pure plumbing - no new business logic. Each layer gets the obvious
`ListTasks` method that delegates to the next:

- `Transport` interface + `unimplementedTransport` stub
- JSON-RPC client: sends `tasks/list`, unmarshals `ListTasksResponse`
- JSON-RPC server: dispatches `tasks/list` to `onListTasks`
- gRPC client: converts via pbconv, calls proto `ListTasks`
- `RequestHandler` interface + default impl delegates to
`taskStore.List()`
- `InterceptedHandler`: wraps with before/after interceptors
- `MethodTasksList` constant added

Release-As: 0.3.7
we rely on optimistic concurrency control to propagate cancelation
signal in distributed deployments.
if a task gets cancelled the next task update fails and stops execution.
in case of cancelations OCC also applies, but this also makes
cancelations fragile, especially when execution generates events rapidly
the solution for now is to provide a built-in retry mechanism on task
update level where in cases of concurrent modification task status
update to failed is going to be retried up to a max number of attempts
🤖 I have created a release *beep* *boop*
---


## [0.3.7](v0.3.6...v0.3.7)
(2026-02-20)


### Features

* implement tasks/list RPC
([#210](#210))
([6e04698](6e04698))
* retry cancelations
([#222](#222))
([3057474](3057474))


### Bug Fixes

* handle internal error: tck failure
([#186](#186))
([b55fbfd](b55fbfd))
* **sse:** support data: prefix without space
([#188](#188))
([6657a6d](6657a6d)),
closes [#162](#162)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @yarolegovich, 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 comprehensive multi-tenancy support across both the a2aclient and a2asrv components. On the client side, it enables automatic inclusion of tenant identifiers in requests, while on the server side, it provides middleware to extract tenant information from incoming request paths and ensures this data is consistently available throughout the request lifecycle via context objects. This enhancement allows for better isolation and management of resources for different tenants.

Highlights

  • Client-side Tenant Handling: The a2aclient now automatically attaches tenant information from the AgentInterface to outgoing requests if a tenant is specified. This is facilitated by a new tenantTransportDecorator.
  • REST Client Path Modification: The a2aclient's REST transport has been updated to prepend the tenant ID to the request URL path when a tenant is present, ensuring tenant-specific routing.
  • Server-side Tenant Extraction Middleware: A new a2asrv.StripTenant HTTP middleware was introduced. It extracts tenant information from the URL path based on a configurable template, strips the tenant prefix from the URL, and injects the tenant ID into the request's context.Context.
  • Tenant Context Propagation: Tenant information is now consistently propagated throughout the a2asrv components, including a2asrv.CallContext (used by interceptors) and a2asrv.ExecutorContext (for task execution), ensuring tenant-aware processing at various stages.
  • New Path Templating Utility: A new internal pathtemplate package was added to provide a flexible mechanism for parsing and matching URI path templates with capture groups, which is utilized by the StripTenant middleware.
Changelog
  • a2aclient/factory.go
    • Added tenantTransportDecorator to wrap the transport if a tenant is specified in the endpoint.
  • a2aclient/factory_test.go
    • Added TestFactory_Tenant to verify that the factory correctly applies the tenantTransportDecorator.
  • a2aclient/jsonrpc_test.go
    • Added TestJSONRPCTransport_Tenant to test tenant propagation in JSONRPC requests.
  • a2aclient/rest.go
    • Introduced restRequest struct to centralize HTTP request parameters, including tenant information.
    • Modified sendRequest to use the new restRequest struct and to prepend the tenant to the URL path.
    • Updated doRequest and doStreamingRequest to accept the restRequest struct.
    • Modified all REST client methods to construct and pass restRequest objects, including tenant data.
  • a2aclient/rest_test.go
    • Added TestRESTTransport_Tenant to verify tenant-aware URL path construction in REST transport.
  • a2aclient/transport.go
    • Defined tenantTransportDecorator to inject tenant IDs into request objects for all transport methods.
  • a2asrv/agentexec.go
    • Updated CreateExecutor and CreateCanceler to set the tenant in ExecutorContext from the CallContext.
    • Modified loadExecutionContext to include tenant information in the ExecutorContext.
  • a2asrv/handler.go
    • Added a check for an empty ID in CancelTask requests to return ErrInvalidParams.
  • a2asrv/handler_test.go
    • Updated a test case for CancelTask to pass an empty a2a.CancelTaskRequest{} instead of nil.
  • a2asrv/intercepted_handler.go
    • Modified attachMethodCallContext to accept and set tenant information in the CallContext.
    • Updated all InterceptedHandler methods to pass the request's tenant to attachMethodCallContext.
  • a2asrv/middleware.go
    • Added a tenant field to CallContext and a Tenant() getter method.
    • Introduced AttachTenant and TenantFromContext functions for context-based tenant management.
  • a2asrv/reqctx.go
    • Added a Tenant field to the ExecutorContext struct.
  • a2asrv/rest.go
    • Added fillTenant helper function to populate tenant from context if not already present in the request.
    • Integrated fillTenant into various REST handlers to ensure tenant information is correctly set on incoming requests.
  • a2asrv/tenant.go
    • Added new file a2asrv/tenant.go.
    • Implemented StripTenant HTTP middleware to extract tenant IDs from URL paths and attach them to the request context.
  • a2asrv/tenant_test.go
    • Added new file a2asrv/tenant_test.go.
    • Added tests for the StripTenant middleware with various path templates and scenarios.
  • internal/pathtemplate/pathtemplate.go
    • Added new file internal/pathtemplate/pathtemplate.go.
    • Implemented a Template struct and New and Match methods for parsing and matching URI path templates with capture groups.
  • internal/pathtemplate/pathtemplate_test.go
    • Added new file internal/pathtemplate/pathtemplate_test.go.
    • Added tests for the pathtemplate package, covering template creation and path matching.
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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

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.

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

This pull request introduces tenant handling across a2aclient and a2asrv. The client-side changes involve a decorator to inject the tenant into requests, and REST transport modifications to prepend the tenant to the URL path. The server-side changes add a StripTenant middleware to extract the tenant from the URL and propagate it through the context to handlers and executors. The changes are comprehensive and well-structured.

My review identified several critical issues regarding potential nil pointer dereferences in a2asrv/intercepted_handler.go due to removed nil checks. I've also found a high-severity bug in a2asrv/agentexec.go where tenant information could be incorrectly overwritten. Additionally, there's a performance improvement opportunity in a2aclient/rest.go and a style guide violation regarding a stale TODO comment in a2asrv/rest.go. All identified issues are detailed in the comments below, with suggestions provided where applicable.

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.

nit: we might change the file name as it is representing ExecutorContext now (not RequestContext)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

will fix on merge of the next pr to avoid merge conflicts

@yarolegovich yarolegovich merged commit 398d902 into release/spec-v1 Feb 27, 2026
4 checks passed
@yarolegovich yarolegovich deleted the yarolegovich/handle-tenant-client branch February 27, 2026 12:10
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.

6 participants