@ssheleg/agent-stack 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +88 -0
- package/README.md +29 -4
- package/package.json +2 -2
- package/plugins/agent-stack/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-stack/skills/agent-interop/SKILL.md +172 -0
- package/plugins/agent-stack/skills/agent-interop/references/a2a.md +209 -0
- package/plugins/agent-stack/skills/agent-interop/references/gateway.md +161 -0
- package/plugins/agent-stack/skills/agent-interop/references/mcp-scale.md +162 -0
- package/plugins/agent-stack/skills/agent-interop/references/mcp-ship.md +142 -0
- package/plugins/agent-stack/skills/agent-interop/references/mcp.md +241 -0
- package/plugins/agent-stack/skills/agent-interop/references/registry.md +181 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,94 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
5
|
Versioning: [SemVer](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.7.1] - 2026-08-14
|
|
8
|
+
|
|
9
|
+
A red `validate` could not stop a publish anywhere in this family, and one member
|
|
10
|
+
proved it: on 2026-08-12 `sheleg-dev` tagged v0.4.1 while its own validate run for that
|
|
11
|
+
exact tag **failed**, and npm served 0.4.1 four minutes later.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **The release now runs the whole validate suite before anything is published.**
|
|
16
|
+
`validate.yml` gained a `workflow_call` trigger and `release.yml` calls it with
|
|
17
|
+
`needs: validate` — the release runs *after* the real suite rather than beside a copy
|
|
18
|
+
of it. **Not one plant is duplicated:** each still has exactly one home.
|
|
19
|
+
- **A guard keeps the connection there.** It fails when the trigger, the call, or the
|
|
20
|
+
`needs` goes missing — calling the suite without depending on it lets the jobs run in
|
|
21
|
+
parallel, which looks gated and is not. Watched failing against the planted removal.
|
|
22
|
+
|
|
23
|
+
Proven end to end on `sheleg-dev` v0.4.3 before it reached here: the release run shows
|
|
24
|
+
`validate / validate` completing first, then `release`, then `publish`.
|
|
25
|
+
|
|
26
|
+
## [0.7.0] — 2026-08-14
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **`agent-interop`, a third skill — the protocol layer between processes.** The pack
|
|
31
|
+
could build an agent (`agent-orchestrator`) and prove it behaved (`agent-evals`), and
|
|
32
|
+
said nothing about how either talks to anything outside its own process. Six references:
|
|
33
|
+
MCP's wire surface, running many servers at once, shipping a server so a client can
|
|
34
|
+
actually reach it, the registry, A2A, and the gateway layer. It is its own skill rather
|
|
35
|
+
than a reference under `agent-orchestrator` because both existing descriptions sit at
|
|
36
|
+
~91% of the 1024-character budget — measured, not estimated — and "write me an MCP
|
|
37
|
+
server" matches neither of their triggers.
|
|
38
|
+
|
|
39
|
+
- **`references/mcp.md`** — MCP pinned at revision `2026-07-28`, written around the part
|
|
40
|
+
that breaks code written from memory: the protocol is now **stateless**, the `initialize`
|
|
41
|
+
handshake is gone in favour of `server/discover`, and version plus capabilities ride in
|
|
42
|
+
`_meta` on every request. The full deprecation register with migration paths —
|
|
43
|
+
**sampling, roots, logging and dynamic client registration are all on the way out**,
|
|
44
|
+
which is precisely the set an older model reaches for first. Plus notifications as opt-in
|
|
45
|
+
`subscriptions/listen` streams, `ttlMs` / `cacheScope` caching, and the fact that a
|
|
46
|
+
failed tool arrives as `isError: true` inside a 200.
|
|
47
|
+
|
|
48
|
+
- **`references/mcp-scale.md`** — the two distinct costs of many servers and the pattern
|
|
49
|
+
for each: progressive discovery for *when* definitions enter context (with the published
|
|
50
|
+
1–5% threshold), programmatic tool calling for *how* tools are invoked. Includes the
|
|
51
|
+
interaction that turns a clever discovery scheme into a regression — most providers cache
|
|
52
|
+
the prompt prefix **including the `tools` array**, so mutating it mid-conversation can
|
|
53
|
+
cost more than the definitions it removed.
|
|
54
|
+
|
|
55
|
+
- **`references/mcp-ship.md`** — mounting a server inside an existing app, transport-level
|
|
56
|
+
auth, client config in both forms, and the 404 that is really FastMCP's double path.
|
|
57
|
+
Relocated from `make-skill`, where it had been describing a protocol rather than a skill.
|
|
58
|
+
|
|
59
|
+
- **`references/a2a.md`** — A2A 1.0 under the Linux Foundation: agent cards and the
|
|
60
|
+
`/.well-known/agent-card.json` path, the full `TASK_STATE_*` enum with terminal states
|
|
61
|
+
marked, three protocol bindings with their REST method mapping, and the v0.x→1.0 rename
|
|
62
|
+
spelled out so inherited code is recognisable on sight.
|
|
63
|
+
|
|
64
|
+
- **`references/registry.md`** — `server.json`, reverse-DNS namespaces and the Ed25519
|
|
65
|
+
DNS/HTTP challenge that proves one, the publish flow with its three named failure modes,
|
|
66
|
+
and the registry's three refusals: no private servers, not for direct host consumption,
|
|
67
|
+
not designed for self-hosting.
|
|
68
|
+
|
|
69
|
+
- **`references/gateway.md`** — what a gateway must do that an API gateway does not, stated
|
|
70
|
+
vendor-neutrally, with agentgateway as the named reference implementation. Includes the
|
|
71
|
+
federation trap that bites later: `prefixMode: conditional` renames every tool the day a
|
|
72
|
+
second target is added.
|
|
73
|
+
|
|
74
|
+
### Changed
|
|
75
|
+
|
|
76
|
+
- **The validator now enforces a revision stamp on protocol references** (`PROTOCOL_PINNED`
|
|
77
|
+
in `test/validate.py`). Prose about somebody else's specification ages silently — a
|
|
78
|
+
reader cannot tell last year's handshake from this year's, and a model writing code from
|
|
79
|
+
it is confidently wrong with no signal anywhere on the page. Every file under
|
|
80
|
+
`agent-interop/references/` must open with `**Spec pinned:** … · read YYYY-MM-DD`, and
|
|
81
|
+
the date must be a real one. Two negative self-tests, both anchored on the stamp's shape
|
|
82
|
+
and both asserting they planted something.
|
|
83
|
+
|
|
84
|
+
- **`test/validate.py` no longer reads `other-skill/references/x.md` as a link of its own.**
|
|
85
|
+
A bare `references/x.md` means this skill's file; a path-qualified one is prose about a
|
|
86
|
+
sibling. Without the lookbehind, stating a boundary against another skill — which
|
|
87
|
+
`agent-interop` must do — failed the build over a file it never claimed. The existing
|
|
88
|
+
dangling-link plant proves the narrowed pattern still catches the real case, and a second
|
|
89
|
+
plant proves it inside the new skill.
|
|
90
|
+
|
|
91
|
+
- **The installer functional test asserts every shipped skill installs**, by enumerating the
|
|
92
|
+
skills directory rather than naming files. `bin/agent-stack.js` already enumerated;
|
|
93
|
+
nothing proved it kept doing so.
|
|
94
|
+
|
|
7
95
|
## v0.6.1 — 2026-08-13
|
|
8
96
|
|
|
9
97
|
Two CI fixes that had been sitting on `main` unreleased ship here, and the half of
|
package/README.md
CHANGED
|
@@ -9,8 +9,9 @@ Part of the [ssheleg skill family](https://github.com/ssheleg/sshlg-skills).
|
|
|
9
9
|
|
|
10
10
|
## What is in here
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
behaves
|
|
12
|
+
Three skills — `agent-orchestrator` for building one, `agent-evals` for proving it
|
|
13
|
+
behaves, `agent-interop` for everything it talks to outside its own process — and
|
|
14
|
+
eleven references they load on demand.
|
|
14
15
|
|
|
15
16
|
**The orchestrator** (`SKILL.md`) — what the agent reads first:
|
|
16
17
|
|
|
@@ -39,6 +40,22 @@ code checks before model judges, judges calibrated against human labels before
|
|
|
39
40
|
they are trusted, and a corpus grown from production failures rather than
|
|
40
41
|
authored up front — where every fixed failure stays a fixture permanently.
|
|
41
42
|
|
|
43
|
+
**The interop skill** (`agent-interop/SKILL.md`) — the protocols an agent speaks
|
|
44
|
+
outside its own process, and the one rule that governs all of them: a protocol claim
|
|
45
|
+
without a date is a guess. Every one of these specifications moved in the last twelve
|
|
46
|
+
months in a way that silently breaks older code — MCP replaced the `initialize`
|
|
47
|
+
handshake with `server/discover` and went **stateless**, deprecated **sampling, roots
|
|
48
|
+
and logging**; A2A renamed its wire surface between v0.x and 1.0; agentgateway
|
|
49
|
+
deprecated `binds` while its own overview page still teaches it. So every reference
|
|
50
|
+
carries a `**Spec pinned:** … · read <date>` line, and the validator fails the build
|
|
51
|
+
without one. Six references: `mcp.md` (the wire and the full deprecation register),
|
|
52
|
+
`mcp-scale.md` (progressive discovery, code mode, and the prompt-cache interaction that
|
|
53
|
+
undoes both), `mcp-ship.md` (mounting, and the 404 that is really a double path),
|
|
54
|
+
`registry.md` (`server.json`, namespace proof, the registry's three refusals),
|
|
55
|
+
`a2a.md` (cards, task states, three bindings), `gateway.md` (what a gateway must do that
|
|
56
|
+
an API gateway does not). Plus a link map, and a verdict on each neighbouring standard —
|
|
57
|
+
ACP, AGNTCY, AP2, Agent Skills — so an agent stops guessing.
|
|
58
|
+
|
|
42
59
|
**`references/context-engineering.md`** — what the loop gives up when the window
|
|
43
60
|
runs out: the five-rung compaction ladder and why to re-measure between rungs,
|
|
44
61
|
the tool-pair boundary invariant, typed carryover blocks copied across the
|
|
@@ -122,8 +139,16 @@ audit row has to carry to prove a control was on.
|
|
|
122
139
|
trajectory rather than a final answer, turning a production failure into a
|
|
123
140
|
permanent fixture, calibrating a judge, gating a release on offline evals.
|
|
124
141
|
|
|
125
|
-
|
|
126
|
-
|
|
142
|
+
`agent-interop`: building or consuming an MCP server, exposing or calling another
|
|
143
|
+
agent over A2A, publishing to the MCP Registry, or putting a gateway in front of
|
|
144
|
+
agent traffic. Not for designing one server's tool set — that is a design problem,
|
|
145
|
+
and Anthropic's `mcp-server-dev` plugin is built for it — and not for a skill's own
|
|
146
|
+
construction, which is `make-skill`. That boundary runs both ways: `make-skill` keeps
|
|
147
|
+
what changes *because you are writing a skill*, and the protocol itself is described
|
|
148
|
+
here and nowhere else in the family.
|
|
149
|
+
|
|
150
|
+
None of the three triggers for a single LLM call in a script or for prompt wording —
|
|
151
|
+
that is not an orchestrator, and pulling this much doctrine for it is how a skill
|
|
127
152
|
teaches you to route around it.
|
|
128
153
|
|
|
129
154
|
---
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ssheleg/agent-stack",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Production patterns for AI agent orchestrators
|
|
3
|
+
"version": "0.7.1",
|
|
4
|
+
"description": "Production patterns for AI agent orchestrators \u2014 tool-calling loops, multi-stage pipelines with checkpoints, LLM provider routing with fallback, four-layer memory with confidence decay \u2014 plus the wallet side of reselling LLM access. This package is the installer CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agent-stack": "bin/agent-stack.js"
|
|
7
7
|
},
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "agent-stack",
|
|
3
3
|
"displayName": "Agent Stack",
|
|
4
4
|
"description": "Two skills: agent-orchestrator \u2014 tool-calling loops, multi-stage pipelines with checkpoints, provider routing with fallback, four-layer memory, context engineering, plus the wallet side of reselling LLM access; and agent-evals \u2014 run/trace/thread evals, judges, and fixtures grown from production.",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.7.1",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "ssheleg",
|
|
8
8
|
"url": "https://x.com/sshlg93"
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-interop
|
|
3
|
+
description: >-
|
|
4
|
+
Use when an agent must talk to something outside its own process — building or consuming an
|
|
5
|
+
MCP server, exposing or calling another agent over A2A, publishing to the MCP Registry, or
|
|
6
|
+
putting a gateway in front of agent traffic. Carries the MCP 2026-07-28 wire surface and what
|
|
7
|
+
it deprecated (server/discover, stateless per-request _meta, elicitation in form and URL mode,
|
|
8
|
+
subscriptions/listen; sampling, roots, logging and dynamic client registration on the way out),
|
|
9
|
+
A2A 1.0 agent cards, task states and three bindings, registry namespaces and server.json, tool
|
|
10
|
+
federation, and what a gateway must do that an API gateway does not. Triggers - "MCP server",
|
|
11
|
+
"MCP client", "A2A", "agent card", "agent interoperability", "MCP registry", "server.json",
|
|
12
|
+
"agentgateway", "tool federation", "MCP-сервер", "карточка агента", "интероперабельность
|
|
13
|
+
агентов", "реестр MCP", "шлюз для агентов". Not for designing one server's tool set, and not
|
|
14
|
+
for a skill's own construction — that is make-skill.
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Agent interop — the protocols an agent speaks outside its own process
|
|
18
|
+
|
|
19
|
+
`agent-orchestrator` builds the loop. `agent-evals` proves it behaves. This skill covers
|
|
20
|
+
everything the loop reaches that is **not in its process**: a tool server, a peer agent, a
|
|
21
|
+
registry, and the gateway between them.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Rule zero — a protocol claim without a date is a guess
|
|
26
|
+
|
|
27
|
+
Every one of these specifications moved in the last twelve months, and each moved in a way
|
|
28
|
+
that silently breaks code written against the previous revision. Concretely, and each one
|
|
29
|
+
measured against the live specification rather than recalled:
|
|
30
|
+
|
|
31
|
+
- MCP replaced the `initialize` handshake with `server/discover` and made the protocol
|
|
32
|
+
**stateless**; a client that opens with `initialize` is speaking a revision that is on its
|
|
33
|
+
way out.
|
|
34
|
+
- MCP **deprecated `sampling`, `roots` and `logging`** — three things an older model will
|
|
35
|
+
reach for first, because for a year they were the interesting part of the client side.
|
|
36
|
+
- A2A renamed its wire surface between v0.x and v1.0, and SDKs and blog posts still document
|
|
37
|
+
v0.3.
|
|
38
|
+
- agentgateway **deprecated `binds`** in favour of `gateways` — while its own overview page
|
|
39
|
+
still introduces `binds` as a core concept.
|
|
40
|
+
|
|
41
|
+
So: **every reference in this skill opens with a `**Spec pinned:**` line**, and
|
|
42
|
+
`test/validate.py` fails the build without one. That is a mechanical check, not an
|
|
43
|
+
aspiration — the class of error it prevents is the one where prose reads as current
|
|
44
|
+
because nothing on the page says otherwise.
|
|
45
|
+
|
|
46
|
+
**Before you write wire-level code, fetch the spec.** These references tell you what to look
|
|
47
|
+
for and what changed; they are not a substitute for the document. Read the pinned revision,
|
|
48
|
+
then check whether a newer one exists. Every entry in the link map below is fetchable.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Which protocol answers which question
|
|
53
|
+
|
|
54
|
+
| The question you actually have | The answer | Where |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| I want to give a model a capability against a live system | **MCP server** | `references/mcp.md` |
|
|
57
|
+
| My server is written and the client cannot connect to it | mounting and transports | `references/mcp-ship.md` |
|
|
58
|
+
| I want my application to consume other people's tool servers | **MCP client** | `references/mcp.md`, then `references/mcp-scale.md` |
|
|
59
|
+
| I have more servers than fit in a context window | client scaling patterns | `references/mcp-scale.md` |
|
|
60
|
+
| I want another team's *autonomous agent* to accomplish an outcome for me | **A2A** | `references/a2a.md` |
|
|
61
|
+
| I want my agent discoverable and callable by other agents | **A2A agent card** | `references/a2a.md` |
|
|
62
|
+
| I want people to find and install my MCP server | **MCP Registry** | `references/registry.md` |
|
|
63
|
+
| I have many servers, many clients, and a security team | **a gateway** | `references/gateway.md` |
|
|
64
|
+
|
|
65
|
+
**The one-line rule between the two big ones.** MCP connects a model to a *capability* you
|
|
66
|
+
control the shape of; A2A connects you to a *peer* whose insides you deliberately cannot
|
|
67
|
+
see. The official framing is exact and worth keeping: *"A2A is about agents partnering on
|
|
68
|
+
tasks, while MCP is more about agents using capabilities."* Real systems run both — an A2A
|
|
69
|
+
server whose internals speak MCP — and that is the recommended architecture, not a
|
|
70
|
+
compromise.
|
|
71
|
+
|
|
72
|
+
**The tell that you picked wrong:** if you find yourself inventing a task lifecycle, a
|
|
73
|
+
progress channel and a resumable handle on top of `tools/call`, you wanted A2A. If you find
|
|
74
|
+
yourself publishing an agent card for something that is one HTTP call with a JSON schema,
|
|
75
|
+
you wanted MCP.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## References
|
|
80
|
+
|
|
81
|
+
Each file opens with its own **Load this when** line and its revision stamp. This table is
|
|
82
|
+
an index; the trigger lives in the file, so the two cannot drift apart.
|
|
83
|
+
|
|
84
|
+
| File | Read it when |
|
|
85
|
+
|---|---|
|
|
86
|
+
| [`references/mcp.md`](references/mcp.md) | you are **building or calling an MCP server** — the layers, per-request `_meta`, `server/discover`, the three server primitives and the one surviving client primitive, notifications, caching, transports, and the full deprecation register |
|
|
87
|
+
| [`references/mcp-ship.md`](references/mcp-ship.md) | the server is written and **cannot be reached** — mounting inside an existing web app, transport-level auth, client config, and the 404 that is really a double path |
|
|
88
|
+
| [`references/mcp-scale.md`](references/mcp-scale.md) | the host has **more servers and tools than context** — progressive discovery, programmatic tool calling, cache interaction, and the security surface each one opens |
|
|
89
|
+
| [`references/a2a.md`](references/a2a.md) | the other side is **another agent, not a tool** — agent cards and discovery, the task lifecycle and its terminal states, three protocol bindings, streaming versus push |
|
|
90
|
+
| [`references/registry.md`](references/registry.md) | you are **publishing a server** or building something that consumes the registry — `server.json`, reverse-DNS namespaces and how ownership is proved, the publish flow, and the registry's three refusals |
|
|
91
|
+
| [`references/gateway.md`](references/gateway.md) | agent traffic needs **one controlled seam** — what a gateway must do that an API gateway does not, federation and name collisions, and where authorization actually belongs |
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Boundaries — what this skill is not
|
|
96
|
+
|
|
97
|
+
**Against `make-skill`.** `make-skill` owns the *skill author's* view: whether a job wants a
|
|
98
|
+
skill or a server at all, declaring a server dependency in `compatibility`, and the fact that
|
|
99
|
+
tool names differ per host (`mcp__<server>__<tool>` in Claude Code, `mcp__plugin_<plugin>_<server>__<tool>`
|
|
100
|
+
for a plugin's own server). **This skill owns the wire.** If the question is "what does the
|
|
101
|
+
protocol say", it is here; if it is "how does my skill declare that it needs one", it is
|
|
102
|
+
there. The protocol is described in exactly one of the two places, and this is it.
|
|
103
|
+
|
|
104
|
+
**Against `agent-orchestrator`.** That skill routes between *model providers* and manages the
|
|
105
|
+
loop's own context. This one routes between *processes*. They meet at exactly one point: an
|
|
106
|
+
orchestrator that federates many MCP servers is subject to `references/mcp-scale.md`, and one
|
|
107
|
+
that fronts them with a proxy is subject to `references/gateway.md`.
|
|
108
|
+
|
|
109
|
+
**Against `agent-orchestrator/references/governance.md`.** That file decides *whether* a
|
|
110
|
+
boundary may be crossed and what an audit row must carry to prove a control was applied. This
|
|
111
|
+
skill describes *how* the crossing is spoken. Permission there, protocol here.
|
|
112
|
+
|
|
113
|
+
**Not covered at all:** designing the tool set of one server (what tools, what schemas, what
|
|
114
|
+
descriptions — that is a design problem, and Anthropic's `mcp-server-dev` plugin is built for
|
|
115
|
+
it); prompt wording; a single LLM call in a script.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## The neighbourhood — one verdict each
|
|
120
|
+
|
|
121
|
+
Named so an agent stops guessing, with the verdict stated rather than implied.
|
|
122
|
+
|
|
123
|
+
| Thing | What it actually is | Verdict |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| **Agent Skills** (`agentskills.io`) | the open `SKILL.md` format this very file is written in — originally Anthropic's, now an open standard with wide client adoption | **Adopt, but not here.** The family owns it in `make-skill`. Relevant to interop in one way: MCP has a *Skills over MCP* extension, so a server can ship skills — see `references/mcp.md` |
|
|
126
|
+
| **ACP** (IBM's Agent Communication Protocol) | a former A2A competitor | **Dead as a choice.** Merged into A2A under LF AI & Data on 2025-08-29; its team stopped developing it. If you meet ACP in a doc, the answer today is A2A |
|
|
127
|
+
| **AGNTCY** (Cisco/Outshift → Linux Foundation, July 2025) | *not* an A2A rival — an infrastructure stack around multi-agent systems: OASF discovery, agent identity, SLIM messaging, observability. It archived its own competing protocol | **Orthogonal.** Evaluate it for identity and observability if you run many agents; it does not replace A2A or MCP |
|
|
128
|
+
| **AP2** (Agent Payments Protocol) | Google's payments extension **for A2A**, standardising through FIDO Alliance working groups. Signs intent as Verifiable Digital Credentials — Checkout Mandates and Payment Mandates, each with an Open and a Closed stage | **Watch, do not build on it yet.** Explicitly in progress rather than production-ready. It is the right shape for the problem — proving *this user authorized this purchase* — so track it if an agent will ever spend money |
|
|
129
|
+
| **"ChatGPT apps" / OpenAI's plugin surface** | checked, and it is **not a separate protocol**: an MCP server, plus Agent Skills for the workflows, plus optional UI | **Nothing new to learn.** Build the MCP server; the host packaging is the host's |
|
|
130
|
+
| **MCP extensions** — Tasks, MCP Apps, Skills over MCP | opt-in additions to the core protocol, negotiated per connection | **Read before inventing.** Long-running work has a durable-handle answer already; see `references/mcp.md` |
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## The link map — where to go and read
|
|
135
|
+
|
|
136
|
+
Nothing here is summarised well enough to build against. These are the documents.
|
|
137
|
+
|
|
138
|
+
| Read | For | URL |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| MCP specification (current) | the normative requirements; always check the revision it serves | `https://modelcontextprotocol.io/specification/latest` |
|
|
141
|
+
| MCP architecture | the two layers, statelessness, the discovery exchange with real JSON | `https://modelcontextprotocol.io/docs/2026-07-28/learn/architecture` |
|
|
142
|
+
| MCP server concepts | tools, resources, resource templates, prompts — who controls each | `https://modelcontextprotocol.io/docs/2026-07-28/learn/server-concepts` |
|
|
143
|
+
| MCP client concepts | elicitation's two modes and the MRTR pattern; the deprecated client features | `https://modelcontextprotocol.io/docs/2026-07-28/learn/client-concepts` |
|
|
144
|
+
| **MCP deprecation register** | the authoritative list of what is on the way out and its earliest removal | `https://modelcontextprotocol.io/specification/2026-07-28/deprecated` |
|
|
145
|
+
| MCP client best practices | progressive discovery and code mode, with the numbers | `https://modelcontextprotocol.io/docs/2026-07-28/develop/clients/client-best-practices` |
|
|
146
|
+
| Build a server / build a client | the SDK-level walkthroughs | `https://modelcontextprotocol.io/docs/2026-07-28/develop/build-server`, `…/build-client` |
|
|
147
|
+
| MCP + Agent Skills | how skills and servers compose, and the `mcp-server-dev` plugin | `https://modelcontextprotocol.io/docs/2026-07-28/develop/build-with-agent-skills` |
|
|
148
|
+
| MCP registry — about, quickstart | what it is, and the exact publish flow | `https://modelcontextprotocol.io/registry/about`, `https://modelcontextprotocol.io/registry/quickstart` |
|
|
149
|
+
| MCP docs index for machines | fetch this first if you are an agent exploring | `https://modelcontextprotocol.io/llms.txt` |
|
|
150
|
+
| A2A home and specification | v1.0, the three bindings, the normative surface | `https://a2a-protocol.org/latest/`, `https://a2a-protocol.org/latest/specification/` |
|
|
151
|
+
| A2A key concepts / life of a task / discovery | the object model, the lifecycle, the well-known URI | `https://a2a-protocol.org/latest/topics/key-concepts/`, `…/life-of-a-task/`, `…/agent-discovery/` |
|
|
152
|
+
| A2A and MCP | the official statement of how they divide | `https://a2a-protocol.org/latest/topics/a2a-and-mcp/` |
|
|
153
|
+
| agentgateway — standalone, Kubernetes | the config model, and the Gateway API story | `https://agentgateway.dev/docs/standalone/latest/`, `https://agentgateway.dev/docs/kubernetes/latest/` |
|
|
154
|
+
| Source repositories | when the docs are behind the code | `https://github.com/a2aproject/A2A`, `https://github.com/modelcontextprotocol/modelcontextprotocol`, `https://github.com/modelcontextprotocol/registry`, `https://github.com/agentgateway/agentgateway` |
|
|
155
|
+
|
|
156
|
+
**Fetch the `llms.txt` first when you are an agent.** Both `modelcontextprotocol.io` and
|
|
157
|
+
`agentgateway.dev` publish one, and both are versioned per docs release — which is how you
|
|
158
|
+
find the page that exists rather than the page you remember.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Checklist — shipping anything that speaks these protocols
|
|
163
|
+
|
|
164
|
+
- [ ] The revision you build against is **written down** — in `compatibility`, a constant, or a README line
|
|
165
|
+
- [ ] You read the deprecation register before using a client feature
|
|
166
|
+
- [ ] Version mismatch has a handled path, not a crash
|
|
167
|
+
- [ ] Tool output is treated as **untrusted input**, including output from your own servers
|
|
168
|
+
- [ ] Nothing secret is requested through an elicitation form — that is URL mode's job
|
|
169
|
+
- [ ] Long-running work uses a durable handle rather than a held connection
|
|
170
|
+
- [ ] If you federate: name collisions are resolved deliberately, not by load order
|
|
171
|
+
- [ ] If you publish: the namespace is one you can prove you own
|
|
172
|
+
- [ ] Authorization is enforced per hop, not only at the entrance
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# A2A — when the other side is an agent, not a tool
|
|
2
|
+
|
|
3
|
+
**Load this when:** you are delegating an outcome to somebody else's autonomous agent,
|
|
4
|
+
publishing your own as callable, or choosing between A2A and MCP.
|
|
5
|
+
|
|
6
|
+
**Spec pinned:** A2A **v1.0**, `https://a2a-protocol.org/latest/specification/` · read 2026-08-13
|
|
7
|
+
|
|
8
|
+
Governance: created by Google, transferred to the **Linux Foundation**, Apache-2.0, run by a
|
|
9
|
+
Technical Steering Committee with AWS, Cisco, Google, IBM Research, Microsoft, Salesforce,
|
|
10
|
+
SAP and ServiceNow.
|
|
11
|
+
|
|
12
|
+
**The v0.x → v1.0 rename is the trap here.** The wire surface changed names between them, and
|
|
13
|
+
plenty of SDKs, tutorials and blog posts still document v0.3. A document that mixes the two
|
|
14
|
+
is wrong against at least one of them. Check every field name against the version you target.
|
|
15
|
+
|
|
16
|
+
## Contents
|
|
17
|
+
|
|
18
|
+
- The five design principles, and what each one bought
|
|
19
|
+
- The object model
|
|
20
|
+
- Discovery — the agent card
|
|
21
|
+
- The task lifecycle
|
|
22
|
+
- Three protocol bindings
|
|
23
|
+
- Getting results back
|
|
24
|
+
- Security
|
|
25
|
+
- Traps
|
|
26
|
+
|
|
27
|
+
## The five design principles, and what each one bought
|
|
28
|
+
|
|
29
|
+
Stated at announcement, and each is visible in the protocol:
|
|
30
|
+
|
|
31
|
+
| Principle | What it produced |
|
|
32
|
+
|---|---|
|
|
33
|
+
| **Embrace agentic capabilities** | agents collaborate without shared memory, tools or context — the peer is opaque by design |
|
|
34
|
+
| **Build on existing standards** | HTTP, SSE, JSON-RPC rather than a novel transport |
|
|
35
|
+
| **Secure by default** | enterprise authentication and authorization, aligned with OpenAPI's auth schemes |
|
|
36
|
+
| **Support for long-running tasks** | a task lifecycle that spans hours or days, with progress reported |
|
|
37
|
+
| **Modality agnostic** | parts carry more than text — audio, video, binary, structured data |
|
|
38
|
+
|
|
39
|
+
**The first one is the design decision that matters.** A2A's peer is deliberately a black
|
|
40
|
+
box: you send an outcome, not a plan. If your design needs to see inside the other agent,
|
|
41
|
+
A2A is the wrong protocol and you probably want an MCP server.
|
|
42
|
+
|
|
43
|
+
## The object model
|
|
44
|
+
|
|
45
|
+
| Object | What it is | Key fields |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| **AgentCard** | JSON metadata describing identity, capabilities, endpoint, skills and auth requirements | name, description, version, provider, capabilities, skills, security schemes |
|
|
48
|
+
| **Task** | a **stateful unit of work** with a unique id and a lifecycle | `id`, `contextId`, `status`, `artifacts`, `history`, `metadata` |
|
|
49
|
+
| **Message** | one turn of communication | `role` (`user` or `agent`), parts |
|
|
50
|
+
| **Part** | the fundamental content container inside messages and artifacts | one of `text`, `raw` (bytes), `url`, `data` (JSON); plus optional `mediaType`, `filename`, `metadata` |
|
|
51
|
+
| **Artifact** | a tangible output produced during a task | `artifactId`, human-readable name, one or more parts |
|
|
52
|
+
|
|
53
|
+
**`contextId` is the piece people miss.** It is server-generated and groups multiple related
|
|
54
|
+
tasks across interactions — the thing that makes a sequence of delegations one conversation
|
|
55
|
+
rather than a pile of unrelated jobs.
|
|
56
|
+
|
|
57
|
+
**`skills[]` on an agent card is not an Agent Skills `SKILL.md`.** A2A borrowed the word
|
|
58
|
+
for *an advertised capability of a remote agent* — `id`, `name`, `description`, `tags`,
|
|
59
|
+
`examples`, `inputModes`, `outputModes`. Agent Skills are instruction folders loaded into a
|
|
60
|
+
model's context. Two unrelated things, one word. Keep them apart in anything you write, or
|
|
61
|
+
every reader loses an hour.
|
|
62
|
+
|
|
63
|
+
## Discovery — the agent card
|
|
64
|
+
|
|
65
|
+
The standard location, following RFC 8615:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
https://{agent-server-domain}/.well-known/agent-card.json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Pre-0.3 deployments served `/.well-known/agent.json`** — expect both in the wild.
|
|
72
|
+
|
|
73
|
+
Top-level card fields in 1.0 — confirm against the live schema before implementing:
|
|
74
|
+
`name`, `description`, `version`, `provider`, `iconUrl`, `documentationUrl`,
|
|
75
|
+
`supportedInterfaces`, `capabilities`, `securitySchemes`, `securityRequirements`,
|
|
76
|
+
`defaultInputModes`, `defaultOutputModes`, `skills`, `extensions`, `signatures`.
|
|
77
|
+
|
|
78
|
+
**`capabilities` gates what you may attempt** — `streaming`, `pushNotifications`,
|
|
79
|
+
`extendedAgentCard`, `extensions`. Read it and branch; never assume streaming or push
|
|
80
|
+
exists because the docs describe them.
|
|
81
|
+
|
|
82
|
+
**Cards can be signed.** An unsigned card at a well-known URI is a claim, not proof —
|
|
83
|
+
verify `signatures` whenever the peer is not first-party.
|
|
84
|
+
|
|
85
|
+
A plain HTTP GET returns the card. Four discovery strategies exist, and they are not equal:
|
|
86
|
+
|
|
87
|
+
1. **Well-known URI** — the standard, and what you should publish.
|
|
88
|
+
2. **Authenticated extended cards** — fetched via `GetExtendedAgentCard`. This is the
|
|
89
|
+
recommended way to expose sensitive capability information: **selective disclosure by
|
|
90
|
+
client permission**, rather than a static public card carrying secrets.
|
|
91
|
+
3. **Curated registries** — catalogues queryable by skill, tag or provider. Note the honest
|
|
92
|
+
gap: **the current specification does not prescribe a standard API for them**, so anything
|
|
93
|
+
you build against one is vendor-specific.
|
|
94
|
+
4. **Direct configuration** — hardcoded URLs. Fine for a fixed pair of agents, and it does
|
|
95
|
+
not scale or standardize.
|
|
96
|
+
|
|
97
|
+
**Never put a secret in the public card.** That is what the extended card exists for.
|
|
98
|
+
|
|
99
|
+
## The task lifecycle
|
|
100
|
+
|
|
101
|
+
The enum, spelled exactly as the specification defines it:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
TASK_STATE_UNSPECIFIED
|
|
105
|
+
TASK_STATE_SUBMITTED
|
|
106
|
+
TASK_STATE_WORKING
|
|
107
|
+
TASK_STATE_INPUT_REQUIRED <- interrupted, awaiting the client
|
|
108
|
+
TASK_STATE_AUTH_REQUIRED <- interrupted, awaiting credentials
|
|
109
|
+
TASK_STATE_COMPLETED <- terminal
|
|
110
|
+
TASK_STATE_CANCELED <- terminal
|
|
111
|
+
TASK_STATE_REJECTED <- terminal
|
|
112
|
+
TASK_STATE_FAILED <- terminal
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Terminal means terminal: a task that reached completed, canceled, rejected or failed cannot
|
|
116
|
+
restart.** Continuing work means a *new* task, linked by `contextId`. Client code that
|
|
117
|
+
retries by re-sending to the same `taskId` after a failure is coding against a state machine
|
|
118
|
+
that does not exist.
|
|
119
|
+
|
|
120
|
+
**Interrupted is not failed.** `INPUT_REQUIRED` and `AUTH_REQUIRED` are the protocol asking
|
|
121
|
+
you for something and holding the work open. A client that treats every non-`COMPLETED`
|
|
122
|
+
status as an error abandons tasks that were waiting for one field.
|
|
123
|
+
|
|
124
|
+
## Three protocol bindings
|
|
125
|
+
|
|
126
|
+
The specification defines three, and an agent may implement any of them:
|
|
127
|
+
|
|
128
|
+
| Binding | Section | Use when |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| **JSON-RPC** | §9 | the default; broadest tooling |
|
|
131
|
+
| **gRPC** | §10 | you already run gRPC and want streaming and typed stubs |
|
|
132
|
+
| **HTTP+JSON/REST** | §11 | plain REST clients, easiest to inspect and curl |
|
|
133
|
+
|
|
134
|
+
**A server declares which bindings it supports on its card; the client picks one.**
|
|
135
|
+
|
|
136
|
+
| Functionality | JSON-RPC / gRPC | REST |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| Send message | `SendMessage` | `POST /message:send` |
|
|
139
|
+
| Send streaming message | `SendStreamingMessage` | `POST /message:stream` |
|
|
140
|
+
| Get task | `GetTask` | `GET /tasks/{id}` |
|
|
141
|
+
| List tasks | `ListTasks` | `GET /tasks` |
|
|
142
|
+
| Cancel task | `CancelTask` | `POST /tasks/{id}:cancel` |
|
|
143
|
+
| Subscribe to task | `SubscribeToTask` | `POST /tasks/{id}:subscribe` |
|
|
144
|
+
| Create push config | `CreateTaskPushNotificationConfig` | `POST /tasks/{id}/pushNotificationConfigs` |
|
|
145
|
+
| Get push config | `GetTaskPushNotificationConfig` | `GET /tasks/{id}/pushNotificationConfigs/{configId}` |
|
|
146
|
+
| List push configs | `ListTaskPushNotificationConfigs` | `GET /tasks/{id}/pushNotificationConfigs` |
|
|
147
|
+
| Delete push config | `DeleteTaskPushNotificationConfig` | `DELETE /tasks/{id}/pushNotificationConfigs/{configId}` |
|
|
148
|
+
| Extended card | `GetExtendedAgentCard` | `GET /extendedAgentCard` |
|
|
149
|
+
|
|
150
|
+
**The v0.3.x names, so you recognize inherited code on sight:** slash-style JSON-RPC methods
|
|
151
|
+
— `message/send`, `message/stream`, `tasks/get`, `tasks/cancel`, `tasks/resubscribe`,
|
|
152
|
+
`tasks/pushNotificationConfig/{set,get,list,delete}`,
|
|
153
|
+
`agent/getAuthenticatedExtendedCard`. If you meet those, it is a **v0.x client**. Do not
|
|
154
|
+
"fix" the names to 1.0 without moving the whole contract — half-migrated is worse than
|
|
155
|
+
either version, and it works until it reaches the one field nobody updated.
|
|
156
|
+
|
|
157
|
+
The same drift runs through the states: 1.0 uses proto-style constants
|
|
158
|
+
(`TASK_STATE_COMPLETED`), v0.x used lowercase wire values (`submitted`, `working`,
|
|
159
|
+
`input-required`). A document showing both has been half-migrated.
|
|
160
|
+
|
|
161
|
+
## Getting results back
|
|
162
|
+
|
|
163
|
+
Three mechanisms, matched to how long the work takes and whether you can hold a connection:
|
|
164
|
+
|
|
165
|
+
| Mechanism | Shape | Right when |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| **Request/response with polling** | `SendMessage`, then `GetTask` on an interval | always available; work measured in seconds to minutes |
|
|
168
|
+
| **Streaming (SSE)** | `SendStreamingMessage` / `SubscribeToTask`; needs `capabilities.streaming` | you want incremental output and can hold the connection |
|
|
169
|
+
| **Push notifications** | server calls a webhook you registered; needs `capabilities.pushNotifications` | work spans hours or days, or the client is not always up |
|
|
170
|
+
|
|
171
|
+
Stream events are typed: `TaskStatusUpdateEvent` and `TaskArtifactUpdateEvent`.
|
|
172
|
+
|
|
173
|
+
**Push is the one that makes long-running real.** Streaming dies with the connection;
|
|
174
|
+
polling for six hours is a poor use of everyone's time. If your delegated work can outlive a
|
|
175
|
+
request, register a push config and design for the callback.
|
|
176
|
+
|
|
177
|
+
**Design for all three failing.** A long task whose stream drops must be recoverable **by
|
|
178
|
+
id** — which is precisely why A2A gives tasks ids and states instead of making them
|
|
179
|
+
fire-and-forget calls. Polling is the floor you fall back to.
|
|
180
|
+
|
|
181
|
+
## Security
|
|
182
|
+
|
|
183
|
+
- **Enterprise auth from the start** — the card declares its security schemes, aligned with
|
|
184
|
+
OpenAPI's authentication approaches: API key, HTTP auth, OAuth2, OpenID Connect, mutual
|
|
185
|
+
TLS. Read the card and satisfy what it declares; do not assume bearer tokens.
|
|
186
|
+
- **Scope the token to the task.** Authorization is per skill and per task; handing a peer
|
|
187
|
+
a token broader than the work is how one delegation becomes an account compromise.
|
|
188
|
+
- **Verify card signatures for any peer that is not first-party.** A well-known URI proves
|
|
189
|
+
where the file sits, not who wrote it.
|
|
190
|
+
- **`AUTH_REQUIRED` is a protocol state**, not an error path bolted on. Handle it.
|
|
191
|
+
- **The peer is opaque, and that cuts both ways.** You cannot verify how it reached its
|
|
192
|
+
result, so anything it returns is untrusted input to your system — the same rule as tool
|
|
193
|
+
output, with less recourse.
|
|
194
|
+
- **Trace across hops.** A chain of agents compounds errors, and policy has to be enforced at
|
|
195
|
+
**each hop**, not only at the entrance. See `agent-orchestrator/references/governance.md`
|
|
196
|
+
for the control set; this file only says which wire it rides.
|
|
197
|
+
|
|
198
|
+
## Traps
|
|
199
|
+
|
|
200
|
+
- **Building against v0.3 field names** because that is what the tutorial showed. Check the
|
|
201
|
+
version.
|
|
202
|
+
- **Retrying into a terminal task.** New task, same `contextId`.
|
|
203
|
+
- **Treating `INPUT_REQUIRED` as a failure.** It is a question.
|
|
204
|
+
- **Publishing capability detail in the public card** instead of the authenticated extended
|
|
205
|
+
card.
|
|
206
|
+
- **Choosing A2A for something with a JSON schema and one call.** That is a tool. The cost of
|
|
207
|
+
A2A is a lifecycle, a card and a state machine; pay it when the other side is genuinely
|
|
208
|
+
autonomous.
|
|
209
|
+
- **Assuming a registry API is standard.** It is not, yet.
|