<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     ipr="trust200902"
     docName="draft-prakash-aip-01"
     category="info"
     submissionType="independent"
     xml:lang="en"
     version="3">

  <front>
    <title abbrev="AIP">Agent Identity Protocol (AIP): Verifiable Delegation for AI Agent Systems</title>

    <seriesInfo name="Internet-Draft" value="draft-prakash-aip-01"/>

    <author initials="S." surname="Prakash" fullname="Sunil Prakash">
      <organization>Independent</organization>
      <address>
        <email>sunil@sunilprakash.com</email>
        <uri>https://sunilprakash.com</uri>
      </address>
    </author>

    <date year="2026" month="August" day="19"/>

    <area>Security</area>
    <workgroup>Individual Submission</workgroup>

    <keyword>AI agents</keyword>
    <keyword>authentication</keyword>
    <keyword>delegation</keyword>
    <keyword>capability tokens</keyword>
    <keyword>MCP</keyword>
    <keyword>A2A</keyword>
    <keyword>SPIFFE</keyword>
    <keyword>workload identity</keyword>

    <abstract>
      <t>This document specifies the Agent Identity Protocol (AIP), a protocol
      for verifiable, delegable identity for AI agent systems. AIP introduces
      Invocation-Bound Capability Tokens (IBCTs) that bind identity,
      authorization, scope constraints, and provenance into a single
      cryptographic artifact. Two token modes are defined: a compact mode
      using JSON Web Tokens (JWT) with Ed25519 signatures for single-hop
      interactions, and a chained mode using Biscuit tokens with append-only
      blocks and Datalog policy evaluation for multi-hop delegation chains.
      Protocol bindings are specified for the Model Context Protocol (MCP),
      Agent-to-Agent Protocol (A2A), and generic HTTP APIs. The protocol
      addresses authentication gaps in current AI agent infrastructure where
      a survey of approximately 2,000 MCP servers found all lacked
      authentication. This revision specifies a normative verification
      algorithm, defines the canonical policy encoding for chained mode,
      describes how AIP composes with workload identity systems such as
      SPIFFE, and maps AIP against the cross-organization delegation
      requirements enumerated in
      <xref target="I-D.reece-wimse-cross-org-delegation"/>.</t>
    </abstract>
  </front>

  <middle>
    <section anchor="introduction">
      <name>Introduction</name>

      <t>AI agent systems are increasingly deployed in multi-agent
      architectures where an orchestrator decomposes tasks and delegates
      subtasks to specialist agents. The protocols enabling this
      communication, notably the Model Context Protocol (MCP) and the
      Agent-to-Agent Protocol (A2A), solve the connectivity problem but
      do not solve the identity problem.</t>

      <t>MCP provides no built-in authentication layer. A2A uses
      self-declared identities with no attestation mechanism. OAuth 2.1,
      recently added to MCP, covers single-hop client-to-server
      authentication but does not address multi-hop delegation chains.
      When an orchestrator delegates to a specialist that calls a tool,
      the delegation chain that led to the tool invocation is lost.</t>

      <t>AIP fills this gap by introducing Invocation-Bound Capability
      Tokens (IBCTs) that answer four questions for every agent action:
      who authorized this action, through which delegation chain, with
      what constraints at each hop, and what was the outcome.</t>

      <section anchor="requirements-language">
        <name>Requirements Language</name>
        <t>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 <xref target="RFC2119"/>
        <xref target="RFC8174"/> when, and only when, they appear in
        all capitals, as shown here.</t>
      </section>
    </section>

    <section anchor="identity-scheme">
      <name>Identity Scheme</name>

      <t>AIP defines two identifier schemes for agent identity:</t>

      <section anchor="dns-based">
        <name>DNS-Based Identifiers</name>
        <t>DNS-based identifiers follow the format:</t>
        <artwork><![CDATA[
aip:web:<domain>/<path>
        ]]></artwork>
        <t>Example: aip:web:example.com/agents/research-analyst</t>
        <t>DNS-based identifiers are suitable for long-lived agents with
        stable domain ownership. Identity documents are resolved via HTTPS
        at a well-known path.</t>
      </section>

      <section anchor="self-certifying">
        <name>Self-Certifying Identifiers</name>
        <artwork><![CDATA[
aip:key:ed25519:<multibase-encoded-public-key>
        ]]></artwork>
        <t>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 deterministically computed
        from the Ed25519 public key using multibase encoding.</t>
      </section>

      <section anchor="identity-document">
        <name>Identity Document</name>
        <t>Each agent with a DNS-based identifier MUST publish an identity
        document at:</t>
        <artwork><![CDATA[
https://<domain>/.well-known/aip/<path>.json
        ]]></artwork>
        <t>The identity document is a JSON object containing:</t>
        <ul>
          <li><tt>aip</tt>: Protocol version (MUST be "1.0")</li>
          <li><tt>id</tt>: The agent's AIP identifier</li>
          <li><tt>public_keys</tt>: Array of public key objects with validity windows</li>
          <li><tt>name</tt>: Human-readable agent name</li>
          <li><tt>delegation</tt>: Delegation preferences</li>
          <li><tt>protocols</tt>: Supported protocol bindings</li>
          <li><tt>document_signature</tt>: Ed25519 signature over the canonicalized document</li>
          <li><tt>expires</tt>: Document expiration timestamp</li>
        </ul>
        <t>The document MUST be self-signed. Verification uses
        JSON Canonicalization Scheme (JCS) <xref target="RFC8785"/>:
        remove the document_signature
        field, canonicalize the remaining JSON, and verify the Ed25519
        signature against a currently-valid public key.</t>
      </section>
    </section>

    <section anchor="token-formats">
      <name>Token Formats</name>

      <t>AIP defines two token modes that share a common identity scheme
      but differ in delegation capability.</t>

      <section anchor="compact-mode">
        <name>Compact Mode (JWT)</name>
        <t>Compact mode tokens are JSON Web Tokens <xref target="RFC7519"/>
        signed with Ed25519 (EdDSA). They support single-hop interactions
        only.</t>
        <t>Header:</t>
        <artwork><![CDATA[
{"alg": "EdDSA", "typ": "aip+jwt"}
        ]]></artwork>
        <t>Claims:</t>
        <ul>
          <li><tt>iss</tt>: Issuer AIP identifier (REQUIRED)</li>
          <li><tt>sub</tt>: Subject/holder AIP identifier (REQUIRED)</li>
          <li><tt>scope</tt>: Array of authorized capabilities (REQUIRED)</li>
          <li><tt>budget_usd</tt>: Authorization budget ceiling in USD (REQUIRED)</li>
          <li><tt>max_depth</tt>: Maximum delegation depth, 0 for no further delegation (REQUIRED)</li>
          <li><tt>iat</tt>: Issued-at timestamp (REQUIRED)</li>
          <li><tt>exp</tt>: Expiration timestamp (REQUIRED)</li>
        </ul>
        <t>Token lifetime SHOULD be less than one hour. Both iss and sub
        MUST be valid AIP identifiers.</t>
      </section>

      <section anchor="chained-mode">
        <name>Chained Mode (Biscuit)</name>
        <t>Chained mode tokens use Biscuit <xref target="BISCUIT"/>
        tokens with append-only blocks and Datalog policy evaluation. They support multi-hop delegation
        with cryptographic scope attenuation.</t>
        <t>A chained token consists of ordered blocks:</t>
        <ul>
          <li>Block 0 (Authority): Root identity, initial capabilities,
          budget, max_depth, expiration. Signed by the root authority.</li>
          <li>Blocks 1..N-1 (Delegation): Each block narrows scope. Contains
          delegator, delegate, attenuated capabilities (as Biscuit right facts),
          attenuated budget, and a non-empty context field. Signed by the
          delegator.</li>
          <li>Block N (Completion, optional): Execution outcome. Contains
          status, result_hash (SHA-256), verification_status, and optional
          resource usage metrics. Signed by the executing agent.</li>
        </ul>
      </section>

      <section anchor="scope-attenuation">
        <name>Scope Attenuation</name>
        <t>Scope attenuation is a fundamental security property of AIP. At
        each delegation step, scope can only narrow or remain equal, never
        widen. This applies across four dimensions:</t>
        <ul>
          <li>Tools: Child scope MUST be a subset of parent scope</li>
          <li>Budget: Child budget MUST be less than or equal to parent budget</li>
          <li>Domains: Child domains MUST be a subset of parent domains</li>
          <li>Time: Child expiration MUST be less than or equal to parent expiration</li>
        </ul>
        <t>Verifiers MUST check attenuation at every hop in the delegation
        chain. A wildcard (*) in the parent permits any specific value in
        the child, but a specific value in the parent MUST NOT widen to a
        wildcard in the child.</t>
      </section>

      <section anchor="policy-profiles">
        <name>Policy Profiles</name>
        <t>Chained mode tokens support three policy profiles of increasing
        expressiveness:</t>
        <ul>
          <li>Simple: Templated rules requiring no Datalog knowledge. The
          library generates canonical Datalog for tool allowlists, budget
          ceilings, delegation depth, and time expiry.</li>
          <li>Standard: Curated Datalog subset without recursion and with
          bounded evaluation.</li>
          <li>Advanced: Full Datalog with a maximum 1000 iteration limit.
          Opt-in only.</li>
        </ul>

        <section anchor="canonical-encoding">
          <name>Canonical Block Encoding</name>
          <t>Interoperability of chained mode depends on every implementation
          emitting the same Datalog for the same authorization intent. Two
          encodings that are individually defensible will not verify against
          each other. Implementations of the Simple profile MUST emit exactly
          the forms below.</t>

          <t>The authority block (block 0) MUST contain:</t>
          <sourcecode type="datalog"><![CDATA[
identity("<aip-identifier>");
principal("<identifier>");          ; OPTIONAL, on-behalf-of party
right("<scope>");                   ; one fact per granted scope
max_depth(<n>);
budget_ceiling(<cents>);            ; OPTIONAL, integer cents
check if tool($t), ["<scope>", ...].contains($t);
check if time($t), $t <= <expiry>;
]]></sourcecode>

          <t>Each delegation block (blocks 1 through N) MUST contain:</t>
          <sourcecode type="datalog"><![CDATA[
delegator("<aip-identifier>");
delegate("<aip-identifier>");
context("<non-empty string>");
budget_ceiling(<cents>);            ; OPTIONAL, integer cents
check if tool($t), ["<scope>", ...].contains($t);
check if time($t), $t <= <expiry>;  ; OPTIONAL, <= parent expiry
]]></sourcecode>

          <t>Scope narrowing follows from conjunction: because every block
          contributes a <tt>check if tool($t)</tt> constraint and all checks in
          all blocks MUST pass, the set of authorized tools is the intersection
          of the per-block allowlists. A delegation block cannot widen scope,
          because naming a tool absent from an ancestor's allowlist produces an
          empty intersection and authorizes nothing.</t>

          <t>Budget is carried as a fact rather than a check. A Datalog check of
          the form <tt>check if budget($b), $b &lt;= N</tt> 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. Budget attenuation is verified structurally instead,
          in step V4 of <xref target="verification-algorithm"/>.</t>

          <t>Implementations MUST NOT emit a <tt>check</tt> statement over
          <tt>budget</tt>, and verifiers MUST NOT inject an ambient
          <tt>budget</tt> fact during policy evaluation.</t>
        </section>
      </section>

      <section anchor="budget-semantics">
        <name>Budget Semantics</name>
        <t>Budget values in AIP tokens represent per-token authorization
        ceilings, NOT running balances. A delegator asserts "I authorize up
        to $X for this task" at delegation time.</t>

        <t>A budget ceiling is both declared and verified, and the two are
        distinct operations:</t>
        <ul>
          <li>Declared as a <tt>budget_ceiling</tt> fact in the block that
          establishes it, in integer cents.</li>
          <li>Verified structurally at every hop: a verifier MUST confirm that
          each block's declared ceiling is non-negative and does not exceed the
          nearest ancestor block that declares one. A block that declares no
          ceiling inherits its nearest ancestor's. This check is specified in
          step V4 of <xref target="verification-algorithm"/>.</li>
        </ul>

        <t>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.
        Completion blocks record actual cost_usd for audit purposes, which
        supports after-the-fact reconciliation but is not an authorization
        control.</t>

        <t>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.</t>
      </section>
    </section>

    <section anchor="verification-algorithm">
      <name>Verification Algorithm</name>
      <t>This section is normative. A verifier presented with an AIP token
      MUST perform steps V1 through V7 in the order given before treating any
      identity or capability asserted by the token as established. The
      ordering matters: no step that reads block content is permitted before
      chain integrity is established in V1.</t>

      <section anchor="v1-chain-integrity">
        <name>Step V1: Chain Integrity</name>
        <t>The verifier MUST deserialize the token from its wire form and
        verify the signature on every block against the root public key. In
        chained mode this means verifying the full signature chain from block
        0 through block N, not the signature on the presented leaf alone.</t>
        <t>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.</t>
        <t>A verifier MUST NOT accept any fact, check, or claim from a block
        that it has not verified as part of a chain rooted at the issuer's
        key. Failure returns <tt>aip_signature_invalid</tt>.</t>
      </section>

      <section anchor="v2-root-binding">
        <name>Step V2: Root Binding</name>
        <t>The verifier MUST extract the issuer from the <tt>identity</tt>
        fact in block 0 and confirm that the root public key used in V1 is the
        key bound to that identifier:</t>
        <ul>
          <li>For <tt>aip:web:</tt> identifiers, by resolving the identity
          document as specified in <xref target="identity-document"/> and
          comparing the published key.</li>
          <li>For <tt>aip:key:</tt> identifiers, by decoding the key from the
          identifier itself and comparing.</li>
        </ul>
        <t>An identifier that does not resolve, or that resolves to a
        different key, returns <tt>aip_identity_unresolvable</tt>. A verifier
        MUST NOT infer the root key from the token.</t>
      </section>

      <section anchor="v3-depth">
        <name>Step V3: Depth</name>
        <t>The verifier MUST confirm that the number of delegation blocks does
        not exceed the <tt>max_depth</tt> declared in block 0. Failure returns
        <tt>aip_depth_exceeded</tt>.</t>
      </section>

      <section anchor="v4-attenuation-walk">
        <name>Step V4: Structural Attenuation Walk</name>
        <t>The verifier MUST walk the chain from block 1 to block N and
        confirm, for each block i, that every capability dimension is narrower
        than or equal to the corresponding dimension in block i-1:</t>
        <ul>
          <li>Scope: the allowlist in block i MUST be a subset of the
          allowlist in block i-1. Failure returns
          <tt>aip_scope_insufficient</tt>.</li>
          <li>Budget: a <tt>budget_ceiling</tt> declared in block i MUST be
          non-negative and MUST NOT exceed the ceiling declared by the nearest
          ancestor that declares one. Failure returns
          <tt>aip_budget_exceeded</tt>.</li>
          <li>Time: an expiry declared in block i MUST NOT be later than the
          expiry declared by the nearest ancestor that declares one, and no
          block's expiry may be in the past. Failure returns
          <tt>aip_token_expired</tt>.</li>
          <li>Domains: the domain set in block i MUST be a subset of the
          domain set in block i-1. Failure returns
          <tt>aip_scope_insufficient</tt>.</li>
          <li>Principal: if block 0 declares a <tt>principal</tt>, no
          subsequent block may declare a different one. The on-behalf-of
          principal is invariant along a chain: intermediaries narrow
          authority, they do not substitute the party on whose behalf the
          chain acts. Failure returns <tt>aip_token_malformed</tt>.</li>
        </ul>
        <t>A dimension absent from block i inherits the value of its nearest
        ancestor. A wildcard in an ancestor permits any specific value in a
        descendant. A specific value in an ancestor MUST NOT widen to a
        wildcard in a descendant.</t>

        <t>This step is REQUIRED and is not satisfied by the container format.
        A verifier MUST NOT rely on the semantics of an append-only token
        container to establish attenuation. Container-level signature chaining
        establishes that blocks were appended in order by successive
        keyholders, which is a different property: it prevents a block from
        being substituted, reordered, or forged, but it does not establish
        that the capabilities asserted in block i are a subset of those held
        by block i-1. Attenuation is a property of the capability content and
        MUST be checked as such, in addition to V1.</t>
      </section>

      <section anchor="v5-context">
        <name>Step V5: Delegation Context</name>
        <t>Every delegation block MUST carry a non-empty <tt>context</tt>
        fact. A verifier MUST reject a chain in which any delegation block
        omits it or supplies an empty value, returning
        <tt>aip_token_malformed</tt>.</t>
      </section>

      <section anchor="v6-policy">
        <name>Step V6: Policy Evaluation</name>
        <t>The verifier MUST evaluate the token's policies with the ambient
        facts <tt>tool</tt>, <tt>time</tt>, and <tt>depth</tt> bound to the
        request under consideration, and MUST require that every check in
        every block passes.</t>
        <t>The verifier MUST NOT introduce ambient facts beyond those named
        above. In particular it MUST NOT supply a <tt>budget</tt> fact:
        supplying one causes any budget check in the chain to evaluate against
        verifier-chosen data rather than against the token, which makes the
        check meaningless. Budget is handled in V4.</t>
        <t>Failure returns <tt>aip_scope_insufficient</tt>.</t>
      </section>

      <section anchor="v7-revocation">
        <name>Step V7: Revocation with Bounded Staleness</name>
        <t>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
        <tt>aip_key_revoked</tt> rather than proceeding on stale information.</t>
        <t>Revocation responses MUST be signed by the issuer so that their
        authenticity is verifiable without a trusted transport to the
        revocation endpoint.</t>
      </section>

      <section anchor="v8-result">
        <name>Verification Result</name>
        <t>A token that passes V1 through V7 establishes: the identity of the
        issuer, the identity of each delegator and delegate in the chain, the
        capabilities available at the leaf, and that no hop in the chain
        exceeded the authority of its predecessor. It does not establish that
        the presenting party is the party the leaf was issued to. See
        <xref target="proof-of-possession"/>.</t>
      </section>
    </section>

    <section anchor="trust-anchors">
      <name>Trust Anchors and Workload Identity</name>
      <t>AIP answers a different question from a workload identity system,
      and the two compose rather than compete.</t>

      <t>A workload identity system such as SPIFFE
      <xref target="SPIFFE"/>, in the architecture described by
      <xref target="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.</t>

      <t>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 says nothing about
      whether the process presenting the token is the one the platform
      attested.</t>

      <section anchor="anchor-modes">
        <name>Anchor Modes</name>
        <t>Block 0 of a chain is signed by the issuer's key. Three ways of
        establishing trust in that key are defined:</t>
        <ul>
          <li>DNS-anchored: the issuer is an <tt>aip:web:</tt> identifier and
          the key is published in an identity document resolved over HTTPS.
          Trust derives from the Web PKI and DNS control.</li>
          <li>Self-certifying: the issuer is an <tt>aip:key:</tt> identifier
          and the key is the identifier. Trust derives from whoever accepted
          the identifier.</li>
          <li>Workload-attested: the issuer's key is bound to a workload
          identity credential issued by an external authority, and the identity
          document records that binding. Trust derives from that authority's
          attestation.</li>
        </ul>

        <t>In workload-attested mode, an identity document MAY carry a
        <tt>workload_identity</tt> 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.</t>

        <t>This is the deployment shape most likely in practice: 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.</t>
      </section>

      <section anchor="relationship-token-exchange">
        <name>Relationship to Token Exchange</name>
        <t>A common deployment pattern carries delegation by repeated token
        exchange <xref target="RFC8693"/>, in which each hop presents its
        credential to an authorization server and receives a narrowed token
        carrying an <tt>act</tt> claim naming the acting party.</t>
        <t>The mechanisms differ in where verification happens. Token exchange
        places an authorization server on the path at each hop, and the
        relying party's assurance derives from trusting that server. An AIP
        chain is verified by the relying party directly from the token and the
        issuer's published key, with no synchronous call to the originating
        organization. The two are not exclusive: an exchanged token may serve
        as the credential that anchors block 0.</t>
      </section>

      <section anchor="proof-of-possession">
        <name>Proof of Possession</name>
        <t>An AIP token as specified in this document is a bearer credential.
        Verification establishes what authority the chain conveys and that no
        hop exceeded its predecessor. It does not establish that the party
        presenting the token is the party the leaf was delegated to. A captured
        or relayed token is usable by whoever holds it, within the scope, time,
        and budget the chain permits.</t>
        <t>Deployments requiring proof of possession MUST bind the token to a
        key at the transport or message layer. Mutual TLS, HTTP message
        signatures, and workload proof tokens
        <xref target="I-D.ietf-wimse-wpt"/> are all suitable. Specifying that
        binding is out of scope for this document, and is deliberately left to
        mechanisms already being standardized rather than duplicated here.</t>
        <t>Implementations MUST NOT describe AIP verification as
        authenticating the presenter.</t>
      </section>
    </section>

    <section anchor="protocol-bindings">
      <name>Protocol Bindings</name>

      <section anchor="mcp-binding">
        <name>MCP Binding</name>
        <t>AIP tokens are transported in MCP via the X-AIP-Token HTTP header:</t>
        <artwork><![CDATA[
X-AIP-Token: <compact-or-chained-token>
        ]]></artwork>
        <t>For tokens exceeding 4KB, token-by-reference is supported:</t>
        <artwork><![CDATA[
X-AIP-Token-Ref: https://issuer/.well-known/aip/tokens/<id>
        ]]></artwork>
        <t>An MCP server extracts the token from the header, or fetches it
        from the reference URL, and then verifies it according to
        <xref target="verification-algorithm"/>. On success it injects the
        verified identity into the request context, where the tool
        implementation MAY use it for authorization decisions, logging, or
        audit. The verification steps are not restated here; the algorithm is
        binding-independent, and an MCP server that verifies tokens
        differently from an A2A agent is a source of exactly the divergence
        this document exists to prevent.</t>
        <t>Nine error codes are defined with appropriate HTTP status
        mappings: 401 for authentication failures (token_missing,
        token_malformed, signature_invalid, identity_unresolvable,
        token_expired, key_revoked) and 403 for authorization failures
        (scope_insufficient, budget_exceeded, depth_exceeded).</t>
        <t>Servers declare AIP requirements via the require_aip field
        in their identity document's protocols.mcp configuration.</t>
      </section>

      <section anchor="a2a-binding">
        <name>A2A Binding</name>
        <t>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.</t>
        <t>The A2A verification flow adds a sixth step: the calling agent
        appends a delegation block with attenuated scope before sending
        the task, and the receiving agent verifies that the final
        delegation block delegates to its own AIP identifier.</t>
      </section>

      <section anchor="http-binding">
        <name>HTTP Binding</name>
        <t>For generic HTTP APIs not using MCP or A2A, tokens are
        transported via the Authorization header with the AIP scheme:</t>
        <artwork><![CDATA[
Authorization: AIP <base64url-encoded-token>
        ]]></artwork>
        <t>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).</t>
      </section>
    </section>

    <section anchor="delegation-lifecycle">
      <name>Delegation Lifecycle</name>

      <section anchor="bounded-depth">
        <name>Bounded Depth</name>
        <t>Block 0 declares max_depth (default: 3). Each delegation block
        increments effective depth by 1. If current depth equals max_depth,
        further delegation is forbidden. In compact mode, max_depth of 0
        means the holder MUST NOT delegate further.</t>
      </section>

      <section anchor="delegation-context">
        <name>Delegation Context</name>
        <t>Each delegation block MUST include a non-empty context field
        containing a human-readable description of the delegation purpose.
        Verifiers MUST reject tokens with missing or empty context. This
        requirement ensures audit trail integrity.</t>
      </section>

      <section anchor="ephemeral-agents">
        <name>Ephemeral Agent Grants</name>
        <t>For short-lived sub-agents, a parent agent generates an Ed25519
        keypair, creates an aip:key: identifier, and appends a delegation
        block with scoped capabilities and a short TTL (5 minutes
        RECOMMENDED). The parent's identity document MAY set
        delegation.allow_ephemeral_grants to false to prevent this.</t>
      </section>

      <section anchor="key-rotation">
        <name>Key Rotation</name>
        <t>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.</t>
        <t>Self-certifying identifiers cannot rotate keys; key rotation
        requires identity replacement, which is acceptable for ephemeral
        agents.</t>
      </section>

      <section anchor="revocation">
        <name>Revocation</name>
        <t>AIP prefers short-lived tokens over revocation infrastructure.
        Compact mode tokens SHOULD have a TTL under 1 hour, making
        revocation generally unnecessary. For chained mode, key revocation
        (removing a key from the identity document) invalidates all tokens
        signed by that key. Token-specific revocation via Certificate
        Revocation Lists is deferred to v2.</t>
      </section>
    </section>

    <section anchor="provenance">
      <name>Provenance and Audit</name>

      <section anchor="completion-blocks">
        <name>Completion Blocks</name>
        <t>A completion block is the final block in a chained token,
        signed by the executing agent. It contains:</t>
        <ul>
          <li><tt>status</tt>: REQUIRED. One of "completed", "failed", or "partial".</li>
          <li><tt>result_hash</tt>: REQUIRED. SHA-256 hash of the output in format "sha256:&lt;hex&gt;".</li>
          <li><tt>verification_status</tt>: REQUIRED. One of "self_reported", "tool_verified", "peer_verified", or "human_verified".</li>
          <li><tt>tokens_used</tt>: OPTIONAL. LLM tokens consumed.</li>
          <li><tt>cost_usd</tt>: OPTIONAL. Actual cost incurred.</li>
          <li><tt>duration_ms</tt>: OPTIONAL. Wall-clock execution time.</li>
          <li><tt>ldp_provenance_id</tt>: OPTIONAL. Back-link to LDP provenance record.</li>
        </ul>
      </section>

      <section anchor="trust-levels">
        <name>Verification Trust Levels</name>
        <t>AIP defines three escalating trust levels for completion data:</t>
        <ul>
          <li>Level 1 (Self-Reported): Agent reports its own results with
          no independent verification. Default for trusted environments.</li>
          <li>Level 2 (Counter-Signed): Delegator independently verifies
          the result and appends a verification block.</li>
          <li>Level 3 (Third-Party Attested): External verifier (LDP peer,
          human reviewer, or audit service) signs an attestation block.</li>
        </ul>
      </section>

      <section anchor="audit-tokens">
        <name>Audit Tokens</name>
        <t>A completed chained token with a completion block appended is
        a self-contained audit artifact. It answers five questions without
        requiring an external database: who authorized (Block 0), through
        whom (delegation blocks), what constraints (Datalog policies),
        what happened (completion block), and whether it was verified
        (verification_status). Audit tokens are tamper-evident,
        non-repudiable, and verifiable offline using public keys from
        identity documents.</t>
      </section>
    </section>

    <section anchor="security-considerations">
      <name>Security Considerations</name>

      <t>This section addresses the security properties and threat model
      for AIP.</t>

      <section anchor="threat-model">
        <name>Threat Model</name>
        <t>AIP is designed to resist the following attack categories:</t>
        <ul>
          <li>Scope widening: An agent attempts to exceed its delegated
          capabilities. Prevented by cryptographic scope attenuation
          verification at each hop.</li>
          <li>Delegation depth violation: An agent attempts to delegate
          beyond the maximum permitted depth. Prevented by depth tracking
          in each delegation block.</li>
          <li>Token replay: A captured token is reused. Mitigated by
          short TTLs (under 1 hour recommended for compact mode).</li>
          <li>Token forgery: An attacker constructs a token without
          holding the private key. Prevented by Ed25519 signature
          verification.</li>
          <li>Identity spoofing: An agent claims a false identity.
          Prevented by identity document resolution and signature
          verification.</li>
          <li>Audit evasion: An agent delegates with empty context to
          avoid audit trails. Prevented by mandatory non-empty context
          on all delegation blocks.</li>
          <li>Ancestor substitution: An attacker holding a valid leaf block
          attempts to present it beneath a different, more permissive
          ancestor. Prevented by V1, which verifies the full signature chain
          from the root key rather than the leaf in isolation. A substituted
          ancestor breaks the chain, because each block's signature is
          produced by the key its predecessor committed to.</li>
        </ul>

        <t>Two of these deserve to be separated, because conflating them is a
        common source of error. Signature chaining (V1) prevents blocks from
        being forged, reordered, or substituted. Attenuation checking (V4)
        prevents a block 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.</t>
      </section>

      <section anchor="adversarial-evaluation">
        <name>Adversarial Evaluation</name>
        <t>Experimental evaluation across 600 adversarial attempts in six
        attack categories showed a 100% rejection rate. Two attack
        categories (delegation depth violation and audit evasion through
        empty context) are uniquely addressed by AIP's chained token
        structure and cannot be detected by standard JWT deployments.
        Details are reported in the companion paper
        <xref target="AIP-PAPER"/>.</t>
      </section>

      <section anchor="crypto-agility">
        <name>Cryptographic Agility</name>
        <t>AIP v1 mandates Ed25519 exclusively. No algorithm negotiation
        is supported. This is a deliberate design choice to eliminate
        downgrade attacks and reduce implementation complexity. Future
        versions MAY introduce additional algorithms through the protocol
        version field.</t>
      </section>

      <section anchor="transport-security">
        <name>Transport Security</name>
        <t>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.</t>
      </section>
    </section>

    <section anchor="iana-considerations">
      <name>IANA Considerations</name>

      <t>This document requests the following IANA registrations:</t>

      <section anchor="iana-auth-scheme">
        <name>HTTP Authentication Scheme</name>
        <t>Registration of the "AIP" HTTP authentication scheme in the
        "HTTP Authentication Scheme Registry":</t>
        <ul>
          <li>Authentication Scheme Name: AIP</li>
          <li>Reference: This document, <xref target="http-binding"/></li>
        </ul>
      </section>

      <section anchor="iana-well-known">
        <name>Well-Known URI</name>
        <t>Registration of the "aip" well-known URI suffix in the
        "Well-Known URIs" registry:</t>
        <ul>
          <li>URI Suffix: aip</li>
          <li>Change Controller: IETF</li>
          <li>Reference: This document, <xref target="identity-document"/></li>
        </ul>
      </section>

      <section anchor="iana-media-type">
        <name>Media Type</name>
        <t>Registration of the "aip+jwt" structured syntax suffix:</t>
        <ul>
          <li>Type name: application</li>
          <li>Subtype name: aip+jwt</li>
          <li>Reference: This document, <xref target="compact-mode"/></li>
        </ul>
      </section>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>

      <references>
        <name>Normative References</name>

        <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author initials="S." surname="Bradner" fullname="S. Bradner"/>
            <date year="1997" month="March"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
        </reference>

        <reference anchor="RFC7519" target="https://www.rfc-editor.org/info/rfc7519">
          <front>
            <title>JSON Web Token (JWT)</title>
            <author initials="M." surname="Jones" fullname="M. Jones"/>
            <author initials="J." surname="Bradley" fullname="J. Bradley"/>
            <author initials="N." surname="Sakimura" fullname="N. Sakimura"/>
            <date year="2015" month="May"/>
          </front>
          <seriesInfo name="RFC" value="7519"/>
        </reference>

        <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author initials="B." surname="Leiba" fullname="B. Leiba"/>
            <date year="2017" month="May"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
        </reference>

        <reference anchor="RFC8785" target="https://www.rfc-editor.org/info/rfc8785">
          <front>
            <title>JSON Canonicalization Scheme (JCS)</title>
            <author initials="A." surname="Rundgren" fullname="A. Rundgren"/>
            <author initials="B." surname="Jordan" fullname="B. Jordan"/>
            <author initials="S." surname="Erdtman" fullname="S. Erdtman"/>
            <date year="2020" month="June"/>
          </front>
          <seriesInfo name="RFC" value="8785"/>
        </reference>

        <reference anchor="RFC8693" target="https://www.rfc-editor.org/info/rfc8693">
          <front>
            <title>OAuth 2.0 Token Exchange</title>
            <author initials="M." surname="Jones" fullname="Michael B. Jones"/>
            <author initials="A." surname="Nadalin" fullname="Anthony Nadalin"/>
            <author initials="B." surname="Campbell" fullname="Brian Campbell"/>
            <author initials="J." surname="Bradley" fullname="John Bradley"/>
            <author initials="C." surname="Mortimore" fullname="Chuck Mortimore"/>
            <date year="2020" month="January"/>
          </front>
          <seriesInfo name="RFC" value="8693"/>
        </reference>
      </references>

      <references>
        <name>Informative References</name>

        <reference anchor="SPIFFE" target="https://spiffe.io/">
          <front>
            <title>Secure Production Identity Framework for Everyone (SPIFFE)</title>
            <author>
              <organization>Cloud Native Computing Foundation</organization>
            </author>
            <date year="2026"/>
          </front>
        </reference>

        <reference anchor="I-D.ietf-wimse-arch">
          <front>
            <title>Workload Identity in a Multi System Environment (WIMSE) Architecture</title>
            <author>
              <organization>IETF WIMSE Working Group</organization>
            </author>
            <date year="2026"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-wimse-arch"/>
        </reference>

        <reference anchor="I-D.ietf-wimse-wpt">
          <front>
            <title>WIMSE Workload Proof Token</title>
            <author>
              <organization>IETF WIMSE Working Group</organization>
            </author>
            <date year="2026"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-wimse-wpt"/>
        </reference>

        <reference anchor="I-D.reece-wimse-cross-org-delegation">
          <front>
            <title>Cross-Organizational Delegation for Workload and Agent Identity: Problem Statement and Requirements</title>
            <author initials="M." surname="Reece" fullname="M. Reece"/>
            <date year="2026" month="June"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-reece-wimse-cross-org-delegation-00"/>
        </reference>

        <reference anchor="I-D.rampalli-pedigree">
          <front>
            <title>PEDIGREE: Verifiable Delegation Identity for Agentic AI Systems</title>
            <author initials="K." surname="Rampalli" fullname="Karthik Rampalli"/>
            <date year="2026"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-rampalli-pedigree"/>
        </reference>

        <reference anchor="BISCUIT" target="https://www.biscuitsec.org/">
          <front>
            <title>Biscuit Authorization Token</title>
            <author initials="G." surname="Music" fullname="Geoffrey Music"/>
            <date year="2024"/>
          </front>
        </reference>

        <reference anchor="AIP-PAPER" target="https://arxiv.org/abs/2603.24775">
          <front>
            <title>AIP: Agent Identity Protocol for Verifiable Delegation Across MCP and A2A</title>
            <author initials="S." surname="Prakash" fullname="Sunil Prakash"/>
            <date year="2026" month="March" day="27"/>
          </front>
        </reference>
      </references>
    </references>

    <section anchor="cross-org-mapping">
      <name>Cross-Organization Delegation Requirements Mapping</name>
      <t><xref target="I-D.reece-wimse-cross-org-delegation"/> enumerates nine
      requirements for delegation between organizations that share no
      operator, no runtime, and no bilateral agreement. This appendix maps AIP
      against them. Verdicts are stated conditionally where the mechanism
      depends on deployment choices, and gaps are named rather than
      argued around.</t>

      <t>Other proposals address overlapping parts of the same problem,
      including <xref target="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.</t>

      <dl>
        <dt>R1, Recursive attenuation: MET.</dt>
        <dd>Step V4 of <xref target="verification-algorithm"/> requires a
        structural walk confirming that each hop is a subset of its
        predecessor across scope, budget, time, and domains, verifiable from
        the conveyed authority alone. The canonical encoding in
        <xref target="canonical-encoding"/> additionally makes scope widening
        impossible by construction, since the authorized set is the
        intersection of per-block allowlists.</dd>

        <dt>R2, Cross-organizational verification: MET.</dt>
        <dd>An <tt>aip:web:</tt> 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 <tt>aip:key:</tt> issuer needs no
        resolution at all. Neither requires a federation relationship
        established in advance of the interaction.</dd>

        <dt>R3, No runtime callback: MET, with caching.</dt>
        <dd>Once the issuer's identity document is held, verification is
        local. Documents are cacheable, so the originating organization is not
        on the critical path. The exception is revocation freshness, which
        R7 addresses.</dd>

        <dt>R4, Proof of possession: NOT MET by this document.</dt>
        <dd>An AIP token is a bearer credential, as stated in
        <xref target="proof-of-possession"/>. Binding the token to a key
        requires a transport or message layer mechanism. This document
        deliberately does not define one, and points instead at
        <xref target="I-D.ietf-wimse-wpt"/> and HTTP message signatures.</dd>

        <dt>R5, Principal binding and invariance: MET when declared.</dt>
        <dd>Block 0 MAY declare a <tt>principal</tt>, and V4 requires that no
        subsequent block declare a different one. A chain that omits the
        principal conveys agent authority only and does not satisfy R5.</dd>

        <dt>R6, Dual-axis authorization: NOT MET, and out of scope.</dt>
        <dd>AIP conveys the agent's authority and the identity of the bound
        principal. It does not carry the principal's entitlements, and a
        verifier cannot evaluate them from the token. Composing the two axes
        is the relying party's responsibility. Naming this rather than
        claiming it seems more useful to the working group.</dd>

        <dt>R7, Authentic, bounded-staleness revocation: MET.</dt>
        <dd>Step V7 requires signed revocation responses, so authenticity does
        not depend on transport trust, and requires verifiers to be
        configurable with a maximum staleness and to fail closed beyond it.</dd>

        <dt>R8, Tamper-evident, composable audit: MET.</dt>
        <dd>Each delegation block records delegator, delegate, and a non-empty
        context, and completion blocks record outcome and cost. Because blocks
        are signed in sequence, a participant's own record cannot be altered
        undetectably by a later participant, and the chain composes into an
        end-to-end account.</dd>

        <dt>R9, Format and transport agnosticism: MET.</dt>
        <dd>Compact mode is a JWT and chained mode is a Biscuit token; neither
        presupposes a transport. Bindings are specified for MCP, A2A, and
        generic HTTP, and the identity layer is uniform across them.</dd>
      </dl>

      <t>Summarising the gaps: AIP does not by itself prove possession (R4) or
      evaluate principal entitlements (R6). Both are shared with other
      proposals in this space and both are better solved by composition than
      by any one document.</t>
    </section>

    <section anchor="changes-from-00">
      <name>Changes from draft-prakash-aip-00</name>
      <ul>
        <li>Added <xref target="verification-algorithm"/>, a normative
        verification algorithm with ordered steps V1 through V7 and defined
        error codes. Draft-00 asserted that verifiers must check attenuation
        at every hop without specifying how, which left the requirement open
        to divergent readings.</li>
        <li>Added <xref target="canonical-encoding"/>, fixing the exact Datalog
        each implementation must emit for the Simple profile. Draft-00 named
        canonical templates without normative form, and independent
        implementations diverged.</li>
        <li>Changed budget from a Datalog check to a
        <tt>budget_ceiling</tt> fact verified structurally in V4, and stated
        plainly that ceiling verification is not spend enforcement. The
        previous encoding could not express the intended comparison.</li>
        <li>Added an OPTIONAL <tt>principal</tt> fact with an invariance rule,
        addressing principal binding along a chain.</li>
        <li>Added <xref target="trust-anchors"/> describing workload-attested
        anchoring, the relationship to workload identity systems, and the
        relationship to token exchange.</li>
        <li>Stated explicitly that AIP tokens are bearer credentials and that
        verification does not authenticate the presenter.</li>
        <li>Added bounded-staleness and signed-response requirements for
        revocation.</li>
        <li>Added <xref target="cross-org-mapping"/>.</li>
      </ul>
    </section>

    <section anchor="acknowledgements" numbered="false">
      <name>Acknowledgements</name>
      <t>The Biscuit authorization token specification influenced the
      chained mode design. The MCP and A2A protocol teams provided the
      agent communication infrastructure that AIP extends.</t>
    </section>
  </back>
</rfc>
