RFC-5: Agent Mesh Protocol
Abstract
The Agent Mesh Protocol (AMP) defines how agents and people exchange messages and tasks through a broker. Participants hold one outbound session each. The broker resolves addresses, routes tasks by job, stores them durably with leases, and enforces policy.
Changelog
1. Introduction
The Agent Mesh Protocol (AMP) is an open protocol for communication between autonomous agents, and between agents and people, through a broker. Each participant holds one outbound connection to a broker. The broker resolves addresses, routes work to participants by job, stores tasks durably, and enforces policy.
AMP complements two existing protocols:
- The Model Context Protocol (MCP) connects an agent to its tools and data. AMP does not replace it.
- The Agent2Agent protocol (A2A) connects agents point to point over HTTPS. AMP reuses A2A’s task states and part types, and defines a gateway so the two interoperate (section 15).
1.1 Design principles
- Dial out only. A participant never needs to accept inbound connections. It works behind NAT, inside private networks, and on intermittent hosts.
- Address work, not hosts. A sender can address a job. The broker chooses who does the work.
- Durable by default. A task outlives the connection, the process, and the host that started it.
- One point of policy. Authorization, rate limits, and budgets are enforced at the broker, so a participant cannot bypass them.
- Opaque participants. A participant exposes jobs, never its internals: no shared memory, prompts, or tools.
- Transport neutral. AMP defines messages and semantics. Bindings map them onto a transport (section 4) and onto broker implementations (Appendix C).
1.2 Conventions
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL are to be interpreted as described in RFC 2119 and RFC 8174 when, and only when, they appear in all capitals.
- All objects are JSON (RFC 8259) encoded as UTF-8. Field names are
snake_case. - Timestamps are RFC 3339 strings in UTC.
- Durations are integers in seconds unless the field name ends in
_ms. - The normative schema is the JSON Schema. Where this document and the schema disagree, the schema wins.
- Receivers MUST ignore unknown fields. Senders MUST NOT rely on a receiver understanding a field the version it negotiated does not define.
2. Roles and architecture
A broker has four logical components. An implementation MAY split or merge them.
Brokers MAY federate (section 13). A participant always talks to exactly one broker; federation is invisible to it.
3. Identifiers and addressing
3.1 Namespaces
A namespace is an isolation boundary. Addresses, jobs, and topics are scoped to one namespace. A namespace name MUST match ^[a-z0-9][a-z0-9-]{0,62}$.
3.2 Participant addresses
A participant address is <namespace>/<name>, where <name> matches ^[a-z0-9][a-z0-9._-]{0,127}$. Example: acme/analyst.
The broker assigns or confirms the address during session setup (section 5.1). A participant MUST NOT choose an address outside the namespaces its credential permits.
3.3 Targets
The to field of an envelope is a target:
A job or topic without a namespace resolves in the sender’s namespace. A target in another namespace MUST be fully qualified, and the broker MUST reject it unless a policy grant allows it (section 11).
Job and topic names match ^[a-z0-9][a-z0-9._-]{0,127}$.
3.4 Message and task identifiers
id(message): chosen by the sender, unique per sender for at least 24 hours. RECOMMENDED: a UUIDv7 or ULID.task_id: chosen by the broker when a task is created. Opaque to participants.
3.5 Scopes
A broker MAY partition a namespace into scopes. A scope bounds a piece of work: who it may reach, and what the broker lets it read and write.
- A scope name matches
^[a-z0-9][a-z0-9._-]{0,127}$and is unique within its namespace. - The broker maps every credential to a set of scopes in its namespace (section 10). The set MAY be empty.
- A participant with no scopes belongs to the namespace’s default scope, named
default. A participant with one or more scopes does not.defaultis reserved and MUST NOT name another scope. - A participant keeps one address in every scope it belongs to.
- The broker lists the participant’s scopes in
welcome(section 5.1).
In a partitioned namespace, the scope travels with every interaction. Every envelope a participant sends MUST set scope, every envelope the broker delivers carries it, and every task records it. The broker MUST NOT infer a missing scope.
A broker that does not partition namespaces MUST reject an envelope that sets scope with invalid_envelope. It MUST NOT deliver it unscoped.
4. Transport
4.1 Sessions
A session is one long-lived, ordered, bidirectional stream of frames between a participant and a broker. AMP defines two transport bindings. A broker MUST support at least one. A broker SHOULD support WebSocket.
All sessions MUST run over TLS 1.2 or later.
4.2 Frames
Every frame is a JSON object with a type and a session-unique seq (a positive integer, increasing per direction).
A frame that answers another carries re, the seq of the frame it answers.
5. Session lifecycle
5.1 Opening
- The participant opens the transport and sends
hello:
- The broker authenticates the credential (section 10), selects the highest common version, registers the card, and replies with
welcome:
- If authentication fails or no version is common, the broker sends
errorand closes the transport.
A participant MUST NOT send any frame other than hello before it receives welcome.
5.2 Heartbeats
The participant MUST send heartbeat at least once per heartbeat_interval_s. A broker MUST consider the session dead after three missed intervals. A heartbeat extends every lease the participant holds (section 8.3).
5.3 Closing and reconnecting
Either side MAY send goodbye and close. On reconnect, a participant sends a new hello. The broker MUST redeliver every envelope that it delivered and that was not acknowledged. A new session has a new session_id; leases from the old session survive only until they expire.
6. Objects
6.1 Card
A card describes a participant. It is sent in hello and held by the registry while the session is alive.
A Job:
6.2 Envelope
6.3 Part
A receiver that does not accept a part type MUST answer with error code unsupported_part.
6.4 Task
A Status is { "state", "at", "by", "message" }, where message is an optional Part array.
An Artifact is { "artifact_id", "name", "parts", "final" }. final is true on the last chunk of a streamed artifact.
6.5 Error
7. Messaging
7.1 Envelope kinds
7.2 Sending
A participant sends send with an envelope. The broker MUST, in order:
- Validate the envelope against the schema. On failure:
invalid_envelope. - Set
fromandsent_at. - Evaluate policy (section 11). On failure: the policy error code.
- Resolve the target. A participant target that does not exist:
unknown_target. - Persist the envelope (and, for
task, create the task). - Reply
acceptedwith{ "id", "task_id"? }.
A broker MUST NOT deliver an envelope before it has sent accepted, and MUST NOT deliver an envelope it rejected.
7.3 Delivering and acknowledging
The broker sends deliver with the envelope and a delivery_id. The participant MUST answer with ack or nack referencing that delivery_id. Unacknowledged deliveries are redelivered after ack_wait_s (default 30) and on reconnect.
event envelopes are delivered to each subscriber independently. A subscriber that joins later does not receive earlier events unless it asks for replay with subscribe and from (a timestamp or sequence).
8. Tasks
8.1 States
submitted, working, input-required, completed, failed, canceled, rejected.
completed, failed, canceled, and rejected are terminal. A broker MUST reject any change to a task in a terminal state with task_final.
8.2 Offering and claiming
When a task is submitted, the router selects a participant (section 9) and delivers the task envelope to it as an offer. The offered participant claims it with claim { task_id } or declines with nack. On a claim, the broker grants a lease with granted { task_id, lease_id, expires_at } and moves the task to working. In a partitioned namespace, granted also carries a scope grant (section 11.1).
A participant MUST NOT send status for a task without a valid lease, except a requester sending canceled or a reply to input-required.
8.3 Leases
- A lease lasts
lease_s(default 60). - Every
heartbeatextends every lease the session holds bylease_sfrom receipt. release { task_id }ends a lease and returns the task tosubmitted.- When a lease expires, the broker MUST treat any later
statusfrom the old holder aslease_lost. - At most one valid lease exists per task.
8.4 Progress and artifacts
The assignee reports progress with status envelopes in state working. It attaches results with status envelopes that set artifact; the artifact’s content is the envelope’s parts. A streamed artifact is sent as several envelopes with the same artifact_id, the last with final: true. The broker appends each artifact to the task and forwards the status to the requester.
8.5 Reading a task
A requester or assignee MAY read a task with query { "task": "<task_id>" }. The broker returns the Task object in result.
9. Routing
For a job target, the broker MUST choose among eligible participants:
- In the resolved namespace.
- With a live session.
- Advertising the job.
- Accepting every part type in the envelope.
- Holding fewer leases than its
max_concurrent. - Permitted by policy to receive from the sender.
- A member of the envelope’s scope, or of the default scope when the envelope has none.
Among eligible participants, a broker SHOULD choose the one with the fewest active leases, breaking ties round robin. A broker MAY use another strategy and MUST document it.
If no participant is eligible, the task stays submitted and is offered when one becomes eligible, until expires_at.
A broker MUST NOT offer the same task to two participants at once.
10. Authentication and identity
- A participant authenticates in
hellowith a credential. AMP definesbearer(a token) andmtls(the TLS client certificate). A broker MAY define others. - The broker MUST map every credential to exactly one address and a set of permitted namespaces.
- Credentials SHOULD be short-lived. A RECOMMENDED pattern is token exchange: the participant presents a credential it already holds from its platform, and the broker’s auth service issues a broker-scoped token.
- The broker MUST set
fromfrom the authenticated identity, never from participant input. - A gateway MAY act for external parties. It MUST record the external identity in
metadata.on_behalf_of, and policy decides whether a gateway may do so.
11. Policy
The broker MUST evaluate policy on every send, claim, and subscribe. AMP specifies the decisions, not the policy language.
A broker MUST NOT reveal through errors whether a target exists in a namespace the sender may not address. It answers forbidden for both.
A broker that partitions namespaces (section 3.5) MUST also apply these scope rules on every send:
A participant in no scope sends in default and reaches only default. The broker answers forbidden for a target outside the scope whether or not the target exists.
11.1 Scope grants
A scope grant lets a participant prove to another service that it is doing current work in a scope. A broker that partitions namespaces MUST issue grants. Services outside the broker, such as a document store, verify them without calling the broker.
A grant is a JWS in compact form, signed with Ed25519 (alg: EdDSA).
The broker issues grants as follows:
A grant expires grant_s seconds after it is issued. The broker states grant_s in welcome limits. RECOMMENDED: 300.
The broker MUST publish its public keys as a JWK Set at /.well-known/jwks.json on its HTTP listener, and MUST keep a retired key there until every grant it signed has expired. A verifier MUST check the signature, aud, exp, and that scope matches the resource it guards. It SHOULD also check that sub is still a member of the scope.
12. Errors
13. Federation
Brokers MAY federate to span regions or organizations.
- Every namespace has one home broker, which owns its task store and evaluates its policy.
- A broker that receives a
sendfor a namespace it does not own MUST forward it to the home broker and relay the result. - Federated brokers exchange registry summaries (jobs and presence per namespace) so routing decisions can include remote participants.
- Brokers authenticate each other with mutual TLS.
Federation does not change the participant-facing protocol.
14. Delivery semantics
- At least once. A participant MUST tolerate duplicate deliveries. It SHOULD deduplicate on
(from, id). - Idempotent tasks. A broker MAY re-offer a task after a lease expires. A participant SHOULD make work idempotent by
task_id. - Ordering. Envelopes from one sender to one receiver are delivered in send order. No other ordering is guaranteed.
- Limits. A broker MUST reject an envelope larger than
max_envelope_byteswithtoo_large. The default is 1 MiB. Large content goes byfilepart. - Expiry. A broker MUST NOT deliver an envelope after its
ttl_shas passed.
15. Interoperability with A2A
A gateway exposes mesh jobs to A2A clients, and A2A agents to the mesh.
15.1 Inbound (A2A client to mesh)
- The gateway publishes an A2A agent card whose jobs are the mesh jobs it exposes.
message/sendandmessage/streamcreate ataskenvelope addressed to the job.tasks/getmaps toquery { task }.tasks/cancelmaps to astatusenvelope withstate: canceled.message/streamevents are the task’sstatusenvelopes.
15.2 Outbound (mesh to A2A agent)
The gateway registers as a participant advertising the remote agent’s jobs. When it is offered a task, it claims it, calls the remote agent’s message/send, and translates the response into status envelopes.
15.3 Mapping
16. Observability
- A sender SHOULD set
trace.traceparent. The broker MUST forwardtraceunchanged and SHOULD record spans for policy, routing, and leasing. - A broker SHOULD expose, per namespace and job: queue depth, time to claim, lease expiries, task outcomes, and rejections by error code.
17. Security considerations
- Impersonation. Prevented by broker-set
from(section 6.2). Receivers MUST trustfromonly as delivered by their broker. - Content injection. Parts are untrusted input. A participant MUST treat delivered text, files, and data as data, not instructions, unless its own policy says otherwise.
- File references. A
fileURI can point anywhere. A receiver SHOULD fetch only from origins it trusts and SHOULD verifysha256when present. - Enumeration. Section 11 forbids existence leaks across namespaces.
- Replay. Deduplication by
(from, id)within 24 hours bounds replay. Credentials SHOULD be short-lived. - Denial of service. Rate limits, budgets,
max_concurrent, andmax_envelope_bytesbound the load one participant can create.
18. Versioning and extensions
- The protocol version is
MAJOR.MINOR. Drafts below 1.0 use the transport namev1alpha1(the WebSocket subprotocol and the gRPC package); 1.0 will usev1. A minor version only adds optional fields and frame types. A major version may break compatibility. - Version negotiation happens in
helloandwelcome(section 5.1). - Extensions use fields and frame types prefixed with
x-or a reverse-DNS name (com.example.priority). A receiver MUST ignore extensions it does not understand.
Appendix A. Example: delegating by job
Appendix B. Schemas
- JSON Schema:
amp.schema.json - Protocol Buffers (gRPC binding):
amp.proto