Skip to content

docs: add A2A protocol support design document - #1114

Merged
david-martin merged 42 commits into
Kuadrant:mainfrom
Aman-Cool:feat/a2a-design-doc
Aug 4, 2026
Merged

docs: add A2A protocol support design document#1114
david-martin merged 42 commits into
Kuadrant:mainfrom
Aman-Cool:feat/a2a-design-doc

Conversation

@Aman-Cool

@Aman-Cool Aman-Cool commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Design proposal for A2A protocol support in the MCP Gateway, refs #766 ; this document describes the full direction; agent registration and discovery, path-per-agent routing through ext_proc, and per-principal task ownership.., and, following review, an implementation-phases section that lands it incrementally behind an experimental --enable-a2a router flag, default off, with any new APIs alpha.

Phase 1 is the slice we've agreed to build first (#1333): router-only passthrough for auditing, auth and observability. The router strips inbound x-a2a-* headers, parses /a2a POST bodies envelope-only, and sets x-a2a-method and x-a2a-agent (the agent identity being the first path segment after /a2a/, a documented convention since the A2A body names no agent) ; unparseable POSTs fail closed, GETs pass through, users hand-author their agent HTTPRoutes, and the headers feed Istio Telemetry and AuthPolicy with no further gateway code. Registration/discovery and task ownership follow as phases 2 and 3; kept as the direction we're cutting from rather than a commitment, gated on where A2A support lands long-term and on the broker settling after the MCP spec-version work.

A few design positions worth calling out for review context: signed v1.0 AgentCards are served verbatim (a URL rewrite breaks the JWS over the JCS-canonicalized card), with the catalog advertising gateway paths alongside rather than inside the card ; task IDs are agent-assigned and pass through unchanged; routing is by path, so the gateway never mints or rewrites them, and ownership is an insert-only (agent, taskID) -> principal record that fails closed on any miss or mismatch ; and A2A authenticates per-request via OAuth bearer with ownership scoped to the principal, so it is untouched by MCP's stateless changes. The doc's decisions have been exercised end-to-end in a working prototype; discovery, routing and streaming passthrough against a live gateway; so the phases start from validated ground rather than paper.

All review feedback to date is incorporated and the open markers are resolved ; the discovery convention (RFC 9727 catalog vs the emerging AI Catalog) is deliberately held loose until phase 2 ships a catalog at all. Happy to adjust anything that would make this easier to build against as phase 1 lands.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

PR adds A2A design, E2E test, and implementation-plan documents for discovery, path-based routing, gateway task-ID mapping, streaming rewrite behavior, CRD/config/security details, and phased implementation tasks.

Changes

A2A Protocol Design and Implementation Planning

Layer / File(s) Summary
Design problem, goals, and job stories
docs/design/a2a/a2a-design.md
Introduces A2A delegation scope, explicit goals and non-goals, job stories for registration and task flows, and gateway prerequisites including upstream version and authentication assumptions.
End-to-end flows and architecture
docs/design/a2a/a2a-design.md
Documents discovery via the API catalog and agent cards, message/send and message/stream routing, tasks/get and tasks/cancel resolution, task lifecycle behavior, and the corresponding controller, broker, router, and HTTPRoute responsibilities.
CRD, task storage, security, and compatibility
docs/design/a2a/a2a-design.md
Defines the A2AAgentRegistration CRD, task-route storage and persistence details, internal router headers, authentication and ownership checks, header stripping, credential isolation, collision handling, rollback behavior, and future considerations.
E2E test case specifications
docs/design/a2a/tasks/e2e_test_cases.md
Defines discovery, routing, streaming, deregistration, multi-agent isolation, security, and MCP regression test cases for A2A behavior.
Phased 15-task implementation plan
docs/design/a2a/tasks/tasks.md
Outlines the existing-code analysis and the phased implementation tasks for design review, test server, CRD finalization, reconciler work, config hot-reload, broker wiring, router detection, request routing, task mapping, and SSE passthrough.
Spell check word list
project-words.txt
Adds A2A-related terms to the project dictionary.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Possibly related issues

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding a design document for A2A protocol support.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
@Aman-Cool
Aman-Cool force-pushed the feat/a2a-design-doc branch from 9a21ac3 to 399eb7a Compare June 10, 2026 01:24
@coderabbitai coderabbitai Bot added the review-effort/small Low review effort (1-2): straightforward, single file, config/docs label Jun 10, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
docs/design/a2a/tasks/tasks.md (1)

401-401: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add newline at end of file.

File must end with a newline per coding guidelines.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/a2a/tasks/tasks.md` at line 401, Add a final newline character at
the end of docs/design/a2a/tasks/tasks.md so the file ends with a newline per
repository coding guidelines; simply edit the file and ensure the last line is
terminated with a newline (save the file so the trailing newline is present).

Source: Coding guidelines

docs/design/a2a/tasks/e2e_test_cases.md (1)

102-102: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add newline at end of file.

File must end with a newline per coding guidelines.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/a2a/tasks/e2e_test_cases.md` at line 102, The file
e2e_test_cases.md is missing a trailing newline; add a single newline character
at the end of the file so the file ends with a newline (ensure the editor saves
the file with a newline at EOF).

Source: Coding guidelines

🧹 Nitpick comments (1)
docs/design/a2a/a2a-design.md (1)

318-319: ⚖️ Poor tradeoff

Consider cleanup strategy for terminal-state task routes.

TaskRoutes persist until session expiry (matching JWT TTL) even after tasks reach terminal states (completed, failed, canceled, rejected per line 198-201). For long-lived sessions with high task volume, this could accumulate unnecessary entries. Consider adding explicit cleanup on terminal state transitions, or document this as an acceptable tradeoff.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/a2a/a2a-design.md` around lines 318 - 319, TaskRoutes are
currently kept until the JWT TTL via the Redis key pattern
a2atask:{gatewayTaskID} using JWTManager.GetExpiresIn(gatewaySessionID); add
explicit cleanup on task terminal-state transitions (completed, failed,
canceled, rejected) by removing the Redis key or resetting its TTL to a short
value in the task state transition handler (the function that processes task
state changes / terminal-state events), or alternatively document this tradeoff;
update the code paths that write/refresh a2atask:{gatewayTaskID} (and any
task-route creation helpers) to perform the delete/TTL-update when the
TaskRoutes reach a terminal state so entries don’t accumulate for long-lived
sessions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/a2a/a2a-design.md`:
- Line 64: The document uses mixed British and American spelling—specifically
the word "initialises" (UK) appears while "initialize" (US) is used elsewhere;
standardize to a single variant by replacing all occurrences of "initialises"
with "initialize" across the document (search for the token "initialises" and
update it), and run a quick grep for other UK/US pairs to ensure consistency
(e.g., "initialise"/"initialize") so the term is consistent with the existing
"initialize" usage.
- Line 404: This file ends with the line "See
[`tasks/e2e_test_cases.md`](tasks/e2e_test_cases.md) for E2E test case
definitions." but is missing a trailing newline; open the corresponding markdown
file and add a single newline character after that final line so the file
terminates with a newline (configure your editor to trim/ensure final newline on
save if needed).

---

Outside diff comments:
In `@docs/design/a2a/tasks/e2e_test_cases.md`:
- Line 102: The file e2e_test_cases.md is missing a trailing newline; add a
single newline character at the end of the file so the file ends with a newline
(ensure the editor saves the file with a newline at EOF).

In `@docs/design/a2a/tasks/tasks.md`:
- Line 401: Add a final newline character at the end of
docs/design/a2a/tasks/tasks.md so the file ends with a newline per repository
coding guidelines; simply edit the file and ensure the last line is terminated
with a newline (save the file so the trailing newline is present).

---

Nitpick comments:
In `@docs/design/a2a/a2a-design.md`:
- Around line 318-319: TaskRoutes are currently kept until the JWT TTL via the
Redis key pattern a2atask:{gatewayTaskID} using
JWTManager.GetExpiresIn(gatewaySessionID); add explicit cleanup on task
terminal-state transitions (completed, failed, canceled, rejected) by removing
the Redis key or resetting its TTL to a short value in the task state transition
handler (the function that processes task state changes / terminal-state
events), or alternatively document this tradeoff; update the code paths that
write/refresh a2atask:{gatewayTaskID} (and any task-route creation helpers) to
perform the delete/TTL-update when the TaskRoutes reach a terminal state so
entries don’t accumulate for long-lived sessions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0cf24eff-430d-4ff6-80af-26be8ffb65b3

📥 Commits

Reviewing files that changed from the base of the PR and between 5ce1295 and 399eb7a.

📒 Files selected for processing (3)
  • docs/design/a2a/a2a-design.md
  • docs/design/a2a/tasks/e2e_test_cases.md
  • docs/design/a2a/tasks/tasks.md

Comment thread docs/design/a2a/a2a-design.md Outdated
Comment thread docs/design/a2a/a2a-design.md
… design

Correct ImmediateResponse to BodyResponse in message/send sequence diagram,
add missing non-streaming ResponseHeaders/ResponseBody phases with ModeOverride
BUFFERED and StoreTaskRoute, expand tasks/get diagram to show full request and
response body rewriting, fix StoreTaskRoute timing in state machine note,
rewrite Router component responsibilities to split behaviour by ext_proc phase,
add Auth field to A2AAgent config struct, fix COW note in TaskStore section,
replace validating webhook claim with controller-level prefix conflict detection,
and add a2a-task-routing-infra interface incompatibility note to Task 11.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
@Aman-Cool
Aman-Cool force-pushed the feat/a2a-design-doc branch from c88f6da to ddfacc1 Compare June 10, 2026 09:11
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
@Aman-Cool

Copy link
Copy Markdown
Collaborator Author

Hey @david-martin, @jasonmadigan and @maleck13,

Did some digging on Q2 (which spec version to target) since this blocks the test server work; turns out the spec has moved more than I expected, so wanted to lay out what I found.

There are effectively three versions in the wild right now:

  • v0.2.x : what this design doc currently assumes. Methods are message/send, tasks/get, tasks/cancel, agent card at /.well-known/agent.json.
  • v0.3.0 : same method names, but the agent card moved to /.well-known/agent-card.json. That path change was breaking enough that there are open issues on google/adk-python about clients failing after the upgrade, and the general guidance that emerged is to serve both paths.
  • v1.0 (Linux Foundation, early this year) : bigger shift. Methods got renamed entirely (message/sendSendMessage, tasks/get -> GetTask, tasks/resubscribe -> SubscribeToTask, plus a new ListTasks), agent cards can be signed, and there's an A2A-Version header for negotiation.

My suggestion: target v0.3.0 for this term. Every method name in the design doc and the routing logic stays valid; the only real change is serving the card at agent-card.json (with agent.json kept as a legacy alias, which costs us one extra mux line). v1.0 would mean renaming every method constant, dealing with card signing, and version negotiation; feels like a lot of surface for a prototype, and the v0.3 -> v1.0 migration would be a well-scoped follow-up once the architecture is proven.

One wrinkle worth flagging: the official Go SDK (a2aproject/a2a-go/v2) only speaks v1.0 now, so for the test server I'd hand-roll the JSON-RPC handling rather than pull in the SDK; which honestly suits us better anyway, since the e2e tests need the server to produce controlled edge cases (SSE chunks split mid-JSON, keepalives, etc.) that an SDK would abstract away.

If this sounds reasonable I'll update the doc to reflect v0.3.0 + the dual card path and get moving on the test server.

@Aman-Cool

Copy link
Copy Markdown
Collaborator Author

Design conformance issue found during Week 2 prep: message/send has no skill parameter

(Cross-posting from the Slack group so the decision is tracked here.)

While going through the A2A v0.3.0 spec line by line to build the test server, I found that the protocol has no skill parameter in message/send. [MessageSendParams](https://a2a-protocol.org/v0.3.0/specification/#711-messagesendparams-object) is {message, configuration, metadata} ; skills exist only in the Agent Card for discovery. The protocol never routes by skill; a client sends message parts and the receiving agent decides what to do with them.

This design doc currently assumes skill-based dispatch in three places:

  • The message/send flow diagrams (GetAgentInfo("weather_forecast") extracted from the request)
  • The "agent sends a long-running task" job story ("using a skill prefix to identify the target agent")
  • The e2e test cases ("message/send with a skill that matches a registered agent's prefix")

Standard A2A clients will never send that field. It also explains why [agentgateway](https://agentgateway.dev/docs/standalone/main/tutorials/a2a/) (Linux Foundation) does one-route-per-agent rather than skill dispatch; the protocol doesn't support it.

Options

  1. Gateway convention via params.metadata.skill : metadata is an open {[key: string]: any} map designed for extensions, so this is legal. Keeps the single /a2a endpoint and the federated card as designed. Downside: only gateway-aware clients can route; off-the-shelf A2A clients can't use the gateway for first messages.

  2. Path-per-agent: /a2a/{prefix} : each registered agent gets a path segment; the router routes on path alone at the headers phase. Any unmodified A2A client works. The federated card becomes a discovery directory and each agent keeps its own card at its own path. This simplifies the router significantly, and the gateway-owned task ID mapping stays for the ID-isolation security goal.

  3. Hybrid : multi-turn messages already carry message.taskId, so continuations route via the task store; only first messages need agent selection (via path or metadata).

Recommendation

Option 2. It matches how the rest of the ecosystem solved this, works with unmodified clients, and removes complexity from the router rather than adding it. The skill-prefix federation idea survives in the discovery layer; just not in invocation routing.

Impact on current work

Not blocked: the test server's agent card, tasks/get, tasks/cancel, and SSE streaming are unaffected, so I'm building those now. The message/send routing handler and the corresponding design doc sections wait for this decision. Once decided, I'll update the flow diagrams, job stories, and e2e cases in this PR to match.

Replace skill-dispatch routing with path-per-agent: each registered A2A agent
is accessible at /a2a/{prefix} and its card at /a2a/{prefix}/.well-known/agent.json.
Multi-agent discovery moves to /.well-known/api-catalog (RFC 9264) instead of a
merged agent.json. Agent lookup moves to RequestHeaders phase (GetAgentByPrefix)
instead of RequestBody. Resolves open questions Q1 (mcp.kuadrant.io API group)
and Q2 (A2A v0.3.0). Updates flow diagrams, component responsibilities, CRD
example, security section, tasks, and e2e test cases throughout.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
@coderabbitai coderabbitai Bot added review-effort/medium Medium review effort (3): few files, moderate logic and removed review-effort/small Low review effort (1-2): straightforward, single file, config/docs labels Jun 13, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/design/a2a/tasks/e2e_test_cases.md (1)

8-101: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Normalize the case heading level.

These test cases jump from the file title (#) straight to ###, which triggers the markdownlint heading-increment warning. Use ## for the case headings (and keep the same level for the rest of the cases). As per coding guidelines, this doc should stay aligned with the repo’s e2e test-case format; markdownlint also flags the h1→h3 jump here.

Proposed fix
-### [Happy,A2A] API Catalog lists registered agents and per-agent card returns correct skills
+## [Happy,A2A] API Catalog lists registered agents and per-agent card returns correct skills
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/a2a/tasks/e2e_test_cases.md` around lines 8 - 101, The heading
levels jump from the file title ("#") to "###" which triggers markdownlint;
update all test-case headings like "### [Happy,A2A] API Catalog lists registered
agents and per-agent card returns correct skills" (and every other "### ..."
entry) to use "##" instead, keeping the rest of the subheadings unchanged so the
document matches the repo e2e test-case format and resolves the
heading-increment warning.

Sources: Coding guidelines, Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/a2a/a2a-design.md`:
- Around line 177-183: The final diagram line incorrectly shows the last SSE
chunk as "Upstream-->>Client" bypassing Envoy and Router; update the diagram so
the final hop follows the same path as earlier chunks (Upstream → Envoy → Router
→ Client) and ensure the narrative references the a2aSSEPassthrough.Process()
behavior and StoreTaskRoute(gatewayTaskID, TaskRoute{serverName,
"upstream-abc"}) semantics — i.e., replace the terminal "Upstream-->>Client"
with "Upstream-->>Envoy", then "Envoy->>Router: ProcessingRequest_ResponseBody",
and "Router-->>Client: data: {\"result\": {\"id\": \"gateway-123\", ...}}" so
the flow remains consistent with the replacement of "upstream-abc" →
"gateway-123".
- Line 239: Update the ExtProcServer router contract documentation to remove any
mention of the `message/stream` method and instead describe streaming as
negotiated via `Accept: text/event-stream` on `message/send`; specifically edit
the RequestHeaders section (where `message/send`/`message/stream` is referenced)
to only reference `message/send` and the agent-prefix lookup via
A2ABroker.GetAgentByPrefix(), keep gateway task ID generation and header sets
(`:authority`, `x-a2a-agent`, `x-a2a-task-id`) unchanged, adjust any
RequestBody/ResponseHeaders/ResponseBody text that mentions `message/stream` to
describe streaming behavior as `message/send` + SSE negotiation, and update the
a2aSSEPassthrough.Process() description to say it handles streaming for
`message/send` negotiated via Accept: text/event-stream while keeping references
to ResolveTaskRoute() and StoreTaskRoute().

---

Outside diff comments:
In `@docs/design/a2a/tasks/e2e_test_cases.md`:
- Around line 8-101: The heading levels jump from the file title ("#") to "###"
which triggers markdownlint; update all test-case headings like "### [Happy,A2A]
API Catalog lists registered agents and per-agent card returns correct skills"
(and every other "### ..." entry) to use "##" instead, keeping the rest of the
subheadings unchanged so the document matches the repo e2e test-case format and
resolves the heading-increment warning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4defcd30-a0f3-4995-bc34-1a4f559c29e1

📥 Commits

Reviewing files that changed from the base of the PR and between 399eb7a and b89d4b0.

📒 Files selected for processing (3)
  • docs/design/a2a/a2a-design.md
  • docs/design/a2a/tasks/e2e_test_cases.md
  • docs/design/a2a/tasks/tasks.md
✅ Files skipped from review due to trivial changes (1)
  • docs/design/a2a/tasks/tasks.md

Comment thread docs/design/a2a/a2a-design.md Outdated
Comment thread docs/design/a2a/a2a-design.md Outdated
@Aman-Cool

Copy link
Copy Markdown
Collaborator Author

Pushed an update to the design doc based on some spec research I did this week; wanted to share what I found and get your thoughts before moving forward.

The main thing: while going through the A2A v0.3.0 spec more carefully, I noticed that message/send has no skill parameter. MessageSendParams is just {message, configuration, metadata}; skills only appear in the AgentCard for discovery. So the original routing approach in the draft (extracting a skill from the request body) wouldn't actually work with a spec-compliant client.

Given that, I looked at a few options and updated the doc toward path-per-agent (/a2a/{prefix}) since it seemed like the cleanest fit; it's also what agentgateway does. For discovery I went with /.well-known/api-catalog (RFC 9264) instead of a merged agent.json. But I'm not certain either of these is the right call and would really value your input before this gets locked in.

Also took a first pass at Q1 (CRD group -> mcp.kuadrant.io) and Q2 (v0.3.0) based on what felt consistent with the rest of the codebase, but happy to revisit both.

Q4 (session handling) I've left open : planning to bring that to the Week 8 sync as originally discussed.

@david-martin, @jasonmadigan and @maleck13, What do you think? Anything I should reconsider or approach differently?

…ract

SSE final chunk was shown going directly Upstream→Client, skipping
Envoy and Router. All SSE chunks including the terminal one must flow
through the full ext_proc path. Also removes message/stream from the
router component description — streaming is negotiated via Accept:
text/event-stream on message/send, not a separate method.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
@maleck13

Copy link
Copy Markdown
Contributor

Thanks @Aman-Cool . This is on my list to review this week. Sorry at the moment just a bit swamped. Thank you for the effort put in so far

Clarify that the broker rewrites each Agent Card's url field to the gateway
path (/a2a/{prefix}) so unmodified A2A clients route through the gateway by
following the card they already fetch. Note the agentgateway precedent and the
upstream multi-agent discovery work (a2aproject/A2A Kuadrant#641, Kuadrant#883, Kuadrant#166).

Add corresponding acceptance criteria to the test server, broker, and e2e
discovery tasks, and the discovery e2e test case. Add new technical terms to
the cspell dictionary.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
@Aman-Cool

Copy link
Copy Markdown
Collaborator Author

@maleck13, genuinely no rush on the review. I know it's a swamped stretch, and I'd much rather you get to this with real headspace than rush a skim. I'm posting this less to add to your queue and more so that when you (and @jasonmadigan) get a window, the reasoning behind the routing change is in one place instead of scattered across the earlier comments.

One important caveat up front: this is where I've landed after going deep on the spec. @david-martin had an early look and the direction seemed reasonable to him, but it isn't a settled group decision.., you and @jasonmadigan haven't had a chance to weigh in yet, and I really don't want to lock it until you guys also have. So please read everything below as a proposal I'm fairly confident in, with the door wide open to push back; especially on the one piece I've flagged as still genuinely unresolved.

How we got here

The original draft routed A2A requests by reading a skill out of the message/send body. Going through the v0.3.0 spec to build the test server, I hit the problem I flagged earlier: message/send has no skill to read. MessageSendParams is just {message, configuration, metadata}; skills only appear in the AgentCard, for discovery. So skill-dispatch wasn't something we could keep or drop by preference; it was leaning on a field the protocol doesn't have.

That leaves two honest ways to tell the gateway which agent a request is for:

  1. A path per agent : /a2a/{prefix}, known at the request-headers phase from :path.
  2. A header : something like x-a2a-agent, set by the caller.

I'm proposing the path. Reasoning below, and if either of you sees a third option I've missed, I'd genuinely like to hear it.

Why I'm leaning path-per-agent

The header approach has the problem that a stock A2A client has no concept of x-a2a-agent, so only a gateway-aware client could ever set it, the same limitation as stuffing the routing key in metadata. It only works for clients we've specifically taught about the gateway.

The path doesn't need the client to know anything. A2A clients already fetch an agent card and POST to whatever url the card advertises, that's just the normal protocol flow. So if the gateway serves each agent's card with its url pointed at …/a2a/{prefix}, a completely unmodified client just follows it to the right place. The routing key lives in the card we serve, not in something the caller has to be told.

The part that almost caught me out

I want to call this out specifically, because it's subtle and it changed how I wrote the discovery flow. The original draft had the broker simply proxying the upstream Agent Card through unchanged. That looks correct right up until you trace what a real client does with it: it reads the url field and sends message/send straight there. If we pass the upstream url through untouched, the client takes the card from the gateway and then talks directly to the upstream agent; bypassing the gateway entirely. No AuthPolicy, no RateLimitPolicy, no logging. The whole reason for the gateway quietly evaporates, and nothing errors; it just silently routes around us.

So rewriting the card's url to the gateway path isn't a cosmetic detail.., it's the load-bearing piece that makes path-per-agent actually work with unmodified clients. It took me a beat to see that clearly. It's now written up explicitly in the design doc, with its own acceptance criteria on the broker + test-server tasks and an assertion in the discovery e2e test, specifically so it can't silently regress later.

Prior art

Worth noting this isn't us out on a limb. agentgateway (Solo.io, now under the Linux Foundation, same home as A2A) landed in the same place: route-per-agent rather than skill multiplexing, and they rewrite agent card URLs to point back at the gateway... the same mechanism. Reassuring to have a real implementation pulling the same way, though obviously I don't want "someone else did it" to stand in for your own read.

The skill-prefix federation idea from the original draft doesn't die, by the way. It just stops being the routing mechanism and becomes the discovery/index layer instead.

The one piece still genuinely open; and where I'd most value your input

Discovery. A2A assumes one card per agent at the well-known path, so "how does a client find all the agents behind a single gateway" is a convention we have to define ourselves. The doc currently uses an RFC 9264 API Catalog at /.well-known/api-catalog, which is the shape a client would already expect for "list everything under one base URL." We're not alone in needing this, there's active upstream movement on exactly the same problem:

  • a2aproject/A2A#641 : multi-agent open discovery under a single base URL via an RFC 9264 catalog
  • a2aproject/A2A#883 : best practices for exposing multi-skill agents as unified external services
  • a2aproject/A2A discussion Support External MCP Servers #166 : hosting multiple agents under a single base URL

This is the part I'd treat as "track upstream and stay aligned" rather than lock down hard, and it's the spot where a second and third opinion would help most, whether we commit to the RFC 9264 catalog now or keep it deliberately loose while the upstream discussions settle.

One framing I'd put on the table, since I think it's a useful north star: this is a fast-moving spec and any specific shape of it could shift under us. The durable value the gateway adds is the auth / rate-limit / observability layer, which holds no matter how A2A itself settles; so I'm comfortable holding the discovery convention loosely as long as the routing and policy story underneath is solid.

What's already in the PR

I've pushed the design doc and task plan updates so they reflect the path-per-agent approach and the url rewriting rather than the original skill-dispatch draft. The e2e cases are updated to match too. None of it is load-bearing on a decision being final, it's just easier to review the reasoning against an up-to-date doc than against the old one.

So: no urgency at all, but whenever you both have a moment, I'd really value your read on (1) path-per-agent as the routing mechanism and (2) how firmly we want to commit to the RFC 9264 catalog for discovery. I'll hold off treating either as settled until you've had the chance.

@david-martin

Copy link
Copy Markdown
Member

Hey @Aman-Cool, apologies for not flagging this sooner. We recently updated our contributing guidelines to ask contributors to limit themselves to one open PR at a time, so you may not have seen the change. The idea is that getting one change reviewed and merged is more valuable than having several open in parallel.

You currently have four open PRs. Which one do you think is best to focus on first? We'll prioritize getting that one through.

@Aman-Cool

Copy link
Copy Markdown
Collaborator Author

Thanks @david-martin, and no worries at all; the guideline makes complete sense, and it's a good forcing function. I'd rather get one thing landed well than spread thin across several.

I'd like to focus on #1114 (the A2A design doc). It's the one the rest of my A2A work depends on.., until the routing approach and discovery convention are agreed, the CRD, controller, and router PRs would all be building on a design that isn't settled yet. CI's green and it's the furthest along, so it should be the cleanest to get over the line.

To keep things to a single active PR, I'll move my other open PRs to draft and bring them back one at a time once #1114 is merged. The two small bug fixes: the MCPManager status data race (#1005) and the singleflight session-init fix (#930), are independent of A2A and self-contained, so those are the natural ones to pick up next.

Really appreciate you prioritizing it.

…s-namespace prefix

- streaming via message/stream (§7.2) + tasks/resubscribe, not message/send+Accept
- agent card at /.well-known/agent-card.json (§5.3), agent.json as v0.2 alias
- api-catalog cited as RFC 9727 served as an RFC 9264 Linkset
- TaskState aligned to 9 kebab-case values incl auth-required/unknown (§6.3)
- Q4: per-request OAuth auth + principal-scoped task ownership (SEP-2567), deferred to wk8 sync
- TaskStore TTL decoupled from JWT (idmap safety-net), task-id work at RequestBody
- multi-field SSE task-id rewrite; cached agent cards; JSON-RPC error codes (-32001/-32601)
- cross-namespace prefix collision reframed; skillPrefix -> agentPrefix

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
@Aman-Cool
Aman-Cool force-pushed the feat/a2a-design-doc branch from 46ee1e4 to 6b9988d Compare June 26, 2026 01:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
docs/design/a2a/a2a-design.md (1)

62-67: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix UK/US spelling inconsistency.

Line 64 uses "initialises" (UK) while line 100 uses "initialize" (US). This was flagged in a previous review and marked as addressed, but the current text still shows "initialises". Standardize to US spelling to match the existing "initialize" usage.

Suggested fix
-When a platform engineer has an upstream A2A agent running in their cluster, they want to register
+When a platform engineer has an upstream A2A agent running in their cluster, they want to register
-it with the gateway so that clients can discover it via the federated agent card and send tasks
+it with the gateway so that clients can discover it via the federated agent card and send tasks
-through the gateway, so that all inter-agent traffic is subject to the same AuthPolicy and
+through the gateway, so that all inter-agent traffic is subject to the same AuthPolicy and
-RateLimitPolicy as MCP traffic.
+RateLimitPolicy as MCP traffic.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/a2a/a2a-design.md` around lines 62 - 67, The A2A design doc still
mixes UK and US spelling in the same flow, so standardize the wording to US
English. Update the occurrence in the section describing the platform engineer
deploying a new A2A agent to match the existing “initialize” usage elsewhere in
the document, and keep the terminology consistent in the surrounding A2A gateway
registration text.
🧹 Nitpick comments (1)
docs/design/a2a/a2a-design.md (1)

270-281: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reduce repetitive "At the" sentence openings in the Router description.

The Router row (line 276) has four successive sentences beginning with "At the ... phase:". Restructure for readability, e.g., bullet the phases or vary the sentence openings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/a2a/a2a-design.md` around lines 270 - 281, The Router
(`ExtProcServer`) description repeats four sentences starting with “At the ...
phase,” making the responsibilities hard to scan. Rework that row in the
component responsibilities table by restructuring the phase descriptions into
bullets or otherwise varying the sentence openings while keeping the same
`RequestHeaders`, `RequestBody`, `ResponseHeaders`, and `ResponseBody` behavior
details intact.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/a2a/a2a-design.md`:
- Around line 96-101: The job story in the “When a client sends a request
without valid auth” section does not follow the required template because it
states “the gateway’s AuthPolicy should return” instead of using an
actor-centered “[actor] wants [action/outcome] so that [benefit]” phrasing.
Update the wording in this section of the design doc to match the required job
story format by naming the actor, describing the desired outcome in
present-tense “wants” language, and keeping the existing auth/401 behavior and
upstream-forwarding intent intact.

---

Duplicate comments:
In `@docs/design/a2a/a2a-design.md`:
- Around line 62-67: The A2A design doc still mixes UK and US spelling in the
same flow, so standardize the wording to US English. Update the occurrence in
the section describing the platform engineer deploying a new A2A agent to match
the existing “initialize” usage elsewhere in the document, and keep the
terminology consistent in the surrounding A2A gateway registration text.

---

Nitpick comments:
In `@docs/design/a2a/a2a-design.md`:
- Around line 270-281: The Router (`ExtProcServer`) description repeats four
sentences starting with “At the ... phase,” making the responsibilities hard to
scan. Rework that row in the component responsibilities table by restructuring
the phase descriptions into bullets or otherwise varying the sentence openings
while keeping the same `RequestHeaders`, `RequestBody`, `ResponseHeaders`, and
`ResponseBody` behavior details intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 24da5f48-01f1-4ce0-8874-97b70ff93535

📥 Commits

Reviewing files that changed from the base of the PR and between 0205e63 and 46ee1e4.

📒 Files selected for processing (3)
  • docs/design/a2a/a2a-design.md
  • docs/design/a2a/tasks/e2e_test_cases.md
  • docs/design/a2a/tasks/tasks.md
✅ Files skipped from review due to trivial changes (2)
  • docs/design/a2a/tasks/tasks.md
  • docs/design/a2a/tasks/e2e_test_cases.md

Comment thread docs/design/a2a/a2a-design.md
…ity, ratelimit, observability)

- per-agent authorization via AuthPolicy on router-set x-a2a-agent (mirrors x-mcp-toolname RBAC)
- x-a2a-authorized skill filtering as allowed-capabilities.skills, filtered by ServeAgentCard
- skill filtering is visibility/discovery only, NOT access control: message/send has no skill (§7.1.1),
  so the enforceable authorization boundary is the agent (/a2a/{prefix}) via Kuadrant AuthPolicy
- RateLimitPolicy (x-a2a-method, principal) and OTel/Authorino/Limitador observability
- e2e cases: per-agent 403, skill-filter visibility

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
…artifacts

- task id lives at the event envelope (result.id/result.taskId), sibling to artifact/status/history,
  never inside parts (base64 FilePart.file.bytes); router parses only down to the identity fields
- heavy subtrees (status/artifact/history/message/parts) kept as json.RawMessage, never decoded/re-encoded
- cost is O(envelope), not O(artifact); large artifacts pass through as raw bytes
- bounds stated: single-event buffering + no SSE size cap (chunk via append/lastChunk); re-marshal
  copies raw bytes once (byte-splice fallback if profiling warrants)
- history[].taskId rewrite is a scoped replace within the history raw bytes, never a global replace

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
…ler status no-op guard)

- A2A has no card-change notification (verified against the v0.3.0 method set); gateway must poll
- broker A2AAgentManager mirrors only MCPManager's ticker (poll), no persistent conn / subscription
- cheap poll: conditional GET (304) -> version compare -> SHA-256 of normalized card body
- act only on change; card refresh is an in-memory cache swap under RWMutex, NOT a Secret write
- real anti-thrash point is the controller discoveredSkills status Update: skip when unchanged
  (reuse MCPServer.ConfigChanged no-op discipline)
- staleness bound = ticker interval (reuse managerTickerInterval, default 1 min); cache-buster rejected

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
…dentity/token-exchange for invocation)

- two paths, two models (mirrors MCP, which keeps credentialRef off the client path)
- card fetch (no client): Gateway-to-Agent via credentialRef; router has no credentialRef access
- message/send/tasks (real client): client identity, NOT credentialRef (static cred = confused deputy)
  - default: forward client bearer; recommended: RFC 8693 token exchange (Authorino) -> agent audience (RFC 8707)
- agent securitySchemes (apiKey/http/oauth2/openIdConnect/mutualTLS), card- and skill-level (§5)
- per-skill security advisory at gateway (no skill named in message/send); agent enforces it
- exception: apiKey/mTLS-only agents -> opt-in per-agent static credential, client authz enforced at gateway AuthPolicy

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Aman-Cool added 5 commits July 5, 2026 06:59
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
… shapes

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
…tore TTL source

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
…pe, and non-goals

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Task IDs are assigned by the upstream agent and pass through the gateway
unchanged. Routing is by path, so the gateway no longer mints, virtualizes,
or rewrites task IDs.

Replace the gateway-owned task ID and TaskRoute mapping with an
(agent, taskID) -> principal ownership record used only for ownership checks
and trace correlation. Drop the buffered and SSE task-ID body rewrites: the
non-streaming path forwards the response body byte-for-byte after reading
result.id, and the SSE handler becomes a read-only observer that binds
ownership on the first event and deletes the record on a terminal state.

Update the implementation plan and e2e test cases to match, including a new
security case covering per-principal task ownership.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
The ext_proc filter's default response_body_mode is NONE, so the router
receives a response body only when it sets a ModeOverride at
ResponseHeaders. Binding task ownership requires reading the agent-assigned
task ID from the SendMessage response, so non-streaming methods set a
BUFFERED override for observation. Nothing is mutated, so the body length
is unchanged and no content-length removal is needed; that part of the
spike remains relevant only to a future body rewrite. Restore the
ResponseHeaders step in the SendMessage and GetTask flows and align the
router responsibilities and task plan.

Describe discovery routing as implemented: card and catalog requests share
the /a2a rule, traverse ext_proc, and are passed through untouched to the
broker, which serves them. A separate card-suffix HTTPRoute rule could not
bypass the listener-scoped filter, so none exists.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Ownership checks fail closed with -32001, cover SendMessage continuations,
and records persist past terminal states (retention TTL, Redis for
multi-replica, insert-only store). SendMessage reads result.task.id per the
v1.0 oneof; GetTask/CancelTask return a bare Task. Card validation covers
every advertised interface; deferred methods are rejected, never forwarded.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Aman-Cool added a commit to Aman-Cool/A2A-Agent2Agent-protocol that referenced this pull request Jul 19, 2026
…GENT_PREFIX)

- drop the message/send + Accept streaming branch; streaming is message/stream only (§7.2)
- remove now-dead wantsSSE
- rename SKILL_PREFIX env -> AGENT_PREFIX (matches the agentPrefix rename in Kuadrant#1114)

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Aman-Cool added a commit to Aman-Cool/A2A-Agent2Agent-protocol that referenced this pull request Jul 19, 2026
- 'large'/'image' trigger returns a FilePart with a deterministic, size-configurable
  base64 payload (ARTIFACT_BYTES, default 1 MiB)
- message/send: single large FilePart artifact (buffered rewrite path)
- message/stream: chunked artifact-update events (append/lastChunk), split mid-base64
  on purpose so a decoder chokes but a passthrough doesn't (proves envelope-only, no decode)
- deterministic content so e2e can regenerate and assert byte-for-byte forwarding
- adds fileContent/artifactUpdateEvent types; exercises the Task 12 SSE design (Kuadrant#1114)

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Aman-Cool added a commit to Aman-Cool/A2A-Agent2Agent-protocol that referenced this pull request Jul 19, 2026
raw ': ping' comment after the initial task event, so the gateway's data:-only
SSE rewriter must pass non-data: lines through untouched without JSON-parsing them
(regression guard for the Task 12 passthrough, Kuadrant#1114)

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Aman-Cool added a commit to Aman-Cool/A2A-Agent2Agent-protocol that referenced this pull request Jul 19, 2026
streaming method: reconnect replays the current task state over SSE and, for a
working task, streams working updates then a terminal final event (bounded so it
can't hang); an already-terminal task still gets an SSE final event, not a
buffered response; unknown id -> -32001. completes the v0.3.0 method matrix (Kuadrant#1114)

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Aman-Cool added a commit to Aman-Cool/A2A-Agent2Agent-protocol that referenced this pull request Jul 19, 2026
- agentCard gains security/securitySchemes; AUTH_MODE declares them
- enforcement, not just declaration: apikey requires X-API-Key (API_KEY) on the card
  fetch (tests credentialRef discovery) and /a2a; bearer requires Authorization: Bearer
  on /a2a (tests forward/token-exchange invocation); none (default) stays open
- 401 + WWW-Authenticate when the credential is missing
- lets e2e validate the gateway's credentialRef + token-exchange auth brokering (Kuadrant#1114)

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
…ation

The A2A project closed its RFC 9264-catalog discovery issue in favor of
the Agent-Card AI Catalog specification, whose entries carry both A2A
agent cards and MCP server cards; update the discovery [OPEN] marker with
that state and note the catalog layer is thin enough to serve ai-catalog
additively. Cite the reference a2a-go client's behavior where it verifies
this design's contract: it binds to the card's supportedInterfaces, its
default resolution matches the gateway card path with no configuration,
and its transport selection would pick a stray non-JSONRPC interface.
Note that the reference SDK does not verify card signatures today and
that additive counter-signing is an open protocol question, and state
that the task-record retention TTL is operator-configured because A2A
defines no discoverable task-retention period.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
…ownership

Align the card-validation claims with what the broker enforces (http(s)
scheme, gateway path and host, JSONRPC binding, v1 protocolVersion) and
correct the fail-closed wording: the broker excludes an agent from the
catalog, a broker-local catalog-ineligible state, not the CRD Ready
condition, since the broker is a read-only config observer with no status
channel. Catalog eligibility now means a validated card is cached.

Add a parallel insert-only (agent, contextId) -> principal record so a
principal that learns another's contextId cannot inject into or continue
that conversation, and both send methods verify context ownership. State
insert-only as LoadOrStore / SET NX with new / same-owner / different-owner
/ store-unavailable outcomes, binding before the response is released.

Note that catalog traversal is a gateway convention, not stock A2A
discovery (per-agent card resolution is stock), with the RFC 9727 HEAD and
profile details; that signed cards are single-gateway and their
securitySchemes are advisory under gateway auth; that the AuthPolicy must
scope to POST so public card GET stays unauthenticated; that the router
guards the A2A-Version before parsing ownership fields; and that the router
consumes a sanitized routing view without discovery credentials. Sync the
task plan and e2e cases.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Align the Data Storage section with the implemented task ownership store:
records are the owning principal keyed (agent, taskID) in the existing in-memory
sync.Map under a taskowner: prefix, not a separate taskRecords field holding a
TaskRecord struct; StoreTaskRecord takes the principal and a TTL and returns the
current owner plus whether it created the record (insert-only via LoadOrStore /
SET NX); the Redis key is taskowner:{agent}:{id}. Trace context on the record is
reframed as the additive span-link enhancement rather than a stored struct field.

Fix an internal inconsistency in header stripping: the Security section listed
only x-a2a-agent and x-a2a-task-id, while the API Changes and RateLimitPolicy
sections rely on x-a2a-method being router-derived and un-forgeable. All three
are stripped at the HTTPRoute and in internalOnlyHeaders.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Land the design incrementally behind an experimental --enable-a2a router flag,
default off, with any APIs introduced along the way alpha. Phase boundaries
follow review: no new CRDs while the long-term home for A2A support is being
settled, and no broker changes while the broker is mid-churn on the new MCP
spec version.

Phase 1 is router-only passthrough for auditing, auth and observability: strip
inbound x-a2a-* headers, parse POST bodies envelope-only, set x-a2a-method and
x-a2a-agent (agent identity is the first path segment after /a2a/, a documented
convention since the body names no agent), fail closed on unparseable POSTs,
pass GETs through. Users hand-author agent HTTPRoutes; the headers feed Istio
Telemetry and AuthPolicy with no further gateway code, and the agent-side task
isolation and card-URL trust boundaries are documented rather than enforced.
Phase 2 is registration and discovery (CRD, card cache and validation, verbatim
serving); phase 3 is task ownership records and read-only SSE lifecycle
observation. Phases 2 and 3 are the direction as understood, not a commitment.

The Summary gains a pointer to the phases so the full-direction description is
read as the destination rather than the first landing.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
The task plan predated the phased landing and collided with it: its "Phase 1:
Foundation" contained the CRD and reconciler, while the design's phase 1 is the
router-only passthrough cut that explicitly excludes them. Restructure the plan
around the design's implementation phases: phase 1 is the passthrough cut
(Kuadrant#1333) — the flag, header stripping, envelope-only parse and passthrough
metadata, its docs, and e2e against a hand-authored HTTPRoute — with the test
server moved up since the e2e needs it; registration/discovery and task
ownership tasks move under gated phases 2 and 3, narrowed where phase 1 already
ships a piece. Week-based scheduling is dropped in favour of the phase gates.

Also reconcile stale details with the design and the tree: the task-ownership
store criteria now match the design's store section (records in the existing
in-memory map under a taskowner: prefix, insert-only store returning owner and
created, taskowner:{agent}:{id} Redis key); file references follow the router
refactor (ext_proc_adapter.go, internal/routing); and the session-validation
row gives way to per-request principal extraction via ExtractSubClaim, matching
the per-request OAuth model.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
The e2e case catalog describes the full direction; point phase 1's passthrough cases at the plan's Task 5 so the two read consistently with the phased landing.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Reconcile the full-direction body with the implementation phases and drop stale
citations found on a close read:

- Non-Goals now qualifies the -32004 deferred-method rejection as landing with
  the ownership enforcement it protects, so it no longer reads as always-on
  against the phase 1 exclusion.
- Phase 2 explicitly names registry-backed request routing (agent resolution +
  :authority) as part of the discovery half, and the AuthPolicy section notes
  x-a2a-agent carries the bare path segment in phase 1, the namespace-qualified
  identity once the registry exists.
- Remove line-number citations that drift as code moves (manager.go, tracing.go,
  request_handlers.go) and the header-strip reference now points at
  InternalOnlyHeaders in internal/routing and the a2a rule's filter, matching the
  router refactor.

All 11 internal anchors verified; no [OPEN markers remain.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>

@david-martin david-martin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approving, with phase 1 changes being implementable

The intent is to have a --enable-a2a flag on the router, and only then parse traffic as a2a if it's on a /a2a prefixed path. No CRDs in this phase. Enables auth, auditing and observability at this phase. No a2a aggregation of cards or a2a catalog endpoint at this time.

@david-martin
david-martin merged commit 23869cd into Kuadrant:main Aug 4, 2026
17 checks passed
Aman-Cool added a commit to Aman-Cool/A2A-Agent2Agent-protocol that referenced this pull request Aug 8, 2026
The design doc merged upstream (Kuadrant#1114) with an implementation-phases section,
and the landing is now incremental behind an experimental --enable-a2a flag:
a router-only passthrough cut first (Kuadrant#1333), with registration/discovery and
task ownership as later phases. Bring the fork's copies of the design doc,
tasks plan and e2e cases up to the merged upstream versions, and update the
README to match: Kuadrant#1114 merged, the phased landing narrative, the first-cut
scope agreed with David and Craig, the test server approved (Kuadrant#1200), and the
router/SSE/e2e prototype now merged and live-verified in-fork.

Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-effort/medium Medium review effort (3): few files, moderate logic triage/needs-issue PR needs a linked issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants