Network Working Group D. Liu Internet-Draft Alibaba Intended status: Standards Track 2 November 2026 Expires: 6 May 2027 The Agent Communication Protocol (ACP) draft-liu-agentproto-acp-00 Abstract An agentic dialog can run for hours or days, go quiet for long stretches, move between hosts, and survive the loss of whatever connection was carrying it. The Agent Communication Protocol (ACP) architecture names Agentic Dialog Management as a building block and requires an identifier that correlates every message of a dialog and outlives the transport, but leaves the wire format out of scope. This document specifies one such wire format. ACP is an application-level session protocol in the style of SIP: every message is a start line, a block of text header fields, a blank line, and an optional body. A dialog is named by an Agentic Dialog Identifier (ADID) and its durable state is an append-only log of entries, each digesting the one before it into a hash chain. The chain lets two endpoints that have been apart establish in one exchange which entries they still share, replay only what is missing, and detect divergence. Periodic checkpoints bound the log, so aligning a dialog does not cost more as it ages. ACP carries control and log state only. Real-time media flows beside it on its own channels and enters the log as a metadata entry or as a content-addressed reference, never as bytes the chain must digest. The semantics are transport-independent; this version binds them to Media over QUIC Transport (MoQ) and to WebTransport over HTTP/3, both of which multiplex the channels ACP needs and migrate across network paths without disturbing the dialog. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Liu Expires 6 May 2027 [Page 1] Internet-Draft ACP November 2026 Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on 6 May 2027. Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License. Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 1.1. Conventions and Definitions . . . . . . . . . . . . . . . 4 2. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 5 3. Protocol Layering and Transport Mapping . . . . . . . . . . . 6 3.1. Protocol Overview . . . . . . . . . . . . . . . . . . . . 7 3.2. Traffic Classes . . . . . . . . . . . . . . . . . . . . . 9 3.3. The Agentic Dialog Identifier . . . . . . . . . . . . . . 10 3.4. Participants . . . . . . . . . . . . . . . . . . . . . . 10 3.5. Workload Identity and Attribution . . . . . . . . . . . . 10 3.6. Transport Mapping . . . . . . . . . . . . . . . . . . . . 11 4. Dialog and Transport State . . . . . . . . . . . . . . . . . 12 4.1. Dialog State . . . . . . . . . . . . . . . . . . . . . . 12 4.2. Transport State and Transitions . . . . . . . . . . . . . 14 5. Wire Format and Signaling . . . . . . . . . . . . . . . . . . 16 5.1. Message Format . . . . . . . . . . . . . . . . . . . . . 16 5.2. Header Fields . . . . . . . . . . . . . . . . . . . . . . 18 5.3. Transactions, Ordering, and Timers . . . . . . . . . . . 21 5.4. Methods . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.4.1. INITIATE . . . . . . . . . . . . . . . . . . . . . . 23 5.4.2. APPEND . . . . . . . . . . . . . . . . . . . . . . . 25 5.4.3. CANCEL . . . . . . . . . . . . . . . . . . . . . . . 26 5.4.4. SUSPEND . . . . . . . . . . . . . . . . . . . . . . . 27 5.4.5. RESUME . . . . . . . . . . . . . . . . . . . . . . . 27 5.4.6. PROBE . . . . . . . . . . . . . . . . . . . . . . . . 28 5.4.7. CHECKPOINT . . . . . . . . . . . . . . . . . . . . . 30 Liu Expires 6 May 2027 [Page 2] Internet-Draft ACP November 2026 5.4.8. TERMINATE . . . . . . . . . . . . . . . . . . . . . . 31 5.5. Status Codes . . . . . . . . . . . . . . . . . . . . . . 31 6. The Log . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 6.1. Entries and Sequencing . . . . . . . . . . . . . . . . . 33 6.1.1. Pending Entries . . . . . . . . . . . . . . . . . . . 34 6.2. Event Boundaries . . . . . . . . . . . . . . . . . . . . 35 6.3. The Entry Digest . . . . . . . . . . . . . . . . . . . . 36 6.4. Media and Large Assets . . . . . . . . . . . . . . . . . 37 6.5. Checkpoints and Truncation . . . . . . . . . . . . . . . 38 6.6. Log Alignment . . . . . . . . . . . . . . . . . . . . . . 40 6.6.1. Tail Verification . . . . . . . . . . . . . . . . . . 40 6.6.2. Fork Detection and Resolution . . . . . . . . . . . . 41 6.6.3. Resynchronization Below a Checkpoint . . . . . . . . 42 7. Transport Bindings . . . . . . . . . . . . . . . . . . . . . 42 7.1. Binding Requirements . . . . . . . . . . . . . . . . . . 42 7.2. MoQ Binding . . . . . . . . . . . . . . . . . . . . . . . 43 7.3. WebTransport Binding . . . . . . . . . . . . . . . . . . 45 8. Security Considerations . . . . . . . . . . . . . . . . . . . 46 8.1. Dialog Identifiers . . . . . . . . . . . . . . . . . . . 47 8.2. Authorizing Session Establishment . . . . . . . . . . . . 47 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 48 9.1. ACP Registries . . . . . . . . . . . . . . . . . . . . . 48 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 49 10.1. Normative References . . . . . . . . . . . . . . . . . . 49 10.2. Informative References . . . . . . . . . . . . . . . . . 51 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 52 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 52 1. Introduction A task handed to an agent is rarely one request and one answer. It runs for hours, produces output long after the request that caused it, goes quiet while a human sleeps, and resumes from a different device. The connection carrying it will be replaced several times over that life. Nothing in the connection survives, so the dialog needs a name and a state of its own. The ACP architecture [I-D.manyfolks-agentproto-arch] names that state Agentic Dialog Management and requires an identifier that correlates every message of a dialog and survives the loss or replacement of the transport. It does not say what the messages look like. This document supplies a wire format for that building block, and adds the one thing a dialog that spans days cannot do without: a way for two endpoints that have been apart to agree on what they both remember. The problem is not reliability. QUIC already delivers a stream without gaps. The problem is the interval between connections. An agent may finish work while its principal is offline; a principal may Liu Expires 6 May 2027 [Page 3] Internet-Draft ACP November 2026 accept an entry whose acknowledgement never arrived; a server may recover from a crash having lost its last few entries. Each side holds a plausible history and there is no shared clock or shared connection to arbitrate them. ACP answers this with a hash chain: every log entry digests its predecessor, so a history is a sequence of digests that can be compared from the tail backwards, and the first position where two histories differ is exactly the position where they diverged (Section 6.6). The encoding follows SIP [RFC3261] rather than a structured data format, for two reasons. A text start line and text header fields can be read by a human in a log, generated by a shell script, and extended by adding a field without a schema change. And because the body is carried as raw octets with no field ordering to normalize, the digest of an entry is the digest of a byte string both endpoints already hold verbatim. A format whose in-memory representation is serialized differently by different implementations cannot offer that, and a chain that disagrees about its own digests is worse than no chain at all. The rest of this document is organized as follows. Section 2 defines the terms used throughout; Section 3 gives the layering, the traffic classes, the participants and their identity, and the mapping onto transports; Section 4 gives the dialog and transport state machines; Section 5 defines the message format, the header fields, the methods, transactions, and status codes; Section 6 defines the log, its event boundaries, the entry digest, asset references, checkpoints, and the alignment procedure that lets a dialog survive its transport; and Section 7 maps ACP onto MoQ and WebTransport. This is a first revision and is deliberately narrow. How a client learns the https URI of the agent service it wants is not specified here; ACP assumes the client already has one. Delegation between dialogs, per-entry signatures, concurrent access from several devices, and the media negotiation body are likewise identified but not specified. 1.1. Conventions and Definitions The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. The syntax uses the Augmented Backus-Naur Form of [RFC5234]. The terms "octet", "byte", and the character names CR, LF, and SP are used as in that specification. Liu Expires 6 May 2027 [Page 4] Internet-Draft ACP November 2026 2. Terminology The terms below follow the ACP architecture [I-D.manyfolks-agentproto-arch] where it defines them. Agent A software process that acts on a task over an extended period, holds state between exchanges, and produces output that is not a direct function of a single request. An agent is the server side of a dialog in this document, but an agent may also be the principal of another dialog. Principal The entity on whose behalf a dialog is conducted: a human user, or an agent acting for one. Agentic dialog (dialog) A long-lived session between two participants, named by an ADID. A dialog is a protocol object with state of its own; it is not a connection, and it does not end when one is lost. ADID The Agentic Dialog Identifier: an opaque, unguessable identifier for a dialog (Section 3.3). Client, server The participant that sends INITIATE is the client; the participant that answers it is the server. The roles name who offered the dialog, not which side runs the model. Ordering authority The participant that assigns the authoritative Sequence numbers of a dialog's log. In this version the server is always the ordering authority (Section 6.1). Log The ordered, append-only sequence of entries that constitutes a dialog's durable state (Section 6). Each participant holds a replica; the ordering authority's replica is authoritative. Entry One unit of the log, occupying exactly one Sequence number and carrying one digest (Section 6.3). Event boundary A point at which an application's execution has completed a whole unit of work: a turn, a tool call and its result, an accepted utterance. Every entry closes exactly one event boundary (Section 6.2). Dialog context The protocol state of a dialog: its ADID, its participants, its capability and lifetime parameters, and its log. Model context The inference state an agent's runtime keeps for a Liu Expires 6 May 2027 [Page 5] Internet-Draft ACP November 2026 dialog: token windows, scratch memory, tool bindings. Model context belongs to the application. ACP neither carries nor reconstructs it, and losing it is not an ACP failure. Alignment The process by which two replicas of a log establish their last common entry and bring the lagging one up to date (Section 6.6). Checkpoint An entry of Entry-Type system that commits to a prefix of the log, after which entries in that prefix may be discarded (Section 6.5). Control plane, log plane The two planes on which ACP carries traffic that must be delivered reliably. The control plane is requests and responses, matched by CSeq. The log plane is committed entries. They are separated because their durability requirements differ: the log must also be recoverable after a connection is replaced. A third class, progress traffic, rides neither plane and is never logged (Section 3.2). 3. Protocol Layering and Transport Mapping ACP sits between the application that owns the dialog and the transport that carries it. It is layered so that neither knows the other: the application issues methods and appends entries, the transport adapter decides which channel each byte takes, and the session layer owns the log that makes the two independent of any particular connection (Table 1). +=======================+===============================+ | Layer | Responsibilities | +=======================+===============================+ | ACP application layer | dialog management, identity | | | and delegation, authorization | +-----------------------+-------------------------------+ | ACP session and | log, entry digest, alignment, | | synchronization layer | checkpoints | +-----------------------+-------------------------------+ | ACP transport adapter | channel mapping, connection | | | migration, resumption | +-----------------------+-------------------------------+ | underlying transport | WebTransport over HTTP/3 or | | | MoQ; further bindings TBD | +-----------------------+-------------------------------+ Table 1: ACP layering Liu Expires 6 May 2027 [Page 6] Internet-Draft ACP November 2026 The layering matters for one reason above the others. A dialog's lifetime is not a connection's lifetime, and the difference can be days. Everything ACP defines is therefore keyed to the ADID and to log position, never to a connection, a stream, or a socket. A transport connection may be established, migrated, and lost any number of times while the dialog stays in one state, and when a connection is replaced the dialog does not restart: it aligns (Section 6.6). 3.1. Protocol Overview Two parties take part in a dialog: the client, which acts for a principal, and the server, which acts for an agent and is the ordering authority for the log. Figure 1 walks one dialog through establishment, steady state, an interruption, and recovery. Liu Expires 6 May 2027 [Page 7] Internet-Draft ACP November 2026 Client Server (for a principal) (for an agent) | | (1) | INITIATE | | ADID, From, To, Supported-Modalities | |-------------------------------------------->| (2) | 200 | | ADID, Session-TTL, Tail-Seq: 0 | |<--------------------------------------------| | dialog ACTIVE | | | (3) | APPEND Sequence: 1, Entry-Type: input | |-------------------------------------------->| (4) | 200 Sequence: 1, Entry-Hash | |<--------------------------------------------| (5) | APPEND Sequence: 2, Entry-Type: output | |<--------------------------------------------| (6) | 200 Sequence: 2 | |-------------------------------------------->| | | (7) | media and progress, on their own channels | |<- - - - - - - - - - - - - - - - - - - - - ->| | no ACP header, no Sequence, no digest | | | (8) | the connection dies | | X | | both go SUSPENDED | | | (9) | RESUME Tail-Seq: 2, Tail-Hash: H2 | |-------------------------------------------->| (10) | 206 Action: replay, Replay-From: 3 | |<--------------------------------------------| (11) | the entries the client missed | |<============================================| | both ACTIVE again | Figure 1: The life of a dialog Steps 1 and 2 establish the dialog. The client generates the ADID and offers what it supports; the server records the dialog durably, grants a lifetime, and answers with an empty log position. Three fields are the whole handshake, because everything else is either implied by the channel or negotiated later. Liu Expires 6 May 2027 [Page 8] Internet-Draft ACP November 2026 Steps 3 to 6 are the steady state, and they are the same exchange in both directions. Each entry is proposed by its author with the next Sequence and the digest of the entry before it, and is committed when the peer accepts it. The response is not an acknowledgement in the transport sense; it is the commit, and until it arrives the entry is pending (Section 6.1.1). Step 7 is the traffic ACP deliberately does not carry. Real-time media and progress indications flow on their own channels with no header, no position, and no digest, and are recorded in the log only as the event that opened or closed them (Section 6.2). This is what keeps the chain cheap enough for a dialog that runs for days. Steps 8 to 11 are the reason the chain exists. The connection dies and both participants suspend without exchanging anything. When the client returns, possibly days later and on a different host, it names the last entry it holds and its digest; the server compares, and answers with either agreement or the position to replay from. One round trip establishes what the two have in common, and the entries that follow are verified as they arrive rather than trusted (Section 6.6). 3.2. Traffic Classes ACP distinguishes traffic by what has to survive. Control traffic Requests and responses on the control plane: INITIATE, SUSPEND, RESUME, PROBE, CHECKPOINT, TERMINATE, and CANCEL. It must be delivered reliably and in order within a connection, and it is small. It is matched by CSeq (Section 5.3). Log traffic Committed entries, each an indivisible octet string that has already been digested by its author. It must be delivered reliably and in order, it may be large, and it must be recoverable after a connection is replaced, because a peer that reconnects needs the entries it missed rather than the ones it has. Progress traffic Ephemeral indications that something is happening: generation is underway, a tool call started, a partial transcript. It is time-bounded and superseded by the next indication. It MUST be carried unreliably, it is never part of the log, and no ACP state may depend on receiving it. Keeping these apart is what allows ACP to be both light and durable. Real-time media takes the third path: it flows on its own channels, and the log records only that it flowed and how to find it (Section 6.4). A dialog can therefore carry hours of voice and video while its log stays small enough to align in one exchange. Liu Expires 6 May 2027 [Page 9] Internet-Draft ACP November 2026 3.3. The Agentic Dialog Identifier Every dialog has an Agentic Dialog Identifier (ADID), a version 4 UUID [RFC9562]: 122 bits from a cryptographically secure random source [RFC4086], written in the canonical textual form of 36 lowercase hexadecimal digits in five hyphen-separated groups so that it can be compared verbatim. The client generates it and sends it in the INITIATE; the server echoes it in the final response and from then on it names the dialog for both participants. It MUST NOT be chosen or influenced by a peer of the generator, and MUST NOT be reused, including for an INITIATE that went unanswered. The ADID identifies the dialog, not the connection carrying it, so a dialog that moves to a new connection keeps its ADID and its log position. Because it carries 122 bits of randomness, collisions are negligible and no registration is needed. It is also not a credential: it is opaque, non-self-certifying, and reveals nothing about the dialog. Knowledge of an ADID is not authority to use it (Section 8.1). 3.4. Participants A dialog has exactly two participants, both named when it is initiated: the client, acting for a principal, and the server, acting for an agent. Each is named by a SPIFFE ID [SPIFFE], which is what the architecture uses for a participant and what a workload identity carries ([I-D.ietf-wimse-workload-creds]), for example spiffe://example.org/ns/agent/travel. A SPIFFE ID names a participant, not a place to send a message. The request target of INITIATE is an https URI (Section 5.1) naming the agent service: it says where to send the offer, while the From, To, and Author fields say who is in the dialog. A client that does not yet know which workload will serve it addresses the service and learns the participant from the To of the server's final response, which from then on is the name the log uses. 3.5. Workload Identity and Attribution ACP is neither an identity mechanism nor an authorization mechanism, and it introduces no new cryptographic construction. It takes the model the architecture specifies [I-D.manyfolks-agentproto-arch] and states where it rides. Each participant holds a WIMSE workload identity [I-D.ietf-wimse-workload-creds], expressed as a SPIFFE ID [SPIFFE] and carried as the sub claim of a Workload Identity Token (WIT) that binds a public key in cnf.jwk: Liu Expires 6 May 2027 [Page 10] Internet-Draft ACP November 2026 { "iss": "https://aim.example.org", "sub": "spiffe://example.org/ns/agent/travel", "aud": "https://agent.example.com", "cnf": { "jwk": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." } }, "exp": 1793316000 } Figure 2: The identity a participant presents The same identity serves twice. At the transport layer the participant presents it as a workload identity credential over a channel that mutually authenticates both ends, which is what makes the channel requirement of Section 8 satisfiable. At the application layer it presents a token derived from that credential, in an Authorization field, in the messages where the peer has to check authority rather than merely connectivity: INITIATE and RESUME. The WIT is the input to that derivation and is not itself what is sent: a workload identity says who a participant is, while authorizing one request also needs the transaction context that Section 8.2 describes. Attribution then needs no signature of ACP's own, and two rules are the whole of the mechanism. A recipient MUST check that the Author of an APPEND, and the From of any other request, equal the workload identity the channel authenticated, and MUST reject the message with 403 if they do not. And a participant MUST NOT accept dialog traffic on a channel that does not authenticate its sender, because without an authenticated channel there is nothing to attribute a message to and the ADID by itself asserts nothing. The private key corresponding to cnf.jwk is also the key with which the participant signs the tokens it obtains, so one identity serves for channel authentication, for the authority it presents, and for the name that appears in the log. ACP adds no second identity and no second key. Note what this does and does not buy: it proves who sent a message on the connection that carried it, and it does not survive the connection. An entry committed to the log is attributed by an Author string inside a digest, which anyone able to write to the authoritative replica can set. 3.6. Transport Mapping The three traffic classes of Section 3.2 have different delivery requirements, and the adapter's only job is to satisfy each of them on whatever transport is available. Table 2 summarizes the mapping; Section 7 specifies it. Liu Expires 6 May 2027 [Page 11] Internet-Draft ACP November 2026 +===========+====================+=================+================+ | Channel | Requires | MoQ | WebTransport | +===========+====================+=================+================+ | control | reliable, ordered, | one | one | | | bidirectional | bidirectional | bidirectional | | | | stream | stream | +-----------+--------------------+-----------------+----------------+ | log | reliable, ordered, | published | bidirectional | | | recoverable after | track, one | stream, | | | a reconnect | group per | replayed by | | | | entry | the server | +-----------+--------------------+-----------------+----------------+ | asset | reliable, content- | a track per | unidirectional | | | addressed, must | asset | streams | | | not block the log | | | +-----------+--------------------+-----------------+----------------+ | progress, | low latency, | datagrams or | datagrams | | live | unreliable is | media objects | | | media | acceptable | | | +-----------+--------------------+-----------------+----------------+ Table 2: Channel requirements and how each binding meets them Two properties of the underlying transport do work that ACP would otherwise have to do itself. Connection migration lets a dialog change network path without changing state (Section 4.2), and per- stream flow control lets a large asset move without holding up an entry that is a few hundred octets. A binding that cannot provide either is still conformant, but the dialog will suspend more often and its log will stall behind its media. 4. Dialog and Transport State A participant in a dialog tracks two independent variables. Its dialog state is a property of the ADID and survives any number of connections. Its transport state is a property of the connection the binding gives it and survives nothing. Conflating them is the mistake that makes a session protocol fragile, so ACP keeps them apart and defines exactly how the second drives the first (Section 4.2). 4.1. Dialog State ACP keeps one dialog state per participant. The states are the same for both, except that only the server enters ALIGNING: the client stays in SUSPENDED until alignment completes, because it is the server that arbitrates and only the server needs a state in which it has accepted a resumption but not yet settled it. Liu Expires 6 May 2027 [Page 12] Internet-Draft ACP November 2026 IDLE | | INITIATE v INITIATING --4xx / 5xx / T1--> TERMINATED | | 200 v ACTIVE <--------------------------+ | | | transport loss, or SUSPEND | alignment complete v | (200, or 206 after replay) SUSPENDED ---+ | | | | | +--> ALIGNING -------+ | (server only) | | TTL expiry, or TERMINATE v TERMINATED Figure 3: Dialog states IDLE No dialog state exists for this ADID. INITIATING An INITIATE has been sent or received and no final response has settled it. The client has chosen an ADID that is not yet in use. ACTIVE The dialog is established, a transport channel carries it, and the two replicas are aligned. Entries may be appended and work may be requested. On the server this is also the state in which it holds runtime resources for the dialog; it is not required to hold model context, and losing it is not a protocol failure. SUSPENDED The dialog exists and its log is durably held, but no channel carries it. The server releases whatever runtime resources it was holding. This state may last for the whole Session-TTL, which is measured from the moment the dialog was suspended and not from the moment it was created. ALIGNING The server has accepted a RESUME and is comparing replicas. It does not accept APPEND in this state, because an append would move the tail it is trying to agree on. TERMINATED The dialog is finished. State MAY be purged, and the Liu Expires 6 May 2027 [Page 13] Internet-Draft ACP November 2026 ADID MUST NOT be reused. A RESUME for a terminated dialog receives 404. CANCEL does not change dialog state. It stops work associated with an entry already in the log and adds an entry recording that it did (Section 5.4.3), after which the dialog is ACTIVE and accepts the next transaction. 4.2. Transport State and Transitions Transport state is whatever the binding reports: connected, migrating, or gone. It is not an ACP state machine and ACP defines no polling for it, because QUIC reports path loss directly [RFC9000]. What ACP defines is the mapping from transport events to dialog transitions, in Table 3. Liu Expires 6 May 2027 [Page 14] Internet-Draft ACP November 2026 +========+============+===============================+============+ | Who | From | Event | To | +========+============+===============================+============+ | client | IDLE | sends INITIATE | INITIATING | +--------+------------+-------------------------------+------------+ | client | INITIATING | receives 200 | ACTIVE | +--------+------------+-------------------------------+------------+ | client | INITIATING | 4xx, 5xx, or T1 expiry | TERMINATED | +--------+------------+-------------------------------+------------+ | server | IDLE | receives INITIATE | INITIATING | +--------+------------+-------------------------------+------------+ | server | INITIATING | log initialized, sends 200 | ACTIVE | +--------+------------+-------------------------------+------------+ | server | INITIATING | rejects, sends 4xx or 5xx | TERMINATED | +--------+------------+-------------------------------+------------+ | both | ACTIVE | path changes; migration | ACTIVE | | | | completes within T1 | | +--------+------------+-------------------------------+------------+ | both | ACTIVE | transport gone, and no | SUSPENDED | | | | migration within T1 | | +--------+------------+-------------------------------+------------+ | both | ACTIVE | SUSPEND settled by 200 | SUSPENDED | +--------+------------+-------------------------------+------------+ | server | SUSPENDED | receives RESUME | ALIGNING | +--------+------------+-------------------------------+------------+ | server | ALIGNING | replicas agree; 200, or 206 | ACTIVE | | | | and replay complete | | +--------+------------+-------------------------------+------------+ | server | ALIGNING | digests differ, sends 409; or | ALIGNING | | | | tail below Min-Seq, sends 412 | | +--------+------------+-------------------------------+------------+ | server | ALIGNING | T2 expiry, or client abandons | SUSPENDED | +--------+------------+-------------------------------+------------+ | client | SUSPENDED | alignment complete | ACTIVE | +--------+------------+-------------------------------+------------+ | client | SUSPENDED | receives 404, or Session-TTL | TERMINATED | | | | expires | | +--------+------------+-------------------------------+------------+ | both | any | TERMINATE settled, or | TERMINATED | | | | Session-TTL expires | | +--------+------------+-------------------------------+------------+ Table 3: Dialog state transitions The row that matters most is the one that changes nothing. Where the binding supports connection migration, as QUIC does, a participant moving from one network path to another stays ACTIVE and sends no ACP message at all: the dialog is keyed to the ADID and to log position, Liu Expires 6 May 2027 [Page 15] Internet-Draft ACP November 2026 never to a socket (Section 3). It moves to SUSPENDED only when the connection is gone and no migration has completed within T1. This is why a dialog can survive a walk from a wireless network to a cellular one without either participant noticing, and why the resumption path is reserved for separations long enough that the connection really did die. 5. Wire Format and Signaling Everything on the control plane and the log plane has one shape: a start line naming a method or a status, a block of text header fields, a blank line, and an optional body. This section defines that shape, the fields, the methods, and the transactions that match a request to its response. Section 5.4 gives each method in full, and Section 5.5 the response codes. 5.1. Message Format An ACP message is a start line, zero or more header fields, a blank line, and an optional body: Liu Expires 6 May 2027 [Page 16] Internet-Draft ACP November 2026 ACP-message = request / response request = Request-Line *( header-field CRLF ) CRLF [ body ] response = Status-Line *( header-field CRLF ) CRLF [ body ] Request-Line = method SP request-uri SP "ACP/1.0" CRLF Status-Line = "ACP/1.0" SP status-code SP reason-phrase CRLF method = "INITIATE" / "APPEND" / "CANCEL" / "SUSPEND" / "RESUME" / "PROBE" / "CHECKPOINT" / "TERMINATE" / token status-code = 3DIGIT reason-phrase = 1*( unreserved / SP ) header-field = field-name ":" OWS field-value OWS field-name = token field-value = *( HTAB / SP / VCHAR ) request-uri = "https:" "//" authority [ path-abempty ] body = *OCTET OWS = *( SP / HTAB ) token = 1*tchar tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA 3DIGIT = DIGIT DIGIT DIGIT unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" authority = path-abempty = Figure 4: ACP message syntax OWS, token, and 3DIGIT match the definitions of the same names in [RFC9110], and unreserved matches [RFC3986], Section 2.3; all four are repeated here so that the grammar is self-contained. authority and path-abempty are used by reference to [RFC3986], Sections 3.2 and 3.3. The request-uri is an https URI naming the agent service, and is the same in every request of a dialog. It is a locator, not the name of a participant (Section 3.4); its userinfo, query, and fragment components MUST NOT be used. That the scheme is https does not mean ACP runs inside HTTP: how the URI is reached is a property of the binding (Section 7). Liu Expires 6 May 2027 [Page 17] Internet-Draft ACP November 2026 Three properties of this syntax are normative because the entry digest of Section 6.3 depends on them. First, a field-value cannot contain CR or LF, since it is built from VCHAR, SP, and HTAB only; that is what makes a sequence of field values separable without length prefixes. Second, the blank line that ends the header block is exactly CRLF following the CRLF of the last header field, with no other form permitted. Third, the body is an opaque octet string whose extent is given by Content-Length; no transfer encoding, and in particular no chunked encoding, is defined. A sender MUST NOT send a header field it does not understand the syntax of, and a recipient MUST ignore a header field it does not recognize unless Section 5.2 marks it as required for the method in question. This is what allows a field to be added without a version change. A recipient that receives a message whose start line it cannot parse MUST respond 400; one whose method it does not support MUST respond 501. Content-Length is REQUIRED on every message sent on a channel that carries more than one message, and on every message with a body. On a channel that carries exactly one entry body and is then closed by the transport, the end of the stream delimits the body and Content- Length MAY be omitted (Section 7). 5.2. Header Fields Table 4 lists the fields this version defines. Field names are case- insensitive. A field MUST NOT appear more than once unless its definition says otherwise. +======================+======================+===================+ | Field | Value | Where it appears | +======================+======================+===================+ | ADID | The dialog | Every message, | | | identifier | including an | | | (Section 3.3) | INITIATE request, | | | | where it is the | | | | client-generated | | | | value | +----------------------+----------------------+-------------------+ | CSeq | seq SP method, per | Every request; | | | transaction | echoed by its | | | | response | +----------------------+----------------------+-------------------+ | From, To | Participant URIs | INITIATE request | | | (Section 3.4) | and its final | | | | response | +----------------------+----------------------+-------------------+ Liu Expires 6 May 2027 [Page 18] Internet-Draft ACP November 2026 | Sequence | Log position of an | APPEND; a | | | entry | response that | | | | assigns one | +----------------------+----------------------+-------------------+ | Prev-Hash | Entry-Hash of | APPEND | | | Sequence minus one | | +----------------------+----------------------+-------------------+ | Entry-Hash | Digest of this entry | APPEND | | | (Section 6.3) | | +----------------------+----------------------+-------------------+ | Entry-Type | input, output, meta, | APPEND | | | abort, system | | +----------------------+----------------------+-------------------+ | Author | Participant URI of | APPEND | | | the entry's creator, | | | | which MUST equal the | | | | identity the channel | | | | authenticated | | | | (Section 3.5) | | +----------------------+----------------------+-------------------+ | Timestamp | Seconds since the | APPEND, | | | Unix epoch | CHECKPOINT | +----------------------+----------------------+-------------------+ | Event-Cursor | A token naming the | APPEND, CANCEL | | | runtime boundary the | | | | entry closes | | | | (Section 6.2); | | | | optional | | +----------------------+----------------------+-------------------+ | Tail-Seq, Tail-Hash | Position and digest | RESUME, PROBE, | | | of the sender's last | and responses | | | committed entry | that report | | | | position | +----------------------+----------------------+-------------------+ | Min-Seq | Oldest Sequence | RESUME and its | | | still retained | responses | +----------------------+----------------------+-------------------+ | CP-Seq, CP-Hash | Latest checkpoint | CHECKPOINT, | | | entry and its digest | RESUME responses | | | (Section 6.5) | | +----------------------+----------------------+-------------------+ | Replay-From | First Sequence the | 206 response to | | | responder will | RESUME | | | replay | | +----------------------+----------------------+-------------------+ | Action | replay, resync, or | Responses to | | | probe | RESUME | +----------------------+----------------------+-------------------+ Liu Expires 6 May 2027 [Page 19] Internet-Draft ACP November 2026 | Proof | One seq=hash-value | PROBE request and | | | pair; repeatable | response | +----------------------+----------------------+-------------------+ | Session-TTL | delta-seconds; | INITIATE, | | | requested in a | SUSPEND, RESUME | | | request, granted in | | | | a response | | +----------------------+----------------------+-------------------+ | Supported-Modalities | Comma-separated | INITIATE request | | | media type ranges | | +----------------------+----------------------+-------------------+ | Target-Seq | Sequence whose | CANCEL | | | processing is to | | | | stop | | +----------------------+----------------------+-------------------+ | Reason | Machine-readable | CANCEL, TERMINATE | | | token | | +----------------------+----------------------+-------------------+ | Authorization | Credentials of the | INITIATE, RESUME | | | sender, syntax as in | | | | [RFC9110]; carries | | | | the token obtained | | | | as Section 8.2 | | | | describes | | +----------------------+----------------------+-------------------+ | Content-Type | Media type of the | Any message with | | | body [RFC2046] | a body | +----------------------+----------------------+-------------------+ | Content-Length | Body length in | See Section 5.1 | | | octets | | +----------------------+----------------------+-------------------+ Table 4: ACP header fields The values of the fields that carry a digest or a position use this syntax: seq = 1*15DIGIT hash-value = hash-alg "-" b64 hash-alg = "sha256" b64 = 43*unreserved ; RFC 4648, Section 5, unpadded Proof = seq "=" hash-value action = "replay" / "resync" / "probe" Figure 5: Position and digest value syntax Liu Expires 6 May 2027 [Page 20] Internet-Draft ACP November 2026 Tail-Seq and Tail-Hash MUST appear together and describe the same entry. Min-Seq defaults to 1 when absent. Proof is the only field in this document that MAY appear more than once; the set it denotes is the union of its occurrences, and a seq MUST NOT be repeated across them. Digest values are written as the algorithm name, a hyphen, and the base64url encoding of the digest without padding ([RFC4648], Section 5), which for SHA-256 is 43 characters. Hexadecimal is not used because a 64-character digest cannot share a line with a field name inside the formatting width this document observes, and folding a digest across lines would put its textual form at the mercy of each implementation's folder. The algorithm prefix is not decorative: a recipient MUST check it and MUST reject a value naming an algorithm it does not support with 400. Header field order is not significant. A sender MAY emit fields in any order, and a recipient MUST NOT infer meaning from their arrangement. The digest of Section 6.3 uses a fixed order of values that has nothing to do with the order they appear in. 5.3. Transactions, Ordering, and Timers A transaction is one request and the responses to it. The CSeq field carries a sequence number and the method name, separated by a single space. Each participant keeps one CSeq counter per dialog, starting at 1 and increasing by at least one for each request it sends; the counter is independent of log Sequence numbers, because a dialog may see many transactions that add no entry. A response echoes the CSeq of its request verbatim. A recipient that sees a CSeq it has already answered on this dialog MUST discard the request, which makes requests safe to repeat after a connection is replaced. A participant MUST NOT have more than one outstanding APPEND per dialog, so that its pending entries have a total order. It MAY have one outstanding APPEND and one outstanding control request at the same time. Responses may arrive in a different order from requests only where this paragraph allows it, so a recipient matches them by CSeq and never by arrival order. Because every channel ACP uses is reliable and ordered within a connection (Section 7), ACP defines no retransmission timer and no hop-by-hop acknowledgement. It does define two timers, because a request can still go unanswered when a connection dies: Liu Expires 6 May 2027 [Page 21] Internet-Draft ACP November 2026 +=======+=========+=============================================+ | Timer | Default | Meaning | +=======+=========+=============================================+ | T1 | 5 s | Bound on waiting for a final response. On | | | | expiry the transaction fails locally; the | | | | outcome is unknown and the participant MUST | | | | align before relying on it (Section 6.1.1). | +-------+---------+---------------------------------------------+ | T2 | 60 s | Bound on completing a replay announced by | | | | 206. On expiry the alignment attempt fails | | | | and MAY be retried. | +-------+---------+---------------------------------------------+ Table 5: ACP timers A dialog also has a lifetime, Session-TTL, expressed in delta- seconds. A request carries the value the sender wants; the response carries the value granted, which MAY be shorter. The default is 259200 (72 hours). Time starts again on each successful APPEND, RESUME, or CHECKPOINT. When it expires the dialog moves to the terminated state and its state MAY be purged; a later RESUME then fails with 404. 5.4. Methods ACP defines eight methods, summarized in Table 6. The subsections that follow define each one in full: what it requires, what a successful response commits both participants to, and how it fails. The examples use one dialog throughout, with the digests that follow from it, so they can be checked against the construction of Section 6.3. Liu Expires 6 May 2027 [Page 22] Internet-Draft ACP November 2026 +============+=========+============================+ | Method | Sent by | Effect | +============+=========+============================+ | INITIATE | client | Create a dialog and fix | | | | its ADID and participants | +------------+---------+----------------------------+ | APPEND | either | Add one entry to the log | +------------+---------+----------------------------+ | CANCEL | either | Stop work caused by an | | | | entry already in the log | +------------+---------+----------------------------+ | SUSPEND | either | Release runtime resources, | | | | keep the dialog | +------------+---------+----------------------------+ | RESUME | client | Align the log and | | | | reactivate the dialog | +------------+---------+----------------------------+ | PROBE | client | Locate the common ancestor | | | | after a 409 | +------------+---------+----------------------------+ | CHECKPOINT | either | Commit to a log prefix and | | | | permit its truncation | +------------+---------+----------------------------+ | TERMINATE | either | End the dialog and purge | | | | its state | +------------+---------+----------------------------+ Table 6: ACP methods 5.4.1. INITIATE INITIATE creates a dialog. The client generates the ADID (Section 3.3), names both participants, states the modalities it can handle, and asks for a lifetime. Required fields: ADID, CSeq, From, To. Optional: Supported-Modalities, Session-TTL. Liu Expires 6 May 2027 [Page 23] Internet-Draft ACP November 2026 INITIATE https://agent.example.com/travel ACP/1.0 CSeq: 1 INITIATE ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d From: spiffe://example.org/ns/agent/client-1 To: spiffe://example.com/ns/agent/travel Authorization: Bearer eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOi... Supported-Modalities: text/plain, image/*, audio/opus Session-TTL: 259200 Content-Length: 0 ACP/1.0 200 OK CSeq: 1 INITIATE ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d From: spiffe://example.org/ns/agent/client-1 To: spiffe://example.com/ns/agent/travel Session-TTL: 259200 Tail-Seq: 0 Tail-Hash: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Min-Seq: 1 Content-Length: 0 Figure 6: INITIATE and its acceptance On 200 the server has durably recorded the dialog with an empty log and both participants are ACTIVE. The ADID in the response MUST equal the one requested; a server cannot substitute its own, since the client has already begun using it. Session-TTL in the response is the lifetime granted, which MAY be shorter than requested. A server that cannot serve the modalities offered responds 488; one that is out of capacity responds 486; one that cannot durably record the dialog responds 500 and MUST NOT leave partial state. After any failure, and after a T1 expiry, the client MUST discard the ADID and generate a fresh one for any retry: a dialog whose establishment did not settle has no state to resume. ACP does not define the format of a media negotiation body in this revision. Supported-Modalities is a list of media type ranges as in [RFC6838], and 488 is the only negotiation failure this version specifies. Offer and answer semantics, and how a modality is bound to a data channel, are deferred to a later revision. Liu Expires 6 May 2027 [Page 24] Internet-Draft ACP November 2026 5.4.2. APPEND APPEND adds one entry to the log. Required fields: ADID, CSeq, Sequence, Entry-Type, Prev-Hash, Author, Timestamp, Entry-Hash. Optional: Event-Cursor (Section 6.2). The body is optional but its extent must be determinate, so Content-Length is required unless the binding delimits the body by closing a stream. APPEND https://agent.example.com/travel ACP/1.0 ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d CSeq: 502 APPEND Sequence: 90 Entry-Type: input Prev-Hash: sha256-_NrWKsIcH0PxTqjFxzYbg4w8ad2vogH1iWwLtcffWBQ Author: spiffe://example.org/ns/agent/client-1 Timestamp: 1793312400 Event-Cursor: turn-complete Content-Type: multipart/mixed; boundary=acp-9b1deb4d Content-Length: 113 Entry-Hash: sha256-2qyCqGMY8i6F-zXfLQRYMkzVSHBqre6g0CkYq9mmziU --acp-9b1deb4d Content-Type: text/plain; charset=utf-8 Please review the flight schedule. --acp-9b1deb4d-- ACP/1.0 200 OK CSeq: 502 APPEND ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d Sequence: 90 Entry-Hash: sha256-2qyCqGMY8i6F-zXfLQRYMkzVSHBqre6g0CkYq9mmziU Content-Length: 0 Figure 7: An APPEND by the client, and its acceptance An entry authored by the server is identical in form, with Entry- Type: output and the server's URI as Author, and travels in the other direction on the log plane. The response echoes Sequence and Entry- Hash and nothing else is needed: the echo is the commit, and after it the entry is part of the log and its author may use its digest as the next Prev-Hash. A server rejects an APPEND with 409 if it does not extend its tail exactly (Section 6.1), with 422 if the received digest does not match the octets it got (Section 6.3), with 413 if the body is larger than it will accept, and with 415 if it cannot handle the media type. A Liu Expires 6 May 2027 [Page 25] Internet-Draft ACP November 2026 rejected entry is not written and its Sequence is not consumed. Until a final response arrives the entry is pending and its author is bound by Section 6.1.1. 5.4.3. CANCEL CANCEL asks the peer to stop work caused by an entry that is already in the log. It does not remove the entry and does not undo the dialog: an entry, once committed, is part of the history whether or not the work it caused was finished. Required fields: ADID, CSeq, Target-Seq. Optional: Reason, Event-Cursor. CANCEL https://agent.example.com/travel ACP/1.0 ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d CSeq: 503 CANCEL Target-Seq: 90 Reason: user-interrupted Content-Length: 0 ACP/1.0 200 OK CSeq: 503 CANCEL ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d Content-Length: 0 Figure 8: CANCEL and its acceptance CANCEL is a request to stop, not a guarantee that nothing further was produced. The recipient SHOULD stop as soon as it can and MUST then append an entry of Entry-Type: abort recording the Target-Seq and the reason, so that both replicas agree on where the abandoned work ended. That entry, not the 200, is what settles the cancellation in the log; a partial output produced before the stop MAY be appended as an output entry below it, and an application that must know how much was produced reads the two together. This is not an exception to Section 6.2: the cancellation closes the event, so what was produced before it is complete in the only sense that matters, namely that no more is coming. Fragments still in flight when the stop arrives are not part of any entry and are discarded. Because stopping work is often urgent and generation is often metered, a binding SHOULD give CANCEL the highest priority available and SHOULD NOT queue it behind log traffic (Section 7). A server that cannot identify the work referred to, because the entry is not in its log or the work already finished, responds 200 anyway: the requested end state holds. A server that is not authorized to be told to stop responds 403. Liu Expires 6 May 2027 [Page 26] Internet-Draft ACP November 2026 CANCEL does not change dialog state (Section 4). 5.4.4. SUSPEND SUSPEND tells the peer that the sender is going away and asks it to release runtime resources while keeping the dialog. It is advisory about resources and normative about nothing else: a dialog that is never suspended behaves identically, since losing the transport has the same effect (Section 4). Sending it is nonetheless useful, because it lets the server release capacity immediately rather than at a timeout, and it lets the sender ask for a specific retention period. Required fields: ADID, CSeq. Optional: Session-TTL. SUSPEND https://agent.example.com/travel ACP/1.0 ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d CSeq: 601 SUSPEND Session-TTL: 86400 Content-Length: 0 ACP/1.0 200 OK CSeq: 601 SUSPEND ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d Session-TTL: 86400 Tail-Seq: 90 Tail-Hash: sha256-2qyCqGMY8i6F-zXfLQRYMkzVSHBqre6g0CkYq9mmziU Min-Seq: 1 Content-Length: 0 Figure 9: SUSPEND and its acceptance The response reports the lifetime granted and the responder's tail, so the sender can tell before disconnecting whether it is about to strand an unacknowledged append. Session-TTL in the response MAY be shorter than requested; a server that will not retain the dialog at all responds 404 and terminates it. After a 200 the sender closes its channels and moves to SUSPENDED. 5.4.5. RESUME RESUME re-opens a suspended dialog. It is the entry point to alignment, and its outcomes are specified in Section 6.6.1. Required fields: ADID, CSeq, Tail-Seq, Tail-Hash. Optional: Min-Seq, Session- TTL. Liu Expires 6 May 2027 [Page 27] Internet-Draft ACP November 2026 The example below is the ordinary recovery case, and it exercises the pending-entry rule. The client sent the APPEND of Figure 7 and lost the connection before the response arrived, so the entry stayed pending and its tail is still 89. The server received and committed it. RESUME https://agent.example.com/travel ACP/1.0 ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d CSeq: 701 RESUME Authorization: Bearer eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOi... Tail-Seq: 89 Tail-Hash: sha256-_NrWKsIcH0PxTqjFxzYbg4w8ad2vogH1iWwLtcffWBQ Min-Seq: 1 Session-TTL: 259200 Content-Length: 0 ACP/1.0 206 Partial Content CSeq: 701 RESUME ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d Tail-Seq: 90 Tail-Hash: sha256-2qyCqGMY8i6F-zXfLQRYMkzVSHBqre6g0CkYq9mmziU Min-Seq: 1 Action: replay Replay-From: 90 Content-Length: 0 Figure 10: RESUME answered with a replay The server now replays entry 90 on the log plane. It is the entry of Figure 7, whose digest the client already holds as its pending entry, so the replay settles that entry as committed rather than duplicating it. Once the client has committed up to Tail-Seq 90 both participants are ACTIVE with no further exchange. Had the client instead sent new input while offline, it would renumber and resubmit it now (Section 6.1.1). RESUME MUST be authenticated and authorized against the dialog. A server MUST NOT reveal whether an ADID exists to a sender it has not authenticated; to one it has authenticated but that is not a participant of the dialog it responds 403 rather than 404, and to an unauthenticated sender it responds 401 (Section 8.1). 5.4.6. PROBE PROBE locates the last position at which two diverged replicas agree, after a 409. The procedure is specified in Section 6.6.2. Required fields: ADID, CSeq, and at least one Proof. Liu Expires 6 May 2027 [Page 28] Internet-Draft ACP November 2026 In the example, the client wrongly treated its entry 89 as committed while the server holds a different entry 89, produced after the hold expired and was extended. Both agree at 88. RESUME https://agent.example.com/travel ACP/1.0 ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d CSeq: 702 RESUME Authorization: Bearer eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOi... Tail-Seq: 90 Tail-Hash: sha256-2qyCqGMY8i6F-zXfLQRYMkzVSHBqre6g0CkYq9mmziU Min-Seq: 1 Content-Length: 0 ACP/1.0 409 Conflict CSeq: 702 RESUME ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d Tail-Seq: 90 Tail-Hash: sha256-0pNGg9pstIfSFkwGd466m1ObAHFrwyy2cp7nGHgrTIU Min-Seq: 1 Action: probe Content-Length: 0 PROBE https://agent.example.com/travel ACP/1.0 ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d CSeq: 703 PROBE Proof: 89=sha256-_NrWKsIcH0PxTqjFxzYbg4w8ad2vogH1iWwLtcffWBQ Proof: 88=sha256-ej6bM05D6ILtYQ7s78oWlq87P_1UAdmlri_92oCZUcM Content-Length: 0 ACP/1.0 200 OK CSeq: 703 PROBE ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d Proof: 88=sha256-ej6bM05D6ILtYQ7s78oWlq87P_1UAdmlri_92oCZUcM Tail-Seq: 90 Tail-Hash: sha256-0pNGg9pstIfSFkwGd466m1ObAHFrwyy2cp7nGHgrTIU Min-Seq: 1 Content-Length: 0 Figure 11: Divergence, and the PROBE that finds the ancestor The highest position the server confirmed is 88, so that is the common ancestor. The client moves its entries 89 and 90 back to pending, accepts a replay of the server's 89 and 90, and then renumbers its own input to 91 against the tail it has just been given. Only two rungs were needed here; a search that has to go Liu Expires 6 May 2027 [Page 29] Internet-Draft ACP November 2026 further adds 86, 82, 74, and so on, widening the step each time, and Section 6.6.2 bounds the whole ladder at sixteen proofs. The digests at 88, 89, and 90 are the ones the construction of Section 6.3 produces for the bodies shown in Section 5.4.2, so those rungs can be recomputed. 5.4.7. CHECKPOINT CHECKPOINT commits a prefix of the log to one entry so that the prefix can be discarded. The construction is in Section 6.5. Required fields: ADID, CSeq, and a body carrying Lower and Upper. Either participant may propose one; the ordering authority appends the entry. CHECKPOINT https://agent.example.com/travel ACP/1.0 ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d CSeq: 801 CHECKPOINT Content-Type: text/plain; charset=utf-8 Content-Length: 78 acp-checkpoint/1 88 90 sha256-eMqjKss9gHwczrgROqwJKOhAc04c0G30WVgbvF9AJ48 ACP/1.0 200 OK CSeq: 801 CHECKPOINT ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d CP-Seq: 91 CP-Hash: sha256-4eYccg4zhfuEkqtJWcZwf91PJUsFTps8TFd-fZk6Js8 Tail-Seq: 91 Tail-Hash: sha256-4eYccg4zhfuEkqtJWcZwf91PJUsFTps8TFd-fZk6Js8 Min-Seq: 91 Content-Length: 0 Figure 12: CHECKPOINT and its acceptance The checkpoint occupies Sequence 91 and is an ordinary entry, so CP- Hash and Tail-Hash are the same value and the next entry above it links to it as to any predecessor. Both participants may now discard entries 88 to 90, and Min-Seq becomes 91. A recipient that cannot reproduce the accumulator responds 409 and discards nothing. A server MUST NOT accept a CHECKPOINT from a sender it has not authorized for the dialog, and a client MAY refuse one it did not propose. Liu Expires 6 May 2027 [Page 30] Internet-Draft ACP November 2026 5.4.8. TERMINATE TERMINATE ends a dialog and permits both participants to purge its state. Required fields: ADID, CSeq. Optional: Reason. TERMINATE https://agent.example.com/travel ACP/1.0 ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d CSeq: 901 TERMINATE Reason: task-completed Content-Length: 0 ACP/1.0 200 OK CSeq: 901 TERMINATE ADID: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d Content-Length: 0 Figure 13: TERMINATE and its acceptance After a 200 both participants are TERMINATED: the log MAY be erased, the ADID MUST NOT be reused, and a later RESUME receives 404. A participant MAY terminate unilaterally, and a server MAY terminate on Session-TTL expiry without asking; the other participant learns of it on its next RESUME. Termination is therefore not a negotiation, and an application that needs both sides to agree before discarding history must arrange that above ACP. Purging is OPTIONAL and is a matter of local policy. A participant subject to a retention obligation MAY keep its replica after termination; doing so does not keep the dialog alive. 5.5. Status Codes A status code is three digits and a reason phrase. The reason phrase is descriptive only and a recipient MUST NOT parse it. ACP status codes occupy the same numeric space as HTTP [RFC9110] and SIP [RFC3261] and several deliberately echo them, but ACP defines its own code space and the meaning of a code is the one given here. In particular 206 and 412 are not HTTP's byte-range responses: they report the outcome of an alignment attempt. Class 1xx is reserved for provisional responses. This version defines none, but a recipient MUST accept and ignore one. A recipient that receives a code it does not recognize MUST treat it as the default for its class: 2xx as success, 3xx as a redirection it cannot follow, 4xx as a permanent failure of the request, and 5xx as a failure of the recipient that MAY succeed later. Liu Expires 6 May 2027 [Page 31] Internet-Draft ACP November 2026 +======+========================================================+ | Code | Meaning | +======+========================================================+ | 200 | The request succeeded. | +------+--------------------------------------------------------+ | 206 | Resumption accepted; the responder is ahead and will | | | replay from Replay-From (Section 6.6.1). | +------+--------------------------------------------------------+ | 400 | The message could not be parsed, a required field is | | | missing, or a digest names an unsupported algorithm. | +------+--------------------------------------------------------+ | 401 | The sender is not authenticated. | +------+--------------------------------------------------------+ | 403 | The sender is authenticated but is not a participant | | | of this dialog, or is not permitted this operation. | +------+--------------------------------------------------------+ | 404 | No dialog with this ADID, or it has terminated or its | | | Session-TTL expired. | +------+--------------------------------------------------------+ | 408 | The request was not completed in time. | +------+--------------------------------------------------------+ | 409 | The replicas disagree: an APPEND does not extend the | | | authoritative tail, a digest did not verify on replay, | | | or a checkpoint accumulator could not be reproduced. | | | For RESUME, proceed with PROBE (Section 6.6.2). | +------+--------------------------------------------------------+ | 412 | The sender's position is below the responder's Min- | | | Seq; align from the checkpoint instead | | | (Section 6.6.3). | +------+--------------------------------------------------------+ | 413 | The body is larger than the recipient accepts. | +------+--------------------------------------------------------+ | 415 | The media type is not supported for this dialog. | +------+--------------------------------------------------------+ | 422 | The message is well formed but the received Entry-Hash | | | does not match the octets received (Section 6.3). | +------+--------------------------------------------------------+ | 486 | The agent has no capacity for another dialog now; the | | | request MAY succeed later. | +------+--------------------------------------------------------+ | 488 | The offered modalities cannot be served | | | (Section 5.4.1). | +------+--------------------------------------------------------+ | 500 | The recipient failed internally. | +------+--------------------------------------------------------+ | 501 | The method is not implemented. | +------+--------------------------------------------------------+ | 503 | The recipient is unavailable; the request MAY succeed | Liu Expires 6 May 2027 [Page 32] Internet-Draft ACP November 2026 | | later. | +------+--------------------------------------------------------+ Table 7: ACP status codes Class 3xx is undefined in this version. Redirecting a dialog is not a simple matter of following a pointer, because the log lives where the dialog lives; a mechanism for it is deferred to a later revision. 6. The Log A dialog's durable state is its log: an ordered sequence of entries, each occupying one Sequence number, each carrying a digest of itself and of the entry before it. Both participants hold a replica. The log is append-only: an entry that has been committed is never edited, and a committed Sequence number is never reused. What changes history is not editing but truncation from the front (Section 6.5), which is itself a committed act. The log holds protocol state, not conversation. An entry may carry a message body, but nothing in ACP interprets it: the body is opaque, and an application is free to put a transcript, a tool call, or a capability description in it. What ACP requires is that the body be an octet string both participants can digest identically. Media is handled by reference rather than by inclusion (Section 6.4). 6.1. Entries and Sequencing Sequence is a positive integer. The first entry of a dialog is 1 and each subsequent entry is one greater, with no gaps in the authoritative log. The ordering authority for a dialog is its server: its replica defines what the log is, and a client replica that differs from it is wrong and is repaired (Section 6.6). A participant that authors an entry proposes the next Sequence and its Prev-Hash. The ordering authority accepts the entry only if it extends its own tail exactly, that is, only if the proposed Sequence is one greater than its current tail and the proposed Prev-Hash equals that tail's Entry-Hash. If it does, the entry is committed at that position and the response echoes both. If it does not, the entry is rejected with 409 and nothing is written; the author must align, then renumber its entry against the tail it learns, recompute the digest, and resubmit. Rejecting rather than silently renumbering keeps the digest of a committed entry stable: an entry is committed once, at one position, with one digest, and that digest is what the next entry's Prev-Hash refers to. Liu Expires 6 May 2027 [Page 33] Internet-Draft ACP November 2026 +------+ +------+ +------+ +------+ | e.88 |===>| e.89 |===>| e.90 |===>| e.91 | +------+ +------+ +------+ +------+ Prev=H87 Prev=H88 Prev=H89 Prev=H90 Hash=H88 Hash=H89 Hash=H90 Hash=H91 Figure 14: The log as a hash chain; e.N is the entry at Sequence N 6.1.1. Pending Entries An APPEND that has been sent but not finally answered leaves its entry pending. A pending entry is not committed. Its author: * MUST NOT report it as its tail in Tail-Seq and Tail-Hash; * MUST NOT use its Entry-Hash as the Prev-Hash of a later entry; * MUST retain it, with its digest, until alignment settles whether the ordering authority committed it; and * MUST NOT present it to its application as part of the dialog history without marking it unconfirmed. Pending entries are the ordinary source of divergence. A client whose APPEND timed out at T1 cannot know whether the entry was committed before the connection died, and a server that crashed may have committed it without answering. This is why alignment compares digests rather than counts (Section 6.6.1): a count says the two replicas are the same length, which is not the same statement as that they are the same log. Once alignment establishes the ordering authority's tail, each pending entry is settled by comparison. If the authority holds an entry at that Sequence with that Entry-Hash, the pending entry was committed and becomes part of the replica. If the authority's entry at that Sequence differs, or there is none, the pending entry was not committed: its author renumbers it against the tail, recomputes its digest, and resubmits it. Nothing is lost and nothing is duplicated, which is the property that makes an unacknowledged append safe to retry. Liu Expires 6 May 2027 [Page 34] Internet-Draft ACP November 2026 6.2. Event Boundaries A log entry is the unit of commitment, and ACP requires that it also be a unit of meaning: an entry closes exactly one complete event of the application that produced it, and an incomplete event is never committed. One turn of conversation, one tool invocation together with its result, one accepted user utterance, one cancellation are each a complete event. Half of a turn is not an event and MUST NOT become an entry. This rule is what makes the chain usable under streaming. An agent generating a long answer emits it as fragments on a data channel; the fragments carry no ACP header, no Sequence, and no digest (Section 3.2). Nothing is hashed while they flow. When generation ends, the author gathers the completed event into one body and appends one entry, so the cost of the chain is one digest per event rather than one per fragment. A connection that dies in the middle of generation therefore loses fragments that were never part of any entry: the chain is untouched, both tails still point at the last committed entry, and alignment has nothing to reconcile (Section 6.6). The alternative, digesting fragments as they arrive, would put a hash computation in the per-token path and would leave a truncated fragment committed in a chain that both peers then have to agree to forget. Two interruption cases look alike on the wire and are worth separating. If the connection dies while the author is still gathering the event, no APPEND was sent, no entry exists on either side, and the fragments are simply dropped. If it dies after the author sent the APPEND but before the response arrived, the entry is pending (Section 6.1.1): the peer may or may not have committed it, and alignment settles which by comparing digests. In neither case is a partial event committed, and in neither case does a participant have to guess how many octets of an unfinished stream the other one received. An author MAY record which boundary an entry closes by including Event-Cursor, whose value is a token [RFC9110] meaningful to the application, such as turn-complete or tool-result-3. ACP neither defines the token space, nor requires the field, nor interprets it. Its use is local and diagnostic: it tells an application which step of its own execution a given Sequence corresponds to, which is what it needs to re-run the right step after a rollback (Section 6.6.2) or to continue at the right point after an interruption. Event-Cursor is deliberately not part of the digest input (Section 6.3). Alignment compares digests and sequence numbers; it never compares cursors. Two replicas holding identical bytes hold Liu Expires 6 May 2027 [Page 35] Internet-Draft ACP November 2026 the same log whatever their cursors say, and a cursor inside the digest would let an application-level label cause a 422 on an otherwise valid entry. A CANCEL MAY carry the cursor of the boundary at which the sender wants work to stop; that is a hint about where to cut, not a position in the log, and the normative target of a cancellation remains Target-Seq (Section 5.4.3). 6.3. The Entry Digest Each entry carries Entry-Hash, the digest of a fixed octet string built from six field values and the body. The construction is the whole basis of alignment, so it is stated once and precisely. digest-input = ADID-value LF Prev-Hash-value LF Sequence-value LF Entry-Type-value LF Author-value LF Timestamp-value LF body-octets Entry-Hash = "sha256-" base64url( SHA-256( digest-input ) ) Figure 15: The digest input Each -value is the corresponding header field value exactly as it appears in the message, after stripping leading and trailing OWS, and without the field name or the colon. body-octets is the body, exactly Content-Length octets, or the octets between the blank line and the end of the stream where Content-Length is omitted as Section 5.1 allows. An empty body contributes zero octets. The separator is LF (0x0A), not CRLF: the digest input is deliberately not a substring of any message, so that no part of a wire encoding can be mistaken for it. SHA-256 is as specified in [RFC6234] and base64url in [RFC4648], Section 5, without padding. For the entry at Sequence 1 there is no predecessor. Its Prev-Hash is the constant GENESIS, defined as sha256- followed by 43 A characters, which is the base64url encoding of 32 zero octets. GENESIS is a constant and not a digest of anything; it MUST NOT be interpreted as an entry. A log with no entries is described in the position fields as Tail-Seq: 0 with Tail-Hash equal to GENESIS, which keeps the invariant that the entry at Sequence n carries the digest of n - 1 in its Prev-Hash true for n = 1 without a special case. Why these six fields and not the whole message. A digest over the complete header block would depend on field order, on OWS, and on fields that legitimately differ between the original transmission of Liu Expires 6 May 2027 [Page 36] Internet-Draft ACP November 2026 an entry and its replay, so two participants could hold the same entry and compute different digests. That is the failure this construction exists to avoid. Why these six and not the body alone. A digest over the body would leave the entry's position, its predecessor, its type, and its author uncommitted, so an entry could be relabelled, reordered, or moved to another dialog without changing its digest. Binding the ADID in particular is what stops an entry from one dialog being replayed into another at the same position. The six fields are exactly those whose meaning a verifier must be able to trust. Fields not in the digest input are protected only by the channel. That is acceptable for CSeq, which is per transaction and differs when an entry is resubmitted, for Event-Cursor, which labels the boundary an entry closes rather than anything the entry asserts (Section 6.2), and for Content-Length, which the recipient can check against what it received. It is also acceptable for the message- level Content-Type, because a body that needs typed parts carries them as MIME parts [RFC2046] whose own Content-Type headers are inside the body and therefore covered. An implementation that needs the message-level media type to be committed SHOULD repeat it as the first body part header. A recipient of an APPEND MUST recompute the digest and compare it with the received Entry-Hash before committing the entry. On mismatch it MUST NOT commit, MUST respond 422, and SHOULD treat the dialog as requiring alignment, since a mismatch means the two participants disagree about the octet string and not merely about a checksum. The digest of an entry depends only on octets its author already held, so it can be computed once and verified anywhere, including by a participant that never saw the original transmission. It is not a signature. A digest proves that two replicas hold the same bytes; it does not prove who produced them, and a participant that can write to the authoritative log can rewrite history and produce consistent digests. Per-entry signatures are deferred to a later revision. 6.4. Media and Large Assets A dialog that ran for hours of voice and video would have an unusable log if every entry digested its media. ACP therefore keeps media out of the chain, in two ways according to whether the media is stored or live. Stored media is carried by reference. A MIME part MAY omit its content and carry instead an Asset-Ref parameter giving the hash- value of the asset's octets and an Asset-Size giving their length: Liu Expires 6 May 2027 [Page 37] Internet-Draft ACP November 2026 --acp-9b1deb4d Content-Type: video/mp4 Asset-Ref: sha256-GIgdzwklKPw4gUd4U32RfGAuSrr5MEpdNK5NP3bMj78 Asset-Size: 104857600 Content-Location: https://agent.example.com/acp-asset/9b1deb4d/a3 Figure 16: A body part that references an asset The reference is text inside the body, so the digest commits to it, and the asset's octets are transferred separately on an asset channel (Section 7) and never enter the digest input. A recipient that retrieves the asset MUST verify it against Asset-Ref. A consequence worth stating plainly: a log can be fully aligned and every digest verified while an asset is still missing, and an asset can be lost without invalidating the chain. That is intended. The chain records what the dialog said about its media, which is the part that has to survive days of separation; the media itself has its own storage and its own lifetime. Live media is not an asset and is not referenced either. It flows on its own channels while the dialog is active, and the event that opens or closes a media session is recorded as a meta entry describing it (Section 6.2), for example: Session-Type: realtime-voice Media-Status: active Active-Tracks: audio-01 (opus/48000/2) Transport-Mapping: wt-session 0xef4a Figure 17: A meta entry body Such an entry is a few hundred octets, costs one digest, and is enough to re-establish the media path after an interruption. ACP does not define the fields of a meta body, does not transcribe speech, and does not summarize a conversation: those are application concerns, and an application that wants a transcript in the log appends an entry containing one. Keeping them out is what lets the signaling path stay short enough not to interfere with the media it is setting up. 6.5. Checkpoints and Truncation A dialog may run for months. Its log must not grow without bound, so ACP allows a prefix of it to be committed to a single entry and then discarded. A checkpoint is itself an entry, of Entry-Type system, appended at the next Sequence like any other. Making it an entry rather than a side structure is deliberate: it keeps the chain continuous across truncation, it means a checkpoint has an Entry-Hash Liu Expires 6 May 2027 [Page 38] Internet-Draft ACP November 2026 of exactly the same kind as any other entry, and it means a participant that has lost everything below a checkpoint can still resume by naming that one entry (Section 6.6.3). The body of a checkpoint entry is four lines: body = "acp-checkpoint/1" CRLF Lower CRLF Upper CRLF accumulator CRLF Lower = seq ; first Sequence covered, inclusive Upper = seq ; last Sequence covered, inclusive accumulator = "sha256-" base64url( SHA-256( cp-input ) ) cp-input = for i = Lower to Upper, in increasing order: Entry-Hash-value(i) LF Figure 18: Checkpoint entry body and accumulator The body is ordinary message content, so its line endings are CRLF like the rest of a message. cp-input is not a wire format: it is the octet string the accumulator is computed over, and its separator is LF, as in Section 6.3. where Entry-Hash-value(i) is the complete textual hash-value of the entry at Sequence i, and Lower is the proposer's current Min-Seq, which is 1 for a dialog that has never been checkpointed. Checkpoints therefore compose: a checkpoint whose Lower is an earlier checkpoint's Sequence is well defined, and a participant that has already truncated can still take part in a later one. A CHECKPOINT transaction proposes Lower and Upper. The recipient recomputes accumulator from the entries it holds. If it matches, the ordering authority appends the checkpoint entry and responds 200 with CP-Seq set to that entry's Sequence and CP-Hash to its Entry-Hash. Both participants record the entry durably, and only then MAY either discard entries with Sequence below CP-Seq; Min-Seq becomes CP-Seq. If the recipient cannot recompute accumulator, because the digests disagree or because it has already discarded part of the range without holding a checkpoint that covers it, it MUST NOT discard anything and MUST respond 409, or 412 where Section 6.6.3 applies. Discarding before the peer has confirmed is not recoverable and MUST NOT be done. Sequence numbers are never reset by a checkpoint, and the checkpoint entry is retained: the entry above it carries its Entry-Hash as Prev- Hash, so the chain above a checkpoint links to the chain below it through a single digest. A dialog checkpointed a hundred times still has one continuous numbering. A participant holding only the latest Liu Expires 6 May 2027 [Page 39] Internet-Draft ACP November 2026 checkpoint and the entries above it can still verify every entry it holds, and a forged prefix would require inverting the checkpoint entry's digest. 6.6. Log Alignment Alignment is what makes a dialog survive its transport. A participant that reconnects after an hour or after a week runs the same procedure, and the cost depends on how much it missed rather than on how long it was away. The procedure has three outcomes, decided by one exchange: the replicas agree, the client is behind, or they diverged. A fourth case, where the client is behind by more than the server retains, is handled by Section 6.6.3. 6.6.1. Tail Verification The client sends RESUME with Tail-Seq and Tail-Hash giving its last committed entry, and with Min-Seq. It MUST NOT report a pending entry as its tail (Section 6.1.1). The server then applies the first rule that matches: +===+=============================================+=================+ | # | Condition | Response | +===+=============================================+=================+ | 1 | ADID unknown, terminated, or | 404 | | | TTL expired | | +---+---------------------------------------------+-----------------+ | 2 | Sender not authenticated or | 401 or 403 | | | not authorized for this dialog | | +---+---------------------------------------------+-----------------+ | 3 | Client Tail-Seq is below | 412 with | | | server Min-Seq | Action: resync | +---+---------------------------------------------+-----------------+ | 4 | Server holds no entry at the | 409 with | | | client's Tail-Seq, or holds | Action: probe | | | one with a different digest | | +---+---------------------------------------------+-----------------+ | 5 | Tails equal | 200 | +---+---------------------------------------------+-----------------+ | 6 | Server tail ahead of client | 206 with | | | tail | Action: replay | | | | and Replay-From | +---+---------------------------------------------+-----------------+ Table 8: RESUME outcomes Liu Expires 6 May 2027 [Page 40] Internet-Draft ACP November 2026 The order matters. Rule 3 precedes rule 4 because a client below Min-Seq cannot be probed: the entries needed to find a common ancestor are gone. Rules 5 and 6 are reached only when the digests match, which is the point of comparing digests rather than lengths. Every response to RESUME carries the server's Tail-Seq, Tail-Hash, and Min-Seq, and CP-Seq and CP-Hash where a checkpoint exists, so the client learns the authoritative position and any truncation in the same exchange. On 206 the server replays entries from Replay-From, which is the client's Tail-Seq plus one, up to and including its own tail, in increasing Sequence order, on the log plane. The recipient verifies each entry's digest and that its Prev-Hash equals the Entry-Hash of the entry below it, and commits each as it arrives; replay is driven by the transport's ordering, not by per-entry acknowledgement. Alignment is complete when the entry at the Tail-Seq announced in the 206 is committed, so no further message is needed, the target having been announced in advance. If T2 expires first, the attempt fails and MAY be retried with a new RESUME. On 200 or on completion of a replay, both participants are ACTIVE. The client then settles any pending entries as Section 6.1.1 describes, renumbering and resubmitting those the server did not commit. 6.6.2. Fork Detection and Resolution A 409 means the two replicas held the same dialog and now disagree about it. The cause is usually benign: an APPEND whose acknowledgement was lost, a server that recovered from a crash behind its last flush, or a client that committed an entry it should have left pending. Resolution is to find the last position at which the two agree and rebuild above it. The client sends PROBE carrying a ladder of Proof fields: one for each of the positions Tail-Seq - 1, Tail-Seq - 2, Tail-Seq - 4, and so on by powers of two down to its Min-Seq, one for Min-Seq itself, and at most 16 in total. The server responds 200 with Proof fields for exactly those positions whose digest it also holds, together with its own Tail-Seq, Tail-Hash, and Min-Seq. It MUST NOT assert a pair it does not hold, and it need not explain the absence of one. The highest matching position is the common ancestor. The client moves every entry it holds above it back to pending, accepts a replay from the position above it, and then renumbers and resubmits its pending entries against the tail it has been given. Because a renumbered entry has a different Sequence and a different Prev-Hash, Liu Expires 6 May 2027 [Page 41] Internet-Draft ACP November 2026 it has a different digest: the two versions of the same input are distinct entries, and only the one the ordering authority committed is in the log. No content is lost, and the chain above the ancestor is the server's alone. A 16-pair ladder reaches 2^15 entries below the tail, so one PROBE settles almost every divergence. Where it does not, the client continues from the ancestor it found with a further PROBE. If no pair matches, the divergence is below everything the ladder reaches and the server responds 412 instead; Section 6.6.3 applies. A server MUST rate-limit PROBE per dialog, since each one is a read against durable storage and none of them makes forward progress. 6.6.3. Resynchronization Below a Checkpoint A participant that has been away long enough to fall below the other's Min-Seq cannot be aligned entry by entry, because the entries are gone. A 412 carries Action: resync together with Min-Seq, CP- Seq, CP-Hash, Tail-Seq, and Tail-Hash. Because a checkpoint is an ordinary entry (Section 6.5), CP-Hash is the Entry-Hash of the entry at CP-Seq and can be adopted as a tail directly, with no second kind of digest value anywhere in the protocol. The recipient first checks whether it holds the entry at CP-Seq. If it does and the digest matches, its own history is a prefix of the authoritative one and it simply discards what is below and continues. If it does not hold that entry, or the digest differs, its history below CP-Seq is unreconcilable: it MUST stop treating those entries as part of the dialog, SHOULD retain them in local storage if its own policy permits, since they may be the only record it has of what it was told, and then adopts the checkpoint as its base by setting Min- Seq and Tail-Seq to CP-Seq and Tail-Hash to CP-Hash. A second RESUME then proceeds normally and is answered 200 or 206. A participant that adopts a checkpoint it could not verify is trusting the ordering authority. That is not a new trust: it already relies on that authority for every entry it was given. What the checkpoint changes is that the reliance can no longer be checked against the discarded prefix. A signed checkpoint would remove the reliance and is deferred to a later revision. 7. Transport Bindings 7.1. Binding Requirements ACP is transport-independent, and a binding is the mapping of its channels onto one transport. A binding MUST provide: Liu Expires 6 May 2027 [Page 42] Internet-Draft ACP November 2026 * a reliable, ordered, bidirectional channel for the control plane, on which many messages may follow one another; * a reliable, ordered channel for the log plane that does not share a head-of-line queue with the control plane, so that a large entry cannot delay a CANCEL; * a way to carry asset octets without blocking either of the above; and * a signal when the connection is lost, so that a participant can move to SUSPENDED (Section 4). A binding SHOULD also provide an unreliable low-latency channel for progress traffic, and SHOULD support connection migration, which lets a dialog stay ACTIVE across a change of network path. A binding that provides neither is still conformant; progress is then carried on the log channel and simply not logged, and migration is then no better than a suspend and resume. Every stream a binding opens for ACP begins with a preamble that says what the stream carries: channel-preamble = "ACP/1.0" SP channel-name CRLF channel-name = "control" / "log" / "asset" / token Figure 19: Stream preamble A recipient MUST read the preamble before treating a stream as ACP and MUST reset a stream whose preamble it does not recognize. The preamble is what identifies a channel, and no binding may identify one by a stream number instead: transports assign stream identifiers, and an application cannot choose one. Messages on the control channel are delimited by Content-Length, which is REQUIRED there. On a log channel exactly one entry message is sent per stream and the end of the stream delimits it, so Content-Length MAY be omitted; the octets that follow the preamble are the entry exactly as its author digested it, and a recipient MUST NOT re-encode them before verifying the digest. 7.2. MoQ Binding This binding carries the log plane on Media over QUIC Transport (MoQ) [I-D.ietf-moq-transport]. It is the binding to use where a dialog should be relayable and cacheable by infrastructure that understands MoQ, and where recovery of missed entries should be a subscription rather than an application-level replay. Liu Expires 6 May 2027 [Page 43] Internet-Draft ACP November 2026 A dialog occupies one track namespace: { authority, "acp", adid } Figure 20: The track namespace of a dialog where authority is the domain of the agent service that publishes the dialog and adid is the ADID, which uses only URI-unreserved characters and so needs no further encoding. The literal "acp" keeps these namespaces distinct from other uses of the same authority. Because the ADID is in the namespace, a relay forwards, caches, and correlates every track of a dialog without decrypting or interpreting a payload, and a peer that sees the same namespace on a new session can correlate it with the dialog it already knows. +===================+==========================================+ | ACP | MoQ | +===================+==========================================+ | Dialog | Track namespace {authority, "acp", adid} | +-------------------+------------------------------------------+ | Authoritative log | The track named log, published by the | | | ordering authority | +-------------------+------------------------------------------+ | One committed | One object on log, with Group equal to | | entry | Sequence and Object 0 | +-------------------+------------------------------------------+ | Control plane | A bidirectional stream in the same | | | session, carrying the control preamble | +-------------------+------------------------------------------+ | One asset or | A track of its own in the namespace, | | media track | named by the application | +-------------------+------------------------------------------+ | Replay after | SUBSCRIBE to log starting at Group Tail- | | resumption | Seq + 1 | +-------------------+------------------------------------------+ Table 9: ACP mapped onto MoQ Two points in this mapping need stating, because both are places where an obvious alternative does not work. Liu Expires 6 May 2027 [Page 44] Internet-Draft ACP November 2026 A committed entry is carried as a single object rather than split across one object per MIME part. Splitting would require a recipient to reassemble parts before it could verify the digest, and any reassembly that is not byte-exact turns a verified entry into an unverified one. One object per entry means the object payload is the octet string the author digested, and verification is a single pass over what arrived. Bulk content is separated by the asset reference of Section 6.4, not by the object structure. The control plane does not ride MoQ control messages. MoQ data tracks flow from publisher to subscribers, and putting ACP requests inside MoQ control messages would require an extension to MoQ that this document cannot define. Using a bidirectional stream in the same session needs no extension, keeps the preamble framing of Section 7.1, and lets both participants send requests. Whether a native MoQ control-message binding is worth defining is left open. Only the ordering authority publishes log, and it publishes every committed entry including those a client authored. A single authoritative track is what makes recovery a subscription: the client subscribes from the group above its tail and receives exactly the entries it is missing, in order, from whatever cache can serve them. Relay caching is an optimization and not a store. The ordering authority MUST be able to serve the whole retained range itself, and a subscriber MUST NOT treat an object as committed until its digest verifies. 7.3. WebTransport Binding This binding runs ACP over WebTransport [I-D.ietf-webtrans-http3], and therefore over HTTP/3 [RFC9114] and QUIC [RFC9000]. It is the binding to use where one endpoint is a browser or another environment that offers WebTransport but not a general QUIC stack. The request target of Section 5.4.1 is already an https origin and path, so the client opens a WebTransport session to it directly with an extended CONNECT. The session is the dialog's transport for as long as it lives, and it may carry more than one dialog, since every stream is identified by its preamble and every message by its ADID. Liu Expires 6 May 2027 [Page 45] Internet-Draft ACP November 2026 +============+=================================================+ | ACP | WebTransport | +============+=================================================+ | Control | The first bidirectional stream the client opens | | plane | in the session, carrying the control preamble | +------------+-------------------------------------------------+ | One log | One unidirectional stream opened by the entry's | | entry | author, carrying the log preamble, closed when | | | the entry is complete | +------------+-------------------------------------------------+ | One asset | One unidirectional stream carrying the asset | | | preamble, at lower priority than log | +------------+-------------------------------------------------+ | Progress | QUIC datagrams [RFC9297] | | traffic | | +------------+-------------------------------------------------+ | Connection | Session closure or abort | | loss | | +------------+-------------------------------------------------+ | Change of | QUIC connection migration; the dialog stays | | network | ACTIVE | | path | | +------------+-------------------------------------------------+ Table 10: ACP mapped onto WebTransport Because a log entry occupies its own stream, an entry carrying a large body cannot delay the control plane or another entry, and several entries and assets may be in flight at once. A sender SHOULD set stream priority so that control outranks log and log outranks asset. Progress datagrams are limited in size by the path MTU and are neither delivered nor ordered. A binding MUST NOT put anything on them that the log or the state machine depends on, and a recipient MUST tolerate losing any of them. Where datagrams are unavailable, progress traffic MAY be sent on the control channel, in which case it MUST still be excluded from the log. 8. Security Considerations ACP defines no key exchange, no authentication mechanism, and no confidentiality mechanism of its own. It is a session protocol that assumes it is given a channel with three properties: the peer is authenticated, the channel is confidential and integrity-protected, and messages are not delivered to anyone else. Every binding in Section 7 provides these through QUIC [RFC9000], which mandates TLS 1.3. ACP MUST NOT be used over a transport that does not provide Liu Expires 6 May 2027 [Page 46] Internet-Draft ACP November 2026 them, and an implementation MUST NOT fall back to such a transport. Who a participant is, and what it may do, are decided above and below ACP. Below it, the channel tells each endpoint who the peer is; a deployment identifying agents by workload uses a workload identity [I-D.ietf-wimse-workload-creds]. Above it, the ordering authority decides whether an authenticated peer may append to a given dialog. ACP assumes both decisions have been made correctly and does not re- make them. 8.1. Dialog Identifiers An ADID is 128 bits drawn from a random source [RFC4086], so it cannot be guessed at any useful rate. That property is doing real work: several places in this document answer a request about a dialog the sender is not a participant of, and rely on the sender not having found the dialog by searching. An implementation MUST NOT generate ADIDs from a counter, a timestamp, or any other low-entropy source, and MUST NOT reuse one. Knowledge of an ADID is nonetheless not authority to use it. A server MUST authorize every request against the dialog's participants independently of whether the request names the dialog correctly, and MUST NOT treat a correct ADID as proof that the sender belongs to the dialog. Because an ADID is a bearer string that appears in every message, it will end up in logs, proxies, and error reports; a deployment SHOULD treat a leaked ADID as a reason to terminate and re-initiate rather than as a harmless disclosure. Section 5.4.5 has a server answer 403 to a sender it recognizes and 404 to one it does not, which reveals that the dialog exists. That is deliberate: a client recovering on a new device needs to know whether to resume or to start over. A server concerned about the disclosure MAY answer 404 to every sender it has not authorized, at the cost of making recovery from a lost credential indistinguishable from a lost dialog. 8.2. Authorizing Session Establishment Establishing a dialog requires the client to obtain authorization, and ACP does that with existing OAuth mechanisms rather than defining one of its own. The token it obtains is carried in the Authorization field of Section 5.2. Within a trust domain the client presents a Transaction Token [I-D.ietf-oauth-transaction-tokens], obtained from the workload identity it already holds. A Transaction Token carries the delegation context of one transaction, not the standing authority of Liu Expires 6 May 2027 [Page 47] Internet-Draft ACP November 2026 a workload, which is what lets the ordering authority authorize a dialog against the principal the client acts for and not only against the workload that asked. Its narrow scope and short lifetime are also what make it safe to carry in a header field that will end up in logs. Across trust domains there is no issuer both sides accept, so the client instead trades the credential it holds for one the remote domain accepts using OAuth 2.0 Token Exchange [RFC8693], naming the remote service as the audience. Because the token in Authorization is not the credential the channel authenticated, the two must be tied together: the workload identity the channel authenticated, the From of the request, and the identity the token authorizes MUST all name the same participant (Section 3.5). A server that cannot establish that, or that cannot validate the token, answers 403. A token is minted per request, not per dialog: a transaction token is short-lived, and a RESUME days after its INITIATE is a new transaction carrying a new token. 9. IANA Considerations This document requests that IANA create registries for the protocol's namespaces. The registries are listed here so that the namespace they govern is reserved; their registration procedures and initial contents will be specified in a later revision of this document. 9.1. ACP Registries IANA is requested to create an "Agent Communication Protocol (ACP) Parameters" registry group containing the registries in Table 11. Liu Expires 6 May 2027 [Page 48] Internet-Draft ACP November 2026 +=====================+===============================+=============+ | Registry | Governs | Section | +=====================+===============================+=============+ | ACP Methods | Request method tokens | Section 5.4 | +---------------------+-------------------------------+-------------+ | ACP Status Codes | Numeric response codes | Section 5.5 | +---------------------+-------------------------------+-------------+ | ACP Header Fields | Header field names | Section 5.2 | +---------------------+-------------------------------+-------------+ | ACP Entry Types | Entry-Type values | Section 6 | +---------------------+-------------------------------+-------------+ | ACP Hash Algorithms | hash-alg prefixes | Section 6.3 | +---------------------+-------------------------------+-------------+ | ACP Channel Names | Stream preamble | Section 7.1 | | | channel names | | +---------------------+-------------------------------+-------------+ Table 11: Requested ACP registries 10. References 10.1. Normative References [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . [RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types", RFC 2046, DOI 10.17487/RFC2046, November 1996, . [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, . [RFC4086] Eastlake 3rd, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, DOI 10.17487/RFC4086, June 2005, . Liu Expires 6 May 2027 [Page 49] Internet-Draft ACP November 2026 [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, . [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, . [RFC6234] Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, May 2011, . [RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type Specifications and Registration Procedures", BCP 13, RFC 6838, DOI 10.17487/RFC6838, January 2013, . [RFC8693] Jones, M., Nadalin, A., Campbell, B., Ed., Bradley, J., and C. Mortimore, "OAuth 2.0 Token Exchange", RFC 8693, DOI 10.17487/RFC8693, January 2020, . [RFC9000] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based Multiplexed and Secure Transport", RFC 9000, DOI 10.17487/RFC9000, May 2021, . [RFC9110] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI 10.17487/RFC9110, June 2022, . [RFC9114] Bishop, M., Ed., "HTTP/3", RFC 9114, DOI 10.17487/RFC9114, June 2022, . [RFC9297] Schinazi, D. and L. Pardue, "HTTP Datagrams and the Capsule Protocol", RFC 9297, DOI 10.17487/RFC9297, August 2022, . [RFC9562] Davis, K., Peabody, B., and P. Leach, "Universally Unique IDentifiers (UUIDs)", RFC 9562, DOI 10.17487/RFC9562, May 2024, . [I-D.ietf-webtrans-http3] Frindell, A., Kinnear, E., and V. Vasiliev, "WebTransport over HTTP/3", Work in Progress, Internet-Draft, draft- Liu Expires 6 May 2027 [Page 50] Internet-Draft ACP November 2026 ietf-webtrans-http3-16, 6 July 2026, . [I-D.ietf-moq-transport] Nandakumar, S., Vasiliev, V., Swett, I., and A. Frindell, "Media over QUIC Transport", Work in Progress, Internet- Draft, draft-ietf-moq-transport-22, 1 October 2026, . [I-D.ietf-wimse-workload-creds] Campbell, B., Salowey, J. A., Schwenkschuster, A., Sheffer, Y., and Y. Rosomakho, "WIMSE Workload Credentials", Work in Progress, Internet-Draft, draft- ietf-wimse-workload-creds-02, 2 July 2026, . [I-D.ietf-oauth-transaction-tokens] Tulshibagwale, A., Fletcher, G., and P. Kasselman, "Transaction Tokens", Work in Progress, Internet-Draft, draft-ietf-oauth-transaction-tokens-11, 30 July 2026, . [SPIFFE] CNCF SPIFFE Project, "Secure Production Identity Framework for Everyone (SPIFFE)", 2025, . Defines the workload identity form permitted for a participant identifier (Section 3.4). 10.2. Informative References [RFC3261] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP: Session Initiation Protocol", RFC 3261, DOI 10.17487/RFC3261, July 2002, . [I-D.manyfolks-agentproto-arch] Rosenberg, J., Sarker, Z., Reddy.K, T., Yao, K., Liu, D., and S. Krishnan, "Architecture for AI Agent Communications on the Internet", Work in Progress, Internet-Draft, draft- manyfolks-agentproto-arch-00, 30 October 2026, . Liu Expires 6 May 2027 [Page 51] Internet-Draft ACP November 2026 Acknowledgements TBD. Author's Address Dapeng Liu Alibaba Email: max.ldp@alibaba-inc.com Liu Expires 6 May 2027 [Page 52]