Skip to content

Python: A2AExecutor: accept forwarded run kwargs from request metadata - #9193

Open
Dineshsuriya D (droideronline) wants to merge 3 commits into
microsoft:mainfrom
droideronline:feature/a2a-executor-prepare-session
Open

Dineshsuriya D (droideronline) wants to merge 3 commits into
microsoft:mainfrom
droideronline:feature/a2a-executor-prepare-session

Conversation

@droideronline

@droideronline Dineshsuriya D (droideronline) commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Motivation & Context

A2AExecutor receives the inbound RequestContext, including context.metadata (SendMessageRequest.metadata), but ignores it, and run_kwargs is fixed at construction. Runtime context a caller passes as function_invocation_kwargs and client_kwargs therefore never reaches the hosted agent, so middleware and tools see different context.kwargs than they would locally. These two kwargs plus session and stream are the whole SupportsAgentRun.run contract.

Description & Review Guide

  • What are the major changes?
    • New A2AExecutor(accepted_kwargs=[...]) option, an allowlist of key names.
    • execute() reads SendMessageRequest.metadata["agent_framework"] (written by A2AAgent(forwarded_kwargs=...) in Python: A2AAgent: forward selected run kwargs in request metadata #9192), keeps only the allowed keys of function_invocation_kwargs and client_kwargs, and passes them to agent.run(...) in both streaming and non-streaming mode.
  • What is the impact of these changes?
    • Not breaking. The default (None) accepts nothing, so behavior is unchanged.
    • The values come from a remote caller, so only allowlisted keys are accepted. Keys configured in run_kwargs win on conflict, framework-owned names such as stream, messages, options, session and middleware (and underscore-prefixed names) are rejected with ValueError at construction, and missing or malformed metadata is ignored.
    • _run and _run_stream take an optional run_kwargs argument that defaults to the configured kwargs, so existing callers are unaffected.
  • What do you want reviewers to focus on?
    • The precedence and reserved-key rules.
    • The wire key agent_framework, which is defined separately in the client PR so the two PRs stay independent.

Client side: #7973 and #9192.

Related Issue

Fixes #9191

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@agent-framework-automation agent-framework-automation Bot added the python Usage: [Issues, PRs], Target: Python label Oct 8, 2026
@droideronline Dineshsuriya D (droideronline) changed the title Python: A2AExecutor: add prepare_session hook Python: A2AExecutor: accept forwarded run kwargs from request metadata Oct 8, 2026
@droideronline

Copy link
Copy Markdown
Contributor Author

Eduard van Valkenburg (@eavanvalkenburg) Evan Mattson (@moonbox3) - I would appreciate if you could take a look at this one and #9192 when you get a chance, we are in need for these two. thanks!

@eavanvalkenburg

Copy link
Copy Markdown
Member

/review

@github-actions github-actions 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.

MAF Automated Review — Iteration 1

Result: Findings reported
Scope: full PR (2 commit(s)): 0dcc5a5a6be5, 243b12d994b1
Model: gpt-5.6-sol

Overview

The PR adds a default-off, allowlist-gated path for forwarding selected request metadata into agent run kwargs, with server-configured values taking precedence and malformed metadata ignored. The fresh per-request merge, explicit reserved keys, and streaming/non-streaming tests provide useful guardrails. One residual collision remains: because one allowlist governs both forwarded destinations, a remote caller can place an allowed framework-owned name in client_kwargs and reliably fail the task.

Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
1 verified finding remained after source verification (1 medium) across 1 file. Details are attached to the affected lines below.

Affected areas: python/packages/a2a/agent_framework_a2a/_a2a_executor.py

AGENT_FRAMEWORK_METADATA_KEY = "agent_framework"
_FORWARDED_KWARGS_NAMES = ("function_invocation_kwargs", "client_kwargs")
# Framework-managed keys that a remote caller can never set.
_RESERVED_KWARGS = frozenset({"session", "middleware"})

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.

Because this allowlist applies to both forwarded maps, allowing stream (for example, as a tool-context key) also lets the remote caller put stream in client_kwargs. ChatClientBase.get_response() later calls _inner_get_response(stream=..., **client_kwargs), so the duplicate keyword raises TypeError and fails the A2A task. Please scope accepted keys per destination or reject client-kwarg names that collide with framework-owned parameters such as messages, stream, and options.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in the latest commit. Rather than scoping per destination, A2AExecutor now rejects framework-owned names (stream, messages, options, session, middleware, compaction_strategy, tokenizer, function_invocation_kwargs, client_kwargs) and underscore-prefixed names in accepted_kwargs with a ValueError at construction. A caller can then never inject a colliding keyword. Tests cover each reserved name.

Add an overridable hook called after the session is created and before the agent runs so applications can initialize session state from the inbound request.
Replace the prepare_session hook with opt-in acceptance of selected function_invocation_kwargs and client_kwargs keys read from the agent_framework key of SendMessageRequest.metadata.
Fail fast at construction when accepted_kwargs contains a name the framework owns (stream, messages, options, session, middleware and similar) or an underscore-prefixed name, so a remote caller cannot cause duplicate keyword errors.

This branch was successfully deployed

1 active deployment
github-app-auth — 235184cb Deployed Oct 9, 2026 by droideronline via add_label #24900
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: A2AExecutor: accept forwarded run kwargs from request metadata

3 participants