| Internet-Draft | AIP | October 2026 |
| Prakash | Expires 13 April 2027 | [Page] |
This document specifies the Agent Identity Protocol (AIP), which conveys delegated authority along a chain of AI agents so that a relying party can verify, from the token and the issuer's public key, who granted the authority, through which agents it passed, and that no hop widened what it received. AIP addresses hops where no authorization server is on the path, such as one agent subdelegating to another. It is intended to compose with the AI Identity Management System (AIMS) framework, which covers hops where an authorization server is present. The document defines an encoding-neutral delegation chain model with a single attenuation invariant, a normative verification algorithm, and two encodings of the model: a chain of JSON Web Tokens, in which each link names the key of the next holder, and a Biscuit token with Datalog policy. Bindings are given for the Model Context Protocol (MCP), the Agent2Agent protocol (A2A), and generic HTTP.¶
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/.¶
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 13 April 2027.¶
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.¶
In a multi-agent system an orchestrator splits a task and hands parts of it to other agents, which may hand parts on again. The Model Context Protocol (MCP) [MCP] and the Agent2Agent protocol (A2A) [A2A] define how agents and tools connect. MCP specifies OAuth-based authorization for the hop between a client and a server, and A2A agents can declare authentication requirements. Neither carries a verifiable record of authority as it passes through several agents.¶
The AI Identity Management System framework [I-D.ietf-wimse-aims] describes how agents obtain identifiers and credentials from the WIMSE architecture and how OAuth 2.0 mechanisms, including token exchange [RFC8693], transaction tokens [I-D.ietf-oauth-transaction-tokens], and identity and authorization chaining across domains [I-D.ietf-oauth-identity-chaining], apply to agent authorization. In those mechanisms, narrowing is done by an authorization server or token service that evaluates its policy and issues a new token. The holder does not narrow its own token.¶
Some hops have no such server. An agent that hands part of its task to a subagent, or to an agent in another organization with which no authorization server trust has been arranged, has to pass on a subset of its own authority directly. The relying party at the end of such a chain then needs to check, without calling back to the origin, that each hop narrowed or kept what it received.¶
AIP specifies that check. For every action it lets a relying party answer three questions from the presented token: who authorized the action, through which delegation chain, and with what constraints at each hop. Section 3 defines the chain and its attenuation invariant, Section 4 the verification algorithm, and Section 5 two encodings. Section 7 describes how AIP is intended to sit alongside AIMS.¶
This document cites [RFC8785] normatively as a downward reference [RFC8067]. The [BISCUIT] reference is pinned to tag v3.3 of the Biscuit specification.¶
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.¶
AIP defines two identifier schemes for agent identity. Every issuer, delegator, and delegate in a chain is named by one of them.¶
DNS-based identifiers follow the format:¶
aip:web:<domain>/<path>¶
Example: aip:web:example.com/agents/research-analyst¶
DNS-based identifiers are suitable for long-lived agents with stable domain ownership. Identity documents are resolved via HTTPS at a well-known path.¶
aip:key:ed25519:<multibase-encoded-public-key>¶
Self-certifying identifiers derive identity from the public key itself. They are suitable for ephemeral agents that do not require DNS infrastructure. The identifier is computed from the 32-byte Ed25519 [RFC8032] public key encoded as multibase base58btc (a "z" prefix followed by the base58btc encoding of the key).¶
Each agent with a DNS-based identifier MUST publish an identity document at:¶
https://<domain>/.well-known/aip/<path>.json¶
The identity document is a JSON object containing:¶
aip: Protocol version (MUST be "1.0")¶
id: The agent's AIP identifier¶
public_keys: Array of public key objects, each with
id, type, public_key_multibase (the
Ed25519 key in multibase base58btc, as in
Section 2.2), and optional
valid_from and valid_until¶
name: Human-readable agent name¶
delegation: Delegation preferences¶
protocols: Supported protocol bindings¶
revocation: OPTIONAL revocation endpoint (see
Section 4.7)¶
document_signature: Ed25519 signature over the
canonicalized document, encoded as base64url without padding
(Section 5 of [RFC4648])¶
expires: Document expiration timestamp¶
The document MUST be self-signed. Verification uses JSON Canonicalization Scheme (JCS) [RFC8785]: remove the document_signature field, canonicalize the remaining JSON, and verify the Ed25519 signature against a currently-valid public key.¶
This section defines what a chain says, independent of how it is encoded. Each encoding in Section 5 MUST be parsed into this model before steps V3 through V6 of Section 4 are applied, so that the two encodings are verified by one set of rules.¶
A chain is an ordered list of links L0, L1, ..., LN. L0 is the authority link. L1 through LN are delegation links. Each link has the following fields:¶
| Field | L0 | Li, i >= 1 |
|---|---|---|
| issuer | REQUIRED | REQUIRED, the delegate of L(i-1) |
| delegate | REQUIRED in JWT; absent in Biscuit | REQUIRED |
| tools | REQUIRED | OPTIONAL, inherits |
| domains | OPTIONAL | OPTIONAL, inherits |
| budget_ceiling | OPTIONAL | OPTIONAL, inherits |
| expiry | REQUIRED | OPTIONAL, inherits |
| context | absent | REQUIRED, non-empty |
| principal | OPTIONAL | OPTIONAL, invariant once declared |
| max_depth | REQUIRED | MUST NOT appear |
| holder key | REQUIRED in JWT | REQUIRED in JWT |
When tools or domains is present in any link, it MUST be
non-empty. An empty list is malformed, and a verifier MUST reject
a chain containing one with aip_token_malformed. Absence
means the link inherits; it never means "nothing permitted".¶
The effective value of a dimension at L0 is the value L0 declares. The effective value at Li is the value Li declares if it declares one, and otherwise the effective value at L(i-1). The effective values at LN are the authority the chain conveys to its final holder.¶
An effective domains value that is undefined at every link means the chain places no constraint on domains. The same holds for budget_ceiling and principal. A delegation link MAY declare a domains list, a budget ceiling, or a principal when no ancestor declares one; doing so narrows the chain.¶
For every i of 1 or more, and for every dimension (tools, domains, budget_ceiling, expiry, and principal), the effective value at Li MUST be narrower than or equal to the effective value at L(i-1): every tool Li permits MUST be permitted at L(i-1); every domain Li permits MUST be permitted at L(i-1); the budget ceiling at Li MUST NOT exceed that at L(i-1); the expiry at Li MUST NOT be later than that at L(i-1); and once a link declares a principal, no later link may declare a different one. A chain that violates this invariant at any hop conveys no authority, and verifiers MUST reject it as specified in step V4 of Section 4.¶
The invariant is a property of the capability content. It is not established by the signature structure of either encoding, and it is checked separately (Section 4.4).¶
A tools entry "*" covers every tool. Any other entry ending in "*" covers every tool whose name starts with the text before the "*"; for example "tool:*" covers "tool:search". Any other entry covers only the identical name.¶
Narrowing compares an entry in Li against the entries at L(i-1) with the same rule, treating the Li entry as a literal string. An ancestor wildcard therefore permits a specific value or a narrower prefix pattern in a descendant ("tool:*" permits "tool:s*"). A specific value in an ancestor MUST NOT widen to a wildcard in a descendant: "tool:search" does not cover "tool:*", because "tool:*" does not start with "tool:search".¶
Domains are matched exactly in this revision. There is no wildcard or suffix matching for domains.¶
Budget values in AIP tokens represent per-chain authorization ceilings, not running balances. A delegator asserts "I authorize up to this amount for this task" at delegation time.¶
A budget ceiling is both declared and verified, and the two are distinct operations:¶
What the token does not do is track cumulative spending. Nothing in a delegation chain records how much of a ceiling has been consumed, and a verifier evaluating a single request cannot know. Enforcement of actual spend against a ceiling is out of band, and is the responsibility of the orchestration platform at dispatch time.¶
Implementations MUST NOT present ceiling verification as spend enforcement. A chain that verifies establishes that no hop authorized more than it held. It does not establish that the authorized amount remains available.¶
This section is normative. A verifier presented with an AIP token MUST perform steps V1 through V7 before treating any identity or capability asserted by the token as established. V1 MUST complete before any other step reads link content. The remaining steps MAY be performed in any order or interleaved, and when a chain fails more than one step, which of the applicable error codes is returned is not specified.¶
A request that carries no token fails with
aip_token_missing. A token that cannot be parsed in its
encoding, or whose links do not have the fields required by
Section 3.1, fails with aip_token_malformed.¶
The verifier MUST verify the signature on every link, as defined by the encoding (Section 5.1.3 and Section 5.2.3), starting from the root public key. Verifying the signature on the presented leaf alone is not sufficient.¶
Verification MUST be performed against the serialized form as received. An implementation that holds a token in a parsed in-memory representation MUST re-serialize and re-verify before relying on it, rather than trusting the state of its own parsed object.¶
A verifier MUST NOT accept any field from a link that it has not
verified as part of a chain rooted at the issuer's key. Failure
returns aip_signature_invalid.¶
The verifier MUST take the issuer of L0 and confirm that the root public key used in V1 is the key bound to that identifier:¶
aip:web: identifiers, by resolving the identity
document as specified in Section 2.3 and
comparing the published key.¶
aip:key: identifiers, by decoding the key from the
identifier itself and comparing.¶
An identifier that does not resolve, or that resolves to a
different key, returns aip_identity_unresolvable. A verifier
MUST NOT infer the root key from the token.¶
V2 establishes which key speaks for the issuer. It does not
establish that the issuer is entitled to grant authority over the
relying party's resources: anyone can create an aip:key:
identifier and sign a chain under it. A relying party MUST accept
chains only from issuers it has chosen, by its own policy, to trust
as sources of authority for the resource, and MUST reject chains
from any other issuer. When the relying party holds a fixed set of
trusted issuer keys this is detected in V1 and returns
aip_signature_invalid; otherwise it returns
aip_identity_unresolvable.¶
The verifier MUST confirm that L0 declares a max_depth of 0 or
more and that N, the number of delegation links, does not exceed it.
A missing max_depth returns aip_token_malformed. N greater
than max_depth returns aip_depth_exceeded.¶
The verifier MUST confirm that L0 declares tools and expiry, that
no tools or domains list in any link is empty, and that no
delegation link declares max_depth. Failure returns
aip_token_malformed.¶
The verifier MUST then check L0 and walk the chain from L1 to LN, comparing each declared value with the effective value of the parent link (Section 3.2):¶
aip_scope_insufficient.¶
aip_scope_insufficient.¶
aip_budget_exceeded.¶
aip_token_expired.¶
aip_token_malformed.¶
This step is REQUIRED and is not satisfied by the container format. Signature chaining establishes that links were appended in order by successive keyholders. It prevents a link from being substituted, reordered, or forged, but it does not establish that the capabilities asserted in Li are a subset of those held at L(i-1). V4 is a comparison of declared values and MUST NOT be replaced by evaluation of the token's policy language.¶
Every delegation link MUST carry a context that is non-empty and
not only whitespace. A verifier MUST reject a chain in which any
delegation link omits it or supplies an empty value, returning
aip_token_malformed.¶
V6 decides whether the specific request falls within the authority at the leaf. It has a structural part, which applies to both encodings, and a policy part, which applies to the Biscuit encoding only.¶
Structural part: the requested tool MUST be covered by the
effective tools at LN. If the request names a domain and the
effective domains at LN is defined, the domain MUST be a member of
it. A request that names no domain is not constrained by the
domains dimension; a relying party that needs domain enforcement
MUST supply the domain of every request. Failure returns
aip_scope_insufficient.¶
Policy part (Biscuit encoding): the verifier MUST evaluate the
token's Datalog with the ambient facts tool,
time, and depth bound to the request under
consideration, and MUST require that every check in every block
passes. The verifier MUST NOT introduce ambient facts beyond those
named. In particular it MUST NOT supply a budget fact:
doing so causes any budget check in the chain to evaluate against
verifier-chosen data rather than against the token. Budget is
handled in V4. Failure returns aip_scope_insufficient.¶
Some requests name no tool, for example an MCP
initialize or tools/list. For those, a verifier
MUST still perform V1 through V5 and V7, and skips V6.¶
If the issuer's identity document advertises a revocation endpoint,
the verifier MUST check whether any key in the chain has been revoked.
Revocation data MAY be cached. A verifier MUST be configurable with a
maximum acceptable staleness for cached revocation data, and MUST fail
closed when its cached data is older than that bound, returning
aip_key_revoked rather than proceeding on stale information.¶
Revocation responses MUST be signed by the issuer so that their authenticity is verifiable without a trusted transport to the revocation endpoint.¶
This revision does not specify the format of the revocation endpoint, its responses, how revoked keys are identified, or how freshness is represented, so V7 cannot yet be implemented interoperably. No known implementation performs it (Section 11).¶
A token that passes V1 through V7 establishes: the identity of the issuer, the capabilities available at the leaf, and that no hop in the chain exceeded the authority of its predecessor.¶
Whether it also establishes the identity of each delegator and
delegate depends on the encoding. In the JWT chain encoding each
delegation link is signed by the key that the previous link named
in cnf, so the chain of keys is authenticated. The pairing
of that key with the identifier in sub is asserted by the
signer of the previous link. Delegator and delegate identity are
therefore established only if the verifier also confirms, for each
link, that the cnf key is bound to the sub
identifier, by decoding an aip:key: identifier or by
resolving the identity document of an aip:web:
identifier. A verifier that relies on delegator identity MUST
perform that check. In the Biscuit encoding delegation blocks are
appended under keys the token itself supplies, so delegator and
delegate are asserted by whoever appended the block, not
authenticated (Section 5.2.4).¶
In neither encoding does verification establish that the presenting party is the party the leaf was issued to. See Section 8 and Section 12.2.¶
This section defines two encodings of the model in Section 3. Both carry the same fields and are verified by the same steps V2 through V7. They differ in V1, in resistance to truncation (Section 12.2), and in what they say about delegators: the JWT chain encoding authenticates the chain of holder keys, and delegator identity additionally requires the key-to-identifier check of Section 4.8; the Biscuit encoding authenticates neither.¶
A JWT chain is the links in order, each a JWS Compact Serialization [RFC7515] of a JWT [RFC7519], joined by the tilde character:¶
<link0>~<link1>~...~<linkN>¶
The tilde separator follows SD-JWT [RFC9901].
No link may be empty. The media type is
application/aip-chain+jwt
(Section 14.3).¶
The protected header of every link MUST contain
alg "EdDSA" and typ "aip-link+jwt":¶
{"alg":"EdDSA","typ":"aip-link+jwt"}
¶
Other header parameters are ignored, except that a
crit parameter naming an extension the verifier does not
understand causes rejection with aip_token_malformed
(Section 4.1.11 of [RFC7515]).¶
The signature algorithm is Ed25519 [RFC8032].
Keys in the cnf claim are OKP JSON Web Keys
[RFC8037] carried as confirmation keys
[RFC7800].¶
The authority link L0 carries:¶
iss (REQUIRED): the issuer.¶
sub (REQUIRED): the delegate, the first holder.¶
iat (REQUIRED): issue time.¶
exp (REQUIRED): the expiry.¶
jti (REQUIRED): a unique link identifier.¶
aip_tools (REQUIRED): a non-empty JSON array of
strings.¶
aip_domains (OPTIONAL): a non-empty JSON array of
strings.¶
aip_budget_cents (OPTIONAL): a non-negative
integer.¶
aip_max_depth (REQUIRED): an integer of 0 or
more.¶
aip_principal (OPTIONAL): a string.¶
cnf (REQUIRED): {"jwk": <key>}, the
holder key of sub.¶
aip_anchor (OPTIONAL): see
Section 5.1.5.¶
A delegation link Li carries:¶
iss (REQUIRED): MUST equal the sub of
L(i-1).¶
sub (REQUIRED): the delegate.¶
iat and jti (REQUIRED).¶
exp (OPTIONAL): if absent, the link inherits.¶
prev (REQUIRED): the base64url encoding, without
padding, of the SHA-256 digest of the ASCII JWS Compact
Serialization of L(i-1) exactly as transmitted.¶
aip_ctx (REQUIRED): the context, a non-empty
string.¶
cnf (REQUIRED): the holder key of sub.¶
aip_tools, aip_domains,
aip_budget_cents, aip_principal
(OPTIONAL), as in L0.¶
A delegation link MUST NOT carry aip_max_depth.¶
The cnf key MUST be an OKP key with crv
"Ed25519" whose x member decodes to 32 bytes.
x MUST be base64url without padding, using only the
URL-safe alphabet of Section 5 of [RFC4648], and
verifiers MUST reject any other character. A cnf that
does not meet these rules returns aip_token_malformed.¶
Claim names other than the registered JWT claims are prefixed
with aip_ so that they do not collide with registered
claims of different syntax, such as the space-delimited
scope string of [RFC9068]. The
iat and jti claims are for audit and
correlation; this document defines no verifier processing for
them.¶
Given a chain and the root public key, a verifier:¶
aip_token_malformed.¶
alg equal to "EdDSA" and typ equal to
"aip-link+jwt". Any other value, including alg "none",
returns aip_signature_invalid.¶
prev equals
the digest of L(i-1) as received, that iss equals the
sub of L(i-1), and verifies the signature on Li with
the key in the cnf of L(i-1). Any mismatch returns
aip_signature_invalid.¶
The root public key is a 32-byte Ed25519 key, obtained as in
V2. Expiry is not checked in V1; it is checked in V4 so that
every expiry failure returns aip_token_expired.¶
A chain with N equal to 0 is a single JWT. It replaces the compact mode of draft-prakash-aip-01, which is no longer a separate format.¶
For this revision only, verifiers MAY accept a single token
with header typ "aip+jwt" and the draft-01 claims
(scope, budget_usd, max_depth) as a
one-link chain. A verifier that does so maps scope to
tools, budget_usd to budget_ceiling in cents, and
max_depth to max_depth, and then applies V2 through V7.
Such a token has no cnf, so it is a bearer credential
and cannot be used to prove possession. This form is deprecated
and is expected to be removed in a later revision.¶
L0 MAY carry an aip_anchor claim that binds the chain
to an OAuth access token or transaction token issued within an
AIMS deployment (Section 7). Its value is
a JSON object with an alg member, which MUST be "S256",
and exactly one of access_token or txn_token,
whose value is the base64url encoding, without padding, of the
SHA-256 digest of the anchored token as transmitted.¶
The anchor conveys assurance only to a relying party that holds the anchored token and checks the digest. This document does not require verifiers to check it, and a chain whose anchor is not checked is verified exactly as one without an anchor.¶
The Biscuit encoding uses Biscuit tokens [BISCUIT] with append-only blocks and Datalog policy. Block 0 is L0 and is signed by the root key. Block i is Li.¶
Three policy profiles of increasing expressiveness are defined:¶
Checks added under the Standard and Advanced profiles are evaluated in the policy part of V6. They do not change the structural fields of Section 3.1, which are always read from the canonical forms.¶
Interoperability of the Biscuit encoding depends on every implementation emitting the same Datalog for the same authorization intent. Implementations MUST emit exactly the forms below. The order of facts and checks within a block is not significant.¶
The authority block (block 0) MUST contain:¶
identity("<aip-identifier>");
principal("<identifier>"); ; OPTIONAL, on-behalf-of party
right("<tool>"); ; one fact per tools entry
domain("<domain>"); ; OPTIONAL, one fact per domain
max_depth(<n>);
budget_ceiling(<cents>); ; OPTIONAL, integer cents
check if <tool-constraint>;
check if time($t), $t <= <expiry>;
¶
Each delegation block (blocks 1 through N) MUST contain:¶
delegator("<aip-identifier>");
delegate("<aip-identifier>");
context("<non-empty string>");
domain("<domain>"); ; OPTIONAL, one fact per domain
principal("<identifier>"); ; OPTIONAL
budget_ceiling(<cents>); ; OPTIONAL, integer cents
check if <tool-constraint>; ; OPTIONAL, absent = inherit
check if time($t), $t <= <expiry>; ; OPTIONAL, absent = inherit
¶
The <tool-constraint> is a single check built
from the block's tools list. Exact names form one clause
tool($t), ["<name>", ...].contains($t). Each entry
"<prefix>*" forms a clause
tool($t), $t.starts_with("<prefix>"), and the
entry "*" forms the clause tool($t). The clauses are
joined with or. <expiry> is a UTC
timestamp of the form YYYY-MM-DDTHH:MM:SSZ.¶
Mapping to the model: issuer is the identity fact in
block 0 and the delegator fact in later blocks; delegate
is the delegate fact; tools are read from the tool check,
not from the right facts, which are descriptive; domains
are the domain facts; expiry is read from the time check;
the remaining fields are the facts of the same name.¶
Block 0 MUST carry an identity fact, and every
delegation block MUST carry a delegator and a
delegate fact. Verifiers MUST reject a block missing one
of them with aip_token_malformed.¶
A block MUST NOT carry more than one fact of any of the names
identity, principal, context,
delegator, delegate, budget_ceiling,
and max_depth. Verifiers MUST reject such a block with
aip_token_malformed, because a repeated single-valued
fact makes the block's declared value ambiguous. A delegation
block MUST NOT carry max_depth.¶
Scope narrowing is reinforced by conjunction: every block's tool check must pass, so the set of tools the Datalog authorizes is the intersection of the per-block allowlists. V4 still checks it structurally, so that a widening block is reported as malformed authority rather than silently authorizing nothing.¶
Domains are carried as facts only, never as a Datalog check. A
check over a domain ambient fact would fail every
request that names no domain, and adding domain to the
ambient facts would let the verifier choose the value being
checked. Domain attenuation is verified in V4 and the request's
domain in the structural part of V6.¶
Budget is carried as a fact rather than a check. A Datalog check
of the form check if budget($b), $b <= N binds to
whatever budget facts are in scope during evaluation, which is not
the same question as whether this block's ceiling narrows its
parent's. Encoding budget as a check therefore either rejects
valid chains or, if the verifier supplies a satisfying ambient
fact, passes unconditionally. Implementations MUST NOT emit a
check statement over budget, and verifiers MUST
NOT inject an ambient budget fact.¶
In this encoding an empty allowlist has no representation: a
block with no tool check, or with no domain facts,
inherits. The authority block MUST carry a tool check, and a
verifier MUST reject an authority block without one with
aip_token_malformed.¶
V1 is Biscuit signature verification of every block from the serialized token against the root public key. The verifier then reads the fields of each block as described in Section 5.2.2.¶
Biscuit appends each block under an ephemeral key carried in
the token. The signature chain proves the blocks were appended in
order by successive holders of the token, but it does not prove
that the party named in delegator wrote the block. In
this encoding delegator and delegate are asserted, not
authenticated. The issuer of L0 is authenticated by the root key
and V2.¶
Biscuit third-party blocks, which are signed by a key outside the token, could let a delegator sign its own block, and a future revision MAY specify their use. The reference implementation does not use them.¶
A JWS Compact Serialization starts with the base64url encoding
of a JSON object, so a JWT chain starts with "eyJ". A verifier
receiving a token in a binding that does not label its type
treats a token that starts with "eyJ" as a JWT chain, and a token
that is a single JWS with header typ "aip+jwt" as the
deprecated draft-01 form (Section 5.1.4). Any
other token is parsed as Biscuit. The header is read without
verification only to choose the verifier; nothing in it is trusted
before V1.¶
AIP answers a different question from a workload identity system, and a deployment can use both.¶
A workload identity system such as SPIFFE [SPIFFE], in the architecture described by [I-D.ietf-wimse-arch], answers "which workload is this?" It attests a running process against the platform it runs on and issues a credential that says so. Its trust boundary is the trust domain it administers, and it does not model authority passing between parties.¶
AIP answers "on whose authority is this being done, how far back, and can a party with no relationship to the origin verify it?" It carries delegation across hops and organizations, and it does not by itself establish that the process presenting the token is the one the platform attested.¶
L0 is signed by the issuer's key. Four ways of establishing trust in that key, or in the authority behind it, are defined:¶
aip:web: identifier and
the key is published in an identity document resolved over HTTPS.
Trust derives from the Web PKI and DNS control.¶
aip:key: identifier
and the key is the identifier. Trust derives from whoever accepted
the identifier.¶
aip_anchor claim (Section 5.1.5) binding
the chain to an access token or transaction token. This
supplements one of the other modes; it does not replace V2.¶
In workload-attested mode, an identity document MAY carry a
workload_identity member naming the credential that attests
the issuer key, for example a SPIFFE ID. A verifier that recognises
the naming authority MAY treat that attestation as the basis for
accepting the root key, in place of resolving the document over
HTTPS. A verifier that does not recognise it MUST fall back to the
DNS-anchored or self-certifying path, and MUST NOT treat an
unrecognised attestation as an endorsement.¶
In this deployment a workload identity system establishes that the orchestrator is what it claims to be inside its own trust domain, and AIP carries what that orchestrator was permitted to delegate onward, across boundaries the workload identity system does not span.¶
AIMS [I-D.ietf-wimse-aims] describes how existing standards apply to agent identity and authorization. This section states how AIP is intended to fit alongside it. Section numbers refer to draft-ietf-wimse-aims-00.¶
aip_anchor in the JWT chain encoding or through the
workload-attested anchor in either encoding.¶
Verification establishes what authority a chain conveys and that no hop exceeded its predecessor. It does not establish that the party presenting the chain is the party the leaf was delegated to.¶
In the JWT chain encoding the cnf claim of the leaf link
names the key of the leaf delegate. A presenter can prove possession
of that key at the message layer, for example by signing the request
with HTTP Message Signatures [RFC9421], or with a
WIMSE Workload Proof Token [I-D.ietf-wimse-wpt] where
the leaf key is the key of the presenter's workload credential.
Specifying that binding, including which request components are
signed and how freshness and replay are handled, is out of scope for
this document and is left to those mechanisms. A signed request
without freshness and replay controls can itself be replayed.¶
A relying party that relies on attenuation holding against
downstream holders of a JWT chain MUST verify proof of possession of
the key named in the leaf link's cnf. Without it, a JWT chain
conveys no more assurance than a bearer grant from its root, for the
reason given in Section 12.2.¶
The Biscuit encoding names no holder key and remains a bearer credential. Deployments that need proof of possession with it MUST bind the token to a key at the transport or message layer, for example with mutual TLS or the mechanisms above.¶
Implementations MUST NOT describe AIP verification as authenticating the presenter.¶
The bindings carry either encoding. The verification steps are not restated per binding; every binding applies the algorithm of Section 4 unchanged.¶
AIP tokens are transported in MCP via the X-AIP-Token HTTP header:¶
X-AIP-Token: <jwt-chain-or-biscuit-token>¶
For tokens exceeding 4KB, token-by-reference is supported:¶
X-AIP-Token-Ref: https://issuer/.well-known/aip/tokens/<id>¶
An MCP server extracts the token from the header, or fetches it
from the reference URL, determines the encoding as in
Section 5.3, and verifies it according to
Section 4. For tools/call
the requested tool is the string "tool:" followed by the tool name
in the request, so tools entries for MCP are written in that form
(for example "tool:search" or "tool:*"). On success the
server injects the verified identity into the request context,
where the tool implementation MAY use it for authorization
decisions, logging, or audit.¶
Nine error codes are defined with HTTP status mappings: 401 for
authentication failures (aip_token_missing,
aip_token_malformed, aip_signature_invalid,
aip_identity_unresolvable, aip_token_expired,
aip_key_revoked) and 403 for authorization failures
(aip_scope_insufficient, aip_budget_exceeded,
aip_depth_exceeded).¶
A server MAY apply local policy after verification, for example
a lower depth or budget limit than the chain allows. Failures of
such policy are not part of this specification. The reference
proxy reports them as aip_audit_failed with status
403.¶
Servers declare AIP requirements via the require_aip field in their identity document's protocols.mcp configuration.¶
In A2A interactions, AIP tokens are transported in the metadata.aip_token field of task submissions. Agent cards are extended with an aip_identity object containing the agent's AIP identifier and document URL.¶
The calling agent appends a delegation link with attenuated authority before sending the task. In addition to Section 4, the receiving agent verifies that the chain has at least one delegation link and that the delegate of the leaf link is its own AIP identifier. The receiving agent determines the requested tool for V6 from the task, for example the skill the task asks it to perform.¶
For generic HTTP APIs not using MCP or A2A, tokens are transported via the Authorization header with the AIP scheme:¶
Authorization: AIP <token>¶
The token is sent as is. Both a JWT chain and a Biscuit token in its base64url form consist only of characters permitted in the token68 syntax of Section 11.2 of [RFC9110]. Token-by-reference uses the X-AIP-Token-Ref header with a 5-second fetch timeout and SSRF protection (reject reference URLs outside expected domain patterns).¶
L0 declares max_depth, which is REQUIRED. Each delegation link increments the depth by 1. A holder whose link is at depth equal to max_depth MUST NOT delegate further. A max_depth of 0 means the first holder MUST NOT delegate.¶
Each delegation link MUST include a non-empty context containing a human-readable description of the delegation purpose. Verifiers MUST reject tokens with missing or empty context (V5). This keeps the reason for each hop in the audit record.¶
For short-lived sub-agents, a parent agent generates an Ed25519
keypair, creates an aip:key: identifier, and appends a delegation
link with scoped capabilities and a short TTL (5 minutes
RECOMMENDED). In the JWT chain encoding the new key is the
cnf of that link. The parent's identity document MAY set
delegation.allow_ephemeral_grants to false to prevent this.¶
DNS-based identifiers support zero-downtime key rotation through overlapping validity windows on public keys. A new key is published with a future valid_from timestamp. Both keys are valid during the overlap period. Recommended rotation period is 90 days. Cache TTL MUST NOT exceed 5 minutes.¶
Self-certifying identifiers cannot rotate keys; key rotation requires identity replacement, which is acceptable for ephemeral agents.¶
AIP prefers short-lived tokens over revocation infrastructure. Single-link chains SHOULD have a lifetime under 1 hour, which bounds the window in which a compromised key or captured token can be used; whether that window is acceptable is a deployment decision. Key revocation (removing a key from the identity document) invalidates all chains rooted in that key. Step V7 defines the requirements on revocation checking. Token-specific revocation lists are not specified.¶
Signed records of the outcome of a delegated action, appended by the executing agent, are a possible extension. Draft-01 defined completion blocks for this purpose; they were never implemented and are removed from this revision.¶
[Note to RFC Editor: please remove this section and the reference to RFC 7942 before publication.]¶
This section records the status of known implementations of the protocol defined by this specification at the time of posting of this Internet-Draft, and is based on a proposal described in [RFC7942]. The description of implementations in this section is intended to assist the IETF in its decision processes in progressing drafts to RFCs. Please note that the listing of any individual implementation here does not imply endorsement by the IETF. Furthermore, no effort has been spent to verify the information presented here that was supplied by IETF contributors. This is not intended as, and must not be construed to be, a catalog of available implementations or their features. Readers are advised to note that other implementations may exist.¶
According to RFC 7942, "this will allow reviewers and working groups to assign due consideration to documents that have the benefit of running code, which may serve as evidence of valuable experimentation and feedback that have made the implemented protocols more mature. It is up to the individual working groups to use this information as they see fit".¶
Two implementations are known, both by the author. Neither provides V7 revocation. The author is not aware of independent implementations of this revision.¶
Both encodings on one link model. V1, V3, V4, V5, and both
parts of V6, including domains and the rules for empty
allowlists, repeated single-valued Biscuit facts, and
cnf key syntax, and rejection of Biscuit blocks
missing identity, delegator, or
delegate. MCP middleware, an MCP proxy, and an A2A
verifier that accept either encoding.¶
Draft-01 compact tokens: the library verifier for JWT chains
maps a token with typ "aip+jwt" onto the link model as
in Section 5.1.4. The MCP middleware and
proxy do not use that path; for such tokens they keep draft-01
compact semantics: signature and expiry checks, an exact match
of the requested tool against scope with no wildcards,
and no V3 or V4. The compact verifier rejects any
typ other than "aip+jwt" as malformed. The A2A verifier
does not accept compact tokens.¶
V2: the library takes the root key from its caller and does
not resolve identity documents over HTTPS. Only the MCP proxy
compares the issuer a chain declares with the issuer its key is
configured for, and only when trusted keys are configured as a
mapping from issuer to key; with a single unbound key it skips
the comparison and logs a warning. The MCP middleware and the A2A
verifier take one key and do not compare issuers.
The JWT chain verifier does not check that links carry
iat and jti, which Section 5.1.2
requires of issuers. V7 is not implemented. The workload-attested anchor
mode, the token-by-reference header, and the HTTP
Authorization binding are not implemented.
aip_anchor is carried but not checked. No binding
supplies a request domain, so domain constraints are enforced
in V4 but not against requests. The JWT chain verifier does not
check that each cnf key is bound to its sub
identifier (Section 4.8). The MCP proxy, middleware and A2A
verifier do not verify proof of possession, so JWT chains presented to
them are subject to truncation
(Section 12.2).¶
Identity document signatures are decoded as base64url
(standard base64 is also accepted for documents written by
earlier versions). Canonicalization uses sorted-key compact
JSON, which agrees with JCS for documents whose strings are
ASCII and whose numbers are integers. The document is first
parsed into a fixed model, so members the model does not define
(including workload_identity of
Section 6.1) and members whose value is null
are dropped from the bytes that are verified. The signature is
checked against the first listed key only.¶
At commit 989a4f2, 311 unit and integration tests (python -m pytest in the python directory), including a suite that runs the same forged-delegation cases (tool widening, domain widening, budget increase, principal substitution, missing context) through both encodings and requires the same error code from each.¶
A further 26 cross-language tests between the Python and Rust implementations, in three groups: 4 exchange Biscuit chains with a delegation block between the implementations, two checking acceptance and two checking that a tool removed by delegation is rejected; 2 check that draft-01 compact JWTs minted by either verify in the other; and 20 check that both render the same Datalog for the tool, budget and depth parts of an authority block and that neither emits a forbidden budget or depth check. Eight of those 20 use an empty tools list, which this revision makes malformed. None of them covers the JWT chain encoding or domains.¶
principal fact. It decodes identity document signatures
as hex, which does not match Section 2.3.
V7 is not implemented.¶
AIP is designed to resist the following attack categories:¶
prev.¶
Signature chaining and attenuation checking are different properties. Signature chaining (V1) prevents links from being forged, reordered, or substituted. Attenuation checking (V4) prevents a link from asserting more than its predecessor held. The first is a property of the container; the second is a property of the capability content. Neither implies the other, and a verifier that performs only the first will accept a chain in which a delegation widened its own authority. Both are REQUIRED.¶
Any prefix L0 through Lk of a valid JWT chain is itself a valid chain. It carries the authority held by the delegate of Lk, which is wider than or equal to the authority at the leaf. A holder of a longer chain can therefore remove its own and later links and present the prefix. Signature verification and V4 will both succeed.¶
Proof of possession closes this: the prefix names the key of an
earlier holder in its leaf cnf, which the truncating
party does not hold. A relying party that relies on attenuation
holding against downstream holders MUST verify proof of possession
of the key named in the leaf link's cnf, as stated in
Section 8. Without it, a JWT chain
conveys no more assurance than a bearer grant from its root.¶
The Biscuit encoding resists truncation, because the token carries only the private key for its last block, and presenting a shorter chain requires the key for an earlier block, which a downstream holder does not have. It remains a bearer credential in every other respect.¶
In the JWT chain encoding a delegation link can only be produced
by the holder of the key the previous link named, so the chain of
keys is authenticated. The identifier paired with each key is the
previous signer's assertion until the verifier checks the binding
(Section 4.8). Without that check, a delegator can
name another party's identifier in sub next to its own key
in cnf and sign the next link under that name. In the
Biscuit encoding any holder can append a block naming any
delegator. Relying parties and
auditors MUST NOT treat a Biscuit delegator fact as
evidence that the named party delegated.¶
Two implementations that accept each other's tokens can both be wrong in the same way. During the development of draft-01, the Python and Rust implementations passed their cross-language tests while both failed to perform checks this document requires. Implementers should test against the MUST statements of this document, including negative cases, and not only against another implementation.¶
The companion paper [AIP-PAPER] reports an evaluation of an earlier version of the reference implementation against six attack categories. That evaluation predates this revision and the JWT chain encoding, and is not evidence about either.¶
This revision mandates Ed25519 exclusively, and the JWT chain
encoding pins the alg header. No algorithm negotiation is
supported. This is a deliberate choice to eliminate downgrade
attacks and reduce implementation complexity. Future revisions MAY
introduce additional algorithms through a new typ value
or the protocol version field.¶
Identity document resolution and token-by-reference fetching MUST use HTTPS. Implementations SHOULD enforce TLS 1.3 or later. Token-by-reference URLs MUST be validated against expected domain patterns to prevent SSRF attacks. Fetch timeout SHOULD be 5 seconds.¶
Every holder of a chain, and every relying party it is presented to, can read all of its links. The context of each delegation link, the principal, the identifiers of every participant, and the tools and domains granted are therefore disclosed downstream. Delegators SHOULD keep context to what an auditor needs to understand the purpose of the hop and SHOULD NOT put personal data in it. Relying parties that log verified chains SHOULD apply the retention and access controls they apply to other authorization records.¶
This document requests the following IANA registrations:¶
Registration of the "AIP" HTTP authentication scheme in the "HTTP Authentication Schemes" registry:¶
Registration of the "aip" well-known URI suffix in the "Well-Known URIs" registry:¶
Registration of the following media types in the "Media Types" registry, using the template of [RFC6838]. The following fields are the same for each:¶
The subtypes are:¶
typ header value "aip-link+jwt" is this media type
with the "application/" prefix omitted, as described in
Section 4.1.9 of [RFC7515].¶
typ value remains defined.¶
Registration of the following claims in the "JSON Web Token Claims" registry established by [RFC7519]. For all of them the Change Controller is IETF and the Specification Document is Section 5.1.2 of this document.¶
| Claim Name | Claim Description |
|---|---|
| prev | Digest of the previous link in an AIP JWT chain |
| aip_tools | AIP tools allowlist |
| aip_domains | AIP domains allowlist |
| aip_budget_cents | AIP budget ceiling in cents |
| aip_max_depth | AIP maximum delegation depth |
| aip_principal | AIP on-behalf-of principal |
| aip_ctx | AIP delegation context |
| aip_anchor | Digest of an anchoring OAuth token |
[I-D.reece-wimse-cross-org-delegation] enumerates requirements for delegation between organizations that share no operator, no runtime, and no bilateral agreement. Its -02 revision lists ten (R1 through R10); draft-01 of this document mapped the nine of its -00 revision. This appendix maps AIP against them. Each verdict was checked against the implementations described in Section 11, and a verdict distinguishes what this document specifies from what is implemented.¶
Other proposals address overlapping parts of the same problem, including [I-D.rampalli-pedigree]. The requirements themselves, rather than any one mechanism, are the useful common ground, and several of the gaps identified below are shared across proposals.¶
aip:web: issuer publishes its key at a location
derived from its own DNS name, and a relying party resolves it over
HTTPS with no prior arrangement. An aip:key: issuer needs
no resolution at all. Neither requires a federation relationship
established in advance of the interaction. The reference
implementations take issuer keys from configuration rather than
resolving documents.¶
cnf names the key a
presenter must prove, and the proof is delegated to HTTP Message
Signatures or a WIMSE Workload Proof Token
(Section 8). This document does not
define a profile of either, and the reference MCP proxy and
middleware do not verify proof of possession. The Biscuit encoding is a
bearer credential.¶
Summarising the gaps: AIP does not by itself prove possession (R4), and in the JWT chain encoding attenuation (R1) and audit completeness (R8) depend on that proof. It does not evaluate principal entitlements (R6), provide implemented revocation (R7), authenticate delegators in the Biscuit encoding or without the key-to-identifier check in the JWT chain encoding (R8), or carry human approval evidence (R10).¶
aip_domains in the JWT chain
encoding and domain facts in the Biscuit encoding.¶
aip_ prefix
throughout, and every expiry failure returns
aip_token_expired.¶
cnf. Added security considerations on
truncation, encoding-dependent identity guarantees, Datalog
encoding, and conformance testing.¶
The Biscuit authorization token specification influenced the Biscuit encoding. The MCP and A2A protocol teams provided the agent communication infrastructure that AIP extends.¶