#19293: feat: A2A typed contracts for sessions_send
docs
agents
size: XL
Cluster:
Model Management Enhancements
## 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
#19923: feat: track held messages during compaction gate and split verifica...
by PrivacySmurf · 2026-02-18
73.7%
#16247: feat(agents): declarative agent definitions for sessions_spawn
by zerone0x · 2026-02-14
73.2%
#10486: feat: A2A protocol plugin
by benclarkeio · 2026-02-06
72.9%
#7516: feat(sessions): Auto-inject From:/To: identity headers in agent-to-...
by RusDyn · 2026-02-02
72.2%
#11788: feat: inter-agent communication via CLI scripts
by jingkang0822 · 2026-02-08
71.4%
#16565: feat: Add tool_invocation provenance for A2A tool calls
by mdlmarkham · 2026-02-14
71.4%
#20072: feat(sessions_spawn): add sessionKey param to reuse sub-agent sessions
by Be1Human · 2026-02-18
70.9%
#10748: feat: Add sessions.spawn gateway method for direct subagent spawning
by fox-openclaw · 2026-02-06
70.6%
#8471: fix(subagent): add defensive checks for undefined string fields
by adam-smeth · 2026-02-04
70.6%
#20081: feat: post-compaction triage UX — fuzzy ok + stage-2 gate + Discord...
by PrivacySmurf · 2026-02-18
70.5%