← Back to PRs

#19293: feat: A2A typed contracts for sessions_send

by AdairBear open 2026-02-17 16:50 View on GitHub →
docs agents size: XL
## Summary Adds typed message contracts for `sessions_send`, giving inter-agent communication a validation layer that catches malformed payloads at the gate instead of at the receiving agent. Split from #18990 per @steipete's feedback — this PR contains only the A2A contract work, no MCP changes. ## What it does - **Contract definitions** — define JSON-Schema contracts per agent describing the message shapes that agent accepts - **Validation gate** — `sessions_send` validates payloads against registered contracts; rejects freeform text when contracts exist - **Schema constraints** — minLength, maxLength, pattern, minimum, maximum, additionalProperties, minItems, maxItems - **Versioning** — `version`, `deprecated`, and `supersededBy` fields on contracts - **Deprecation warnings** — validation results include warnings when using deprecated contracts - **Context builder** — `buildAgentToAgentContractContext()` generates system-prompt context listing available contracts ## Files changed (7 files, +1,567 lines) | File | Purpose | |------|---------| | `src/agents/tools/a2a-contracts.ts` | Contract registry, validation engine, versioning | | `src/agents/tools/a2a-contracts.test.ts` | 47 unit tests | | `src/agents/tools/a2a-contracts-pipeline.test.ts` | 12 pipeline integration tests | | `src/agents/tools/sessions-send-tool.ts` | Contract validation gate wired into send flow | | `src/agents/tools/sessions-send-helpers.ts` | Contract context builder for system prompts | | `docs/tools/a2a-contracts.md` | Documentation with examples | | `docs/docs.json` | Nav entry under Agent coordination | ## Testing **59 tests** across 2 test files, all passing. ## Breaking changes None. When no contracts are registered, `sessions_send` behaves exactly as before. <!-- greptile_comment --> <h3>Greptile Summary</h3> Adds typed A2A message contracts for `sessions_send`, allowing agents to declare JSON-Schema-based input/output contracts that are validated before message delivery. Includes contract discovery, deprecation/versioning metadata, an `allowFreeform` gate, and system prompt context injection for the target agent. - **Runtime crash bug**: `parseA2AMessage` does not validate the `payload` field exists. When a structured message omits `payload` and the matched contract has no `input` schema, `JSON.stringify(undefined)` in `buildAgentToAgentContractContext` returns the JS value `undefined` (not a string), and the subsequent `.length` access throws a `TypeError`. - **Deprecation warnings discarded**: The validation result's `warnings` array (carrying deprecation notices) is computed but never surfaced in the `sessions_send` response, making the deprecation/versioning feature effectively invisible to callers. - **Missing type definition**: The `a2a` field is not added to `AgentConfig` in `types.agents.ts`, forcing all access to go through `as Record<string, unknown>` casts — contrary to the repo's guideline of preferring strict typing over `any`. - Well-tested with 59 tests across two files covering validation, discovery, deprecation, and pipeline integration. <h3>Confidence Score: 2/5</h3> - This PR has a reachable runtime crash bug that should be fixed before merging. - Score of 2 reflects one confirmed runtime crash (missing payload validation leading to TypeError in buildAgentToAgentContractContext) and one functional gap (deprecation warnings silently discarded despite being a stated feature). The core validation logic is sound and well-tested, but the crash is reachable in normal usage. - Pay close attention to `src/agents/tools/a2a-contracts.ts` (parseA2AMessage missing payload check) and `src/agents/tools/sessions-send-helpers.ts` (unguarded JSON.stringify of potentially undefined payload). <sub>Last reviewed commit: 07899c6</sub> <!-- greptile_other_comments_section --> <sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub> **Context used:** - Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8)) <!-- /greptile_comment -->

Most Similar PRs