Repository navigation
Add standalone native A2A session routing sample with same-user and real-user evidence - #1156
Open
Hameed Kunkanoor (Hameedkunkanoor) wants to merge 3 commits into
Open
Hameed Kunkanoor (Hameedkunkanoor) wants to merge 3 commits into
Hameed Kunkanoor (Hameedkunkanoor) wants to merge 3 commits into
Conversation
Include deterministic A/B-to-C agents, dedicated local and real-user runners, fully pinned runtime dependencies, and recorded same-user and two-user evidence. Exclude only this sample from unsupported shared cloud A2A orchestration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Hameed Kunkanoor (Hameedkunkanoor)
requested a review
from a team
as a code owner
November 11, 2026 05:36
Hameed Kunkanoor (Hameedkunkanoor)
deployed
to
L4-validation
November 11, 2026 05:36 — with
GitHub Actions
Active
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The remote-run assertion checks context-filtered history rather than full session history, allowing cross-context state leakage to go undetected.
1 open issue
What changed in this PR
Adds a standalone native A2A sample to the Python hosted-agent collection, demonstrating how downstream context IDs and authenticated users affect session reuse without involving a model.
Changes:
- Implements deterministic A/B forwarders and a C observer with session-local marker history.
- Adds local and remote runners, real-user receipt comparison, tests, and historical evidence with explicit limitations.
- Provides bundled deployment setup and excludes the sample from the unsupported shared cloud harness.
Paths below are relative to samples/python/hosted-agents/bring-your-own/a2a/session-routing/, except the CI skiplist.
| File | Description |
|---|---|
tests/test_routing.py |
Tests routing modes, ledger history, and receipt comparison. |
test_local.py |
Starts three local agents and runs the experiment. |
src/agent/requirements.txt |
Pins the complete dependency graph. |
src/agent/main.py |
Implements forwarding and session observation. |
src/agent/client.py |
Handles native A2A discovery, authentication, and completed-task validation. |
src/agent/.agentignore |
Excludes local artifacts from deployment uploads. |
run_real_user.py |
Invokes agents using CLI credentials and compares saved receipts. |
run_experiment.py |
Exercises sequential, concurrent, and follow-up routing scenarios. |
README.md |
Documents setup, reproduction, findings, and limitations. |
prepare_bundle.ps1 |
Prepares Linux Python dependency bundles. |
evidence/same-user.json |
Records same-user observations and checks. |
evidence/real-user-u2.json |
Preserves selected second-user receipt fields and provenance. |
evidence/real-user-u1.json |
Preserves selected first-user receipt fields and provenance. |
azure.yaml |
Configures three hosted agents against an existing project. |
AGENTS.md |
Documents sample-specific development and evidence guidance. |
.gitignore |
Excludes generated results, bundles, and deployment state. |
.azure-pipelines/scripts/hosted-agent-samples-ci-skiplist |
Adds the exact-path native A2A cloud-harness exclusion. |
Review effort: Balanced
Comment on lines
+65
to
+67
| check(f"{label}: no cross-caller context history", | ||
| all(item["marker"] not in markers - {receipt["marker"]} | ||
| for receipt in pair for item in receipt["prior_context_messages"])) |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Add one standalone native A2A 1.0 sample at
samples/python/hosted-agents/bring-your-own/a2a/session-routing.No travel-planner, Flight, Hotel, web-search or other existing sample code is included.
The branch starts from upstream
main, not the previous multi-sample branch.The question we tested:
Implementation
REPRO_ROLE, sharing one implementation.fresh: omit C's context;explicit: supplyc_context_id;inherit: copy the incoming A2A context to C.AzureCliCredential.Important: an A2A context ID is not a hosted session ID. We compared C's platform-injected session ID and its stored history rather than inferring sharing from matching context labels.
What we tried and observed
1. Same real user calls A and B
Recorded run:
repro-9af72d559e114a51864d528caabd0bf8.The original deployment completed 18 parent invocations, 18 downstream calls and 57 passing assertions.
Concrete shared-context evidence:
3fa479bce41fc1b2a75drepro-9af72d559e114a51864d528caabd0bf8-shared-ceeac7b653964cc989c6b26e2143e08da4dbec8a18c752e35b6225f3d28c3e95These are not random collisions: the shared cases deliberately reused the same context ID. The fresh cases did not share sessions in this run.
2. Two independently authenticated users: U1 -> A -> C and U2 -> B -> C
Both users sent the identical downstream context:
two-real-users-nov9-test01.Both tasks completed successfully.
3fa479bce41fc1b2a75d8c98f58254de5d698ab0two-real-users-nov9-test01two-real-users-nov9-test0148b40392d95634cce5818562c55536b8596fd2f5f6df2d34bf73de3368c0145f6a0aac7845d438e7db4ad8745900a43892360d6620c1dfb34fbb839e3ed49f203fe03e-2ec8-4cec-b775-7ad760cfabb41a038aa4-9078-4ae0-bfca-158514e1b296Each parent's user fingerprint matched C's fingerprint on that path. The equal context labels did not merge the two users' C sessions in these observations.
U1's response was captured directly; U2's completed response was supplied by the independently signed-in tester. The sample retains selected non-secret fields with provenance.
3. Attempts that did not establish a result
x-ms-user-identitydelegation: 403, "Caller is not authorized to delegate to another user." Normal access returned 200. No delegation permissions were changed and no isolation conclusion is drawn from that attempt.Interpretation and limitations
For the configuration tested:
The real-user requests were approximately 26 hours apart, not concurrent. They do not prove simultaneous cross-user isolation, repeat-call history isolation or cross-tenant isolation. We did not test LLM conversation mixing. Finite tests cannot establish the impossibility of all collisions or service bugs.
Session/context/task IDs and fingerprints are opaque diagnostic comparison values. No bearer tokens, raw user identifiers, private endpoint credentials,
.azurestate, virtual environments or dependency binaries are committed.Reproduce
See the sample README for prerequisite access, unique agent naming, existing-project setup, C-then-A/B deployment, required forwarder roles, local tests and two real-user sign-ins.
Historical evidence:
evidence/same-user.json: the 18 observations and 57 checks.evidence/real-user-u1.json: selected U1 receipt fields.evidence/real-user-u2.json: selected tester-supplied U2 receipt fields.Live runs write to ignored
results/, not over the historical evidence.Validation
--resolveclosure validation.No new cloud deployment or real-user invocation is claimed for this PR preparation; the cloud results above are the recorded experiments.
Why one CI metadata line is included
The only change outside this sample is its exact-path entry in the shared hosted-agent cloud-deployment skiplist. The shared harness supports Responses/Invocations, not native A2A card discovery/JSON-RPC, ordered three-agent setup or separate human sign-ins. This sample uses its dedicated runners rather than claiming unsupported shared-harness coverage. No unrelated sample exclusion or code is changed.