ACP + A2A: Transaction State Between Agents

How lifecycle-aware transaction envelopes travel over agent-to-agent transport, so state survives the hop between systems that have never met.

Architectural context: This page describes how two independent protocols — ACP and A2A — can interoperate. It is informational, not normative. Neither protocol requires the other.

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.

Positioning

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.

What A2A Does

The Agent2Agent protocol (A2A) standardizes how independent agents find one another and communicate. It governs discovery, message structure, and transport.

A2A defines:

  1. Agent cards — A JSON document at a well-known path describing an agent's identity, capabilities, and endpoints.
  2. Typed message parts — A message carries one or more parts, each with a declared kind. A DataPart carries structured JSON.
  3. Bindings — JSON-RPC 2.0 and HTTP+JSON deliver the same messages over different wire conventions.

A2A operates at the transport layer — it governs how agents reach each other. It is agnostic to what they are talking about.

What ACP Does

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:

  1. Envelope structure — Eight top-level objects (acp, source, dealership, lead, transaction, conversation, events, ai_analysis) that capture the full transaction lifecycle.
  2. Snapshot & delta semantics — Immutable snapshots represent complete state; deltas represent incremental updates referencing a parent.
  3. Schema validation — JSON Schema enforcement across all producers and receivers.

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.

Envelope in a DataPart

An ACP envelope travels as a single DataPart inside an A2A message.

Message shape
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

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.

State Requests

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.

State requestJSON
{
  "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.

Agent Card Declaration

An agent declares ACP support by listing the extension URI in capabilities.extensions[] of its A2A agent card.

agent-card.jsonJSON
{
  "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.

Delta Example

A buyer agent detects financing intent during a conversation and sends a delta to the dealership agent.

Delta over A2AJSON-RPC 2.0
{
  "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.

Error Codes

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
Error objectJSON
{
  "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" }
  ]
}

Independence Notice

Protocol Independence: ACP is an independent transaction standard maintained by the ACP Foundation. A2A is an independent agent transport protocol governed by the Linux Foundation. ACP does not require A2A, and A2A does not require ACP. This page describes potential interoperability based on architectural alignment. It does not imply endorsement, partnership, or formal compatibility certification between the two protocols.

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.

Conformance

An implementation conforms to this binding when all of the following hold.

  1. Declared — It publishes an A2A agent card with the extension URI, a valid acp_version, and a resolvable schema_url.
  2. Honest about kinds — It accepts every envelope kind listed in accepts and emits only kinds listed in emits.
  3. One envelope, one part — Every ACP message it sends or receives is one complete envelope in one DataPart.
  4. Validating — It validates inbound envelopes against the declared schema and rejects invalid envelopes whole.
  5. Consent-enforcing — It enforces consent at the boundary, before ingestion.
  6. Append-only — It preserves the event stream and appends to it rather than replacing it.
  7. Transport-identical — It produces identical envelopes on the A2A and HTTPS bindings for the same state.

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.