How lifecycle-aware transaction envelopes travel over agent-to-agent transport, so state survives the hop between systems that have never met.
Agents increasingly hand work to other agents. A shopping assistant reaches a dealership agent. A service agent reaches a fleet operator. What breaks in that handoff is not the message. It is the state. The receiving agent gets a request and no history.
ACP addresses that by exchanging complete transaction state rather than isolated messages. This page defines how an ACP envelope travels over A2A, so an agent already speaking A2A can send and receive ACP state without implementing a separate client.
| Layer | Protocol | Responsibility |
|---|---|---|
| Agent Transport | A2A | Standardizes how agents discover each other and exchange messages. |
| Transaction State | ACP | Standardizes lifecycle-aware transaction state exchange between business systems. |
ACP is transport-agnostic. HTTPS is the primary delivery path and remains so. This binding adds A2A as a second path. It changes nothing about the envelope.
An ACP envelope delivered over A2A is byte-identical to the same envelope delivered over HTTPS. That constraint is the whole design. A binding that alters the payload is not a binding — it is a fork.
The Agent2Agent protocol (A2A) standardizes how independent agents find one another and communicate. It governs discovery, message structure, and transport.
A2A defines:
DataPart carries structured JSON.A2A operates at the transport layer — it governs how agents reach each other. It is agnostic to what they are talking about.
The Automotive Commerce Protocol (ACP) standardizes lifecycle-aware transaction state exchange between business systems. It defines versioned snapshot and delta envelopes for deterministic state progression.
ACP defines:
acp, source, dealership, lead, transaction,
conversation, events, ai_analysis) that capture the full transaction lifecycle.
ACP operates at the business state layer — it governs what the transaction looks like at any point in time. It is agnostic to how the envelope arrived.
An ACP envelope travels as a single DataPart inside an A2A message.
A2A Message
parts[0]
kind: "data"
data: <ACP envelope>
The value of parts[].data must be a complete, schema-valid ACP envelope. It must not be flattened, unwrapped, partially sent, or split across parts.
A message carrying more than one envelope is non-conformant. To send several envelopes, send several messages. This keeps the unit of validation and the unit of delivery the same thing.
A receiving agent validates before acting. An envelope that fails validation is rejected whole. Partial ingestion is non-conformant, because a half-ingested envelope leaves the receiver in a state no snapshot describes.
Snapshot and delta are distinguished exactly as in ACP core. A delta carries parent_envelope_id. A snapshot does not. This binding introduces no discriminator field and no new envelope kind.
An agent declares which kinds it accepts and emits in its agent card. An agent that only ever sends complete state declares emits: ["snapshot"] and never has to implement delta construction.
When a delta arrives referencing a parent the receiver does not hold, the receiver returns ACP_PARENT_UNKNOWN. The sender responds by issuing a snapshot rather than retrying the delta. This is the recovery path for
agents meeting for the first time mid-transaction.
An agent may ask for the current snapshot of a transaction. This is the only message the binding defines that is not an ACP envelope, because ACP core has no request form.
{
"type": "org.acpspec.a2a.state_request",
"transaction_ref": "example-motors:txn:88213"
}
Exactly one of envelope_id or transaction_ref is present. The response is a snapshot in a DataPart, or an error object.
A state request never returns a delta. A delta is only meaningful relative to a parent the requester already holds, and the requester has just declared that it does not.
A state request asks about a transaction that already exists. For the question that comes before one does — what a dealer has in stock — see the Inventory Read Profile, a separate read surface that produces no envelopes.
An agent declares ACP support by listing the extension URI in capabilities.extensions[] of its A2A agent card.
{
"name": "Example Motors",
"url": "https://example-motors.com/a2a",
"version": "1.0.0",
"capabilities": {
"extensions": [
{
"uri": "https://acpspec.org/extensions/a2a/v0.1",
"description": "Automotive Commerce Protocol envelope exchange",
"required": false,
"params": {
"acp_version": "1.0.0",
"schema_url": "https://example-motors.com/schema/acp-v1.0.0.json",
"accepts": ["snapshot", "delta"],
"emits": ["snapshot", "delta"]
}
}
]
}
}
acp_version and schema_url are required, and schema_url must resolve to the JSON Schema document for the declared acp_version. The value above is
illustrative — publishers point it at their own resolvable schema location. accepts and emits are required and each contain at least one value.
The extension URI versions the binding. acp_version versions the envelope. The two version independently, so a transport revision never forces a schema migration.
A buyer agent detects financing intent during a conversation and sends a delta to the dealership agent.
{
"jsonrpc": "2.0",
"id": "1",
"method": "message/send",
"params": {
"message": {
"role": "agent",
"messageId": "01JAR7WQ5M4Z8YB3T2K9XFHNPD",
"parts": [
{
"kind": "data",
"data": {
"acp": {
"version": "1.0.0",
"protocol": "acp",
"envelope_id": "acp_1707900000_d4f8",
"parent_envelope_id": "acp_1707899000_a1b2",
"generated_at": "2026-08-04T17:22:10Z"
},
"source": {
"system": "example-buyer-agent",
"transport": "a2a"
},
"events": [
{
"event_type": "INTENT_DETECTED",
"timestamp": "2026-08-04T17:22:10Z",
"data": {
"intent": "FINANCING",
"confidence": 0.91,
"source": "a2a:example-buyer-agent"
}
}
]
}
}
]
}
}
}
The source.transport value records that the envelope arrived over A2A. Downstream systems can distinguish delivery paths without inspecting envelope contents, which matters when the same transaction is touched by an
HTTPS integration and an agent in the same hour.
Errors occurring after a well-formed A2A message is received are returned as an ACP error object in a DataPart, not as an A2A transport error. Authentication failures, malformed JSON-RPC, and transport faults use A2A
error semantics and are not redefined here.
| Code | Meaning |
|---|---|
ACP_VERSION_UNSUPPORTED |
Declared envelope version not supported by this agent |
ACP_SCHEMA_INVALID |
Envelope failed schema validation |
ACP_PARENT_UNKNOWN |
Delta references a parent the receiver does not hold |
ACP_CONSENT_REQUIRED |
Personal data present without consent state |
ACP_CONSENT_REFUSED |
Subject consent state prohibits ingestion |
ACP_ENVELOPE_NOT_FOUND |
Requested envelope or transaction does not exist |
ACP_KIND_NOT_ACCEPTED |
Envelope kind not listed in the receiver's accepts |
ACP_RATE_LIMITED |
Request rejected for rate |
{
"type": "org.acpspec.a2a.error",
"code": "ACP_SCHEMA_INVALID",
"message": "envelope failed validation against acp-envelope-v1.0.0",
"details": [
{ "path": "/lead/contact/email", "reason": "format" }
]
}
ACP envelopes are valid and complete without any A2A involvement. Any transport that can carry a JSON document can carry an ACP envelope. A2A is one delivery path among several.
ACP does not profile A2A. A profile constrains the base protocol and inherits its scope. This binding does neither. It describes carriage and leaves both specifications intact.
Consent rules are defined in ACP core and are unchanged by transport. This section states how they survive the hop.
An envelope carrying an identified natural person carries that person's consent state. A receiving agent enforces the most restrictive state it holds for that subject. An inbound envelope cannot upgrade a subject's consent state.
Where an inbound envelope asserts a weaker state than the receiver holds, the receiver's state prevails and the conflict is recorded as an event rather than discarded. The disagreement is itself information, and a system that silently drops it loses the audit trail that made the enforcement defensible.
An agent that cannot establish consent rejects the envelope with ACP_CONSENT_REQUIRED. It does not ingest and resolve consent afterward. Enforcement happens at the boundary, before any payload reaches a downstream
system.
An implementation conforms to this binding when all of the following hold.
acp_version, and a resolvable schema_url.accepts and emits only kinds listed in emits.DataPart.The last requirement is the one that matters. If an envelope differs between bindings, the implementation has forked ACP and does not conform.
Envelopes carrying personal data travel over TLS. An agent card advertising ACP carriage over a non-TLS endpoint is non-conformant regardless of what else it satisfies.