<?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" submissionType="IETF" docName="draft-aip-agent-identity-protocol-00" category="std" ipr="trust200902" obsoletes="" updates="" xml:lang="en" symRefs="true" sortRefs="false" tocInclude="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.32.0 -->
  <!-- Generated by id2xml 1.5.2 on 2026-03-16T18:06:04Z -->
	<front>
    <title abbrev="Agent Identity Protocol: Agentic Authent">Agent Identity Protocol: Agentic Authentication and Authorized Policy Enforcement</title>
    <seriesInfo name="Internet-Draft" value="draft-aip-agent-identity-protocol-00"/>
    <author initials="J." surname="Cao" fullname="James Cao">
      <organization>Montcao</organization>
      <address>
        <email>james@montcao.com</email>
        <uri>https://agentidentityprotocol.io</uri>
      </address>
    </author>
    <author initials="C." surname="Arango Gutierrez" fullname="Carlos Eduardo Arango Gutierrez">
      <organization>NVIDIA</organization>
      <address>
        <email>eduardoa@nvidia.com</email>
        <uri>https://agentidentityprotocol.io</uri>
      </address>
    </author>
    <date year="2026" month="March" day="16"/>
    <abstract>
      <t>
   This document defines the Agent Identity Protocol (AIP), an open
   standard for verifiable identity and policy enforcement for
   artificial intelligence (AI) agents.</t>
      <t>
   Agent Identity Protocol (AIP) addresses the problem of AI agents operating with unbounded
   permissions -- running as users, inheriting full API key access, and
   executing tool calls with no verifiable identity boundary between
   human and non-human actors.</t>
      <t>
   The protocol is structured as two cooperating layers.  Layer 1
   (Identity) gives every agent a unique identifier and a key
   pair registered with an AIP Registry; the agent signs every outbound
   action with that key.  Layer 2 (Enforcement) interposes a proxy
   between the AI client and every tool server that verifies the
   signature, evaluates a declarative policy, and produces an allow,
   deny, or hold decision before any tool is reached.</t>
    </abstract>
  </front>
  <middle>
    <section anchor="sect-1" numbered="true" toc="default">
      <name>Introduction</name>
      <t>
   AI agents are being deployed at scale with the same credentials as
   the humans who operate them.  When an agent calls a tool -- writing
   a file, querying a database, sending a request to an external API --
   there is nothing in the request that distinguishes it from a direct
   human action.  The downstream service has no way to know it is
   talking to an agent, which agent, who authorized it, or what it is
   permitted to do.</t>
      <t>
   This creates compounding problems as agents become more capable and
   more numerous.  An agent that is compromised, misbehaves, or is
   manipulated into acting outside its intended scope has no technical
   boundary stopping it from using every credential it has been given.
   Audit logs attribute actions to human accounts rather than to agents,
   making incident investigation difficult.  Multi-agent systems can
   accumulate permissions across delegation steps without any explicit
   record of what was authorized.</t>
      <t>
   AIP closes this gap with two layers:</t>
      <t>
   Layer 1 -- Agent Identity.  At provisioning time, the agent is
   registered with an AIP Registry.  The registry assigns the agent a
   unique identifier (the Agent ID) and records the agent's
   public key alongside the identity of the accountable principal.
   From that point forward, the agent signs every outbound tool call
   with its private key.  Any party that can reach the registry can
   verify who the agent is.</t>
      <t>
   Layer 2 -- Enforcement Proxy.  An AIP Proxy sits between the AI
   client and every tool server.  It intercepts every tool call,
   verifies the agent's signature against the registry, evaluates the
   call against a simple declarative policy (the AgentPolicy), and
   either forwards the call, blocks it, or holds it for human approval.
   The tool server is never reached until all checks pass.  Every
   decision is written to an append-only audit log.</t>
      <t>
   The two layers are independent.  Layer 1 can be used without Layer 2
   to provide signed, attributable agent actions in existing systems.
   Layer 2 requires Layer 1 for identity verification but adds no new
   requirements on tool servers.</t>
      <t>
   AIP targets the Model Context Protocol (MCP) <xref target="MCP" format="default"/> as its primary
   tool-call interface but is designed to be applicable to any
   structured tool invocation mechanism.</t>
      <t>
   AIP does NOT:</t>
      <ul spacing="normal">
        <li>
          <t>Define a new transport protocol.</t>
        </li>
        <li>
          <t>Replace existing service-level authentication (OAuth 2.0, mTLS).
      It adds an agent-identity layer on top of existing mechanisms.</t>
        </li>
        <li>
          <t>Provide content moderation or model output filtering.</t>
        </li>
      </ul>
    </section>
    <section anchor="sect-2" numbered="true" toc="default">
      <name>Terminology and Conventions</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" format="default"/> <xref target="RFC8174" format="default"/> when, and only when, they appear in all
   capitals, as shown here.</t>
      <dl newline="true" spacing="normal" indent="3">
        <dt>Agent:</dt>
        <dd>
	An autonomous software process that uses a large language model
      or other AI system to reason over tasks and invoke external tools
      on behalf of a principal.
	</dd>
        <dt>Agent ID:</dt>
        <dd>
	A unique, stable identifier assigned to an agent by an AIP
      Registry at registration time.  The Agent ID is a UUID v4
      <xref target="RFC4122" format="default"/> prefixed with the registry hostname, e.g.,
      "reg.example.com/01933f4a-9b2c-7d8e-af01-3b5c6d7e8f9a".
	</dd>
        <dt>Agent Record:</dt>
        <dd>
	The data structure stored in the AIP Registry that holds an
      agent's Agent ID, public key, principal identifier, and metadata.
      Defined in <xref target="sect-5.2" format="default"/>.
	</dd>
        <dt>AIP Proxy (or "Enforcement Proxy"):</dt>
        <dd>
	A transparent forward proxy that intercepts tool calls between
      an AI client and tool servers.  It verifies the AIP Token and
      evaluates the AgentPolicy before forwarding or blocking the call.
	</dd>
        <dt>AIP Registry:</dt>
        <dd>
	A server that stores Agent Records and exposes an HTTP API for
      registration, key lookup, and revocation.
	</dd>
        <dt>AIP Token:</dt>
        <dd>
	A signed JSON object attached to every tool call by the agent.
      It carries the agent's Agent ID, the tool being called, a nonce,
      a timestamp, and an key signature.  Defined in <xref target="sect-5.6" format="default"/>.
	</dd>
        <dt>AgentPolicy:</dt>
        <dd>
	A YAML configuration file that declares which tools an agent is
      permitted to call, argument constraints, DLP rules, and HITL
      requirements.  Defined in <xref target="sect-6.2" format="default"/>.
	</dd>
        <dt>DLP:</dt>
        <dd>
	Data Loss Prevention; scanning of tool call arguments and
      responses for sensitive data patterns.
	</dd>
        <dt>HITL:</dt>
        <dd>
	Human-in-the-Loop; a control mode in which the proxy holds a
      tool call and waits for explicit approval from an operator before
      forwarding it.
	</dd>
        <dt>IoA:</dt>
        <dd>
	Internet of Agents; the network of autonomous AI agents that
      act across organizational and infrastructure boundaries.
	</dd>
        <dt>MCP:</dt>
        <dd>
	Model Context Protocol <xref target="MCP" format="default"/>; a structured protocol for tool-call
      communication between AI clients and tool servers.
	</dd>
        <dt>Principal:</dt>
        <dd>
	The human operator or organization accountable for an agent.
	</dd>
        <dt>Tool Call:</dt>
        <dd>
	A structured invocation of an external capability initiated by
      an agent, typically carrying a tool name and arguments.
	</dd>
        <dt>Tool Server:</dt>
        <dd>
	A service that exposes tools callable by agents.
	</dd>
      </dl>
    </section>
    <section anchor="sect-3" numbered="true" toc="default">
      <name>Problem Statement</name>
      <section anchor="sect-3.1" numbered="true" toc="default">
        <name>The Identity Gap</name>
        <t>
   When an AI agent calls a tool, it presents credentials that belong
   to a human account.  The tool server cannot tell whether the actor
   is a human or an agent, which agent it is, or what limits apply to
   it.  This creates four concrete problems:</t>
        <dl newline="false" spacing="normal" indent="5">
          <dt>(a)</dt>
          <dd>
            <t>
	Security -- A compromised or manipulated agent can invoke any
            </t>
            <t>
	tool the human account can reach.  There is no agent-specific
        authorization boundary.
            </t>
          </dd>
          <dt>(b)</dt>
          <dd>
            <t>
	Auditability -- Logs record actions against a human account.
            </t>
            <t>
	After an incident, investigators cannot determine which actions
        were taken by a human versus an agent.
            </t>
          </dd>
          <dt>(c)</dt>
          <dd>
            <t>
	Compliance -- Regulations increasingly require traceability of
            </t>
            <t>
	automated decision-making.  Without agent-level identity,
        organizations cannot satisfy these requirements.
            </t>
          </dd>
          <dt>(d)</dt>
          <dd>
            <t>
	Accountability -- Billing, rate limits, and quotas are scoped
            </t>
            <t>
	to human accounts.  Agent usage cannot be isolated or
        attributed.
            </t>
          </dd>
        </dl>
      </section>
      <section anchor="sect-3.2" numbered="true" toc="default">
        <name>The Enforcement Gap</name>
        <t>
   Even where agent behavior policies exist, they are expressed as
   text in model system prompts.  System prompts are not tamper-evident
   and can be bypassed by adversarial inputs to the model.  There is no
   infrastructure-layer enforcement point that acts independently of
   the model.</t>
      </section>
      <section anchor="sect-3.3" numbered="true" toc="default">
        <name>Scope of This Specification</name>
        <t>
   AIP closes both gaps.  Layer 1 gives every agent a distinct,
   verifiable identity independent of the human principal's credentials.
   Layer 2 enforces agent-specific policy at the tool-call boundary,
   outside the model's trust domain, in a way that cannot be overridden
   by model outputs.</t>
      </section>
    </section>
    <section anchor="sect-4" numbered="true" toc="default">
      <name>Protocol Overview</name>
      <section anchor="sect-4.1" numbered="true" toc="default">
        <name>Architecture</name>
        <t>
   AIP introduces two components into the agent-to-tool-server path:
   an AIP Registry (Layer 1) and an AIP Proxy (Layer 2).</t>
        <figure anchor="ure-aip-architecture">
          <name>AIP Architecture</name>
          <artwork name="" type="" align="left" alt=""><![CDATA[
                 +-----------------------------------------+
                 |           AI Client (Agent)             |
                 +-----------------+-----------------------+
                                   | tools/call + AIP Token
                                   v
                 +-----------------------------------------+
                 |            AIP Proxy (Layer 2)          |
                 |  +-----------+  +--------------------+  |
                 |  |  Verify   |  |   Policy Engine    |  |
                 |  |  Token    |  |   (AgentPolicy)    |  |
                 |  +-----+-----+  +---------+----------+  |
                 |        |                  |              |
                 |  +-----v------------------v----------+  |
                 |  |         Audit Logger              |  |
                 |  +-----------------------------------+  |
                 +-----+-------------------+---------------+
                       |                   |
                ALLOW  |             DENY  |  HOLD
                       v                   v
                 +-----------+    +------------------+
                 | Tool      |    | Error / HITL     |
                 | Server    |    | Queue            |
                 +-----------+    +------------------+

                 ^
                 | key lookup
                 |
            +---------+
            |   AIP   |
            | Registry|
            | (Lay. 1)|
            +---------+
]]></artwork>
        </figure>
      </section>
      <section anchor="sect-4.2" numbered="true" toc="default">
        <name>Call Lifecycle</name>
        <t>
   The lifecycle of a single tool call under AIP is as follows:</t>
        <ol spacing="normal" type="1"><li>
            <t>Registration (once, at deploy time).  The principal registers
       the agent with an AIP Registry.  The registry assigns an Agent
       ID and stores the agent's public key.  The agent stores
       its private key securely.</t>
          </li>
          <li>
            <t>Token construction (per call).  Before each tool call the agent
       constructs an AIP Token (<xref target="sect-5.6" format="default"/>): a small JSON object
       containing the Agent ID, tool name, argument hash, nonce,
       timestamp, and a key signature over the token.</t>
          </li>
          <li>
            <t>Proxy intercept.  The AIP Proxy receives the tool call request
       before it reaches the tool server.</t>
          </li>
          <li>
            <t>Token verification (Layer 1).  The proxy retrieves the agent's
       public key from the registry (or local cache) and verifies the
       signature.  It also checks the nonce for replay and the timestamp
       for freshness.</t>
          </li>
          <li>
            <t>Policy evaluation (Layer 2).  The proxy checks the call against
       the AgentPolicy: is the tool on the allowlist?  Do the arguments
       pass validation?  Does the call trigger a HITL hold?  Does the
       response contain sensitive data that must be redacted?</t>
          </li>
          <li>
            <t>Decision.  The proxy produces one of three outcomes:
       ALLOW -- forward the call to the tool server;
       DENY  -- return an error to the agent, tool server not reached;
       HOLD  -- queue the call for human approval.</t>
          </li>
          <li>
            <t>Audit.  Every decision is written to the audit log regardless
       of outcome.</t>
          </li>
        </ol>
      </section>
      <section anchor="sect-4.3" numbered="true" toc="default">
        <name>Relationship to Existing Standards</name>
        <ul spacing="normal">
          <li>
            <t>OAuth 2.0 <xref target="RFC6749" format="default"/> / OIDC <xref target="OIDC" format="default"/>:  AIP does not replace service-
      level authentication.  The agent still presents its OAuth token or
      API key to the tool server.  AIP provides a separate agent
      identity layer that the proxy can verify independently.</t>
          </li>
          <li>
            <t>SPIFFE/SVID <xref target="SPIFFE" format="default"/>:  In Kubernetes deployments, the AIP Proxy
      MAY use a SPIFFE SVID to authenticate to tool servers over mTLS,
      layering workload identity on top of AIP agent identity.</t>
          </li>
          <li>
            <t>JSON-RPC 2.0 <xref target="JSON-RPC" format="default"/>:  Tool call and error messages use the
      JSON-RPC 2.0 wire format, compatible with MCP and similar
      protocols.</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="sect-5" numbered="true" toc="default">
      <name>Layer 1: Agent Identity</name>
      <section anchor="sect-5.1" numbered="true" toc="default">
        <name>Agent Registration</name>
        <t>
   An agent is provisioned by its principal submitting a registration
   request to an AIP Registry.  The request MUST include:</t>
        <dl newline="false" spacing="normal" indent="5">
          <dt>(a)</dt>
          <dd>
            <t>
	The agent's public key, base64url-encoded <xref target="RFC4648" format="default"/>;
            </t>
            <t>
	(b)  The principal identifier -- a string that uniquely identifies
        the accountable human or organization (e.g., an email address,
        an organization slug, or an OAuth subject claim); (TO BE WORKED ON FURTHER)
            </t>
          </dd>
          <dt>(c)</dt>
          <dd>
            <t>
	A human-readable agent name (RECOMMENDED);
            </t>
            <t>
	(d)  An optional free-text description.
            </t>
          </dd>
        </dl>
        <t>
   The registration request MUST be authenticated.  Authentication MAY
   be via OAuth 2.0 bearer token, mTLS client certificate, or a pre-
   shared registration secret, at the registry operator's discretion.</t>
        <t>
   On successful registration, the registry:</t>
        <dl newline="false" spacing="normal" indent="5">
          <dt>(a)</dt>
          <dd>
            <t>
	Assigns a UUID v4 <xref target="RFC4122" format="default"/> as the agent's local identifier;
            </t>
            <t>
	(b)  Constructs the Agent ID as "&lt;registry-host&gt;/&lt;uuid&gt;";
   (c)  Stores the Agent Record (<xref target="sect-5.2" format="default"/>);
   (d)  Returns the Agent ID to the principal.
            </t>
          </dd>
        </dl>
        <t>
   The principal MUST store the Agent ID and configure the agent with
   both the Agent ID and its private key before deployment.</t>
      </section>
      <section anchor="sect-5.2" numbered="true" toc="default">
        <name>Agent Record</name>
        <t>
   The Agent Record is the data structure the AIP Registry stores for
   each registered agent.  It MUST contain:</t>
        <dl newline="true" spacing="normal" indent="3">
          <dt>agentId (string):</dt>
          <dd>
	The Agent ID assigned at registration, in the form
      "&lt;registry-host&gt;/&lt;uuid-v4&gt;".
      Example: "reg.agentidentityprotocol.io/01933f4a-9b2c-7d8e-af01"
	</dd>
          <dt>publicKey (string):</dt>
          <dd>
	The agent's current public key, base64url-encoded.
	</dd>
          <dt>principalId (string):</dt>
          <dd>
	Identifier of the accountable principal.
	</dd>
          <dt>name (string):</dt>
          <dd>
	Human-readable agent name.  Informational only; not authenticated.
	</dd>
          <dt>description (string, optional):</dt>
          <dd>
	Free-text description of the agent's purpose.
	</dd>
          <dt>createdAt (string):</dt>
          <dd>
	ISO 8601 UTC timestamp of registration.
	</dd>
          <dt>keyHistory (array):</dt>
          <dd>
	Append-only list of all public keys ever bound to this Agent ID.
      Each entry contains "publicKey", "activeFrom", and "revokedAt"
      (null if still active).
	</dd>
          <dt>status (string):</dt>
          <dd>
	One of "active" or "revoked".
	</dd>
        </dl>
        <t>
   Example Agent Record (JSON):</t>
        <artwork name="" type="" align="left" alt=""><![CDATA[
{
  "agentId": "reg.agentidentityprotocol.io/01933f4a-9b2c-7d8e-af01",
  "publicKey": "MCowBQYDK2VwAyEAz8vG...",
  "principalId": "acme-corp",
  "name": "ResearchAssistant-v1",
  "description": "Internal document retrieval agent",
  "createdAt": "2026-01-15T09:00:00Z",
  "keyHistory": [
    {
      "publicKey": "MCowBQYDK2VwAyEAz8vG...",
      "activeFrom": "2026-01-15T09:00:00Z",
      "revokedAt": null
    }
  ],
  "status": "active"
}
]]></artwork>
      </section>
      <section anchor="sect-5.3" numbered="true" toc="default">
        <name>AIP Registry API</name>
        <t>
   The AIP Registry MUST expose the following HTTP endpoints over
   TLS 1.3 (<xref target="sect-9.4" format="default"/>):</t>
        <artwork name="" type="" align="left" alt=""><![CDATA[
POST   /v1/agents              Register a new agent
GET    /v1/agents/{agentId}    Retrieve an Agent Record
PUT    /v1/agents/{agentId}/key  Rotate the agent's public key
DELETE /v1/agents/{agentId}    Revoke an agent
GET    /v1/revocations/stream  SSE stream for revocation events
]]></artwork>
        <t>
   The GET /v1/agents/{agentId} endpoint is the only endpoint that
   MUST be reachable by AIP Proxies at call-verification time.  All
   other endpoints are used during provisioning and key management.</t>
        <t>
   Responses from GET /v1/agents/{agentId} MUST include the full
   Agent Record.  Proxies SHOULD cache this response for at least
   30 seconds.  The cache MUST be invalidated on receipt of a
   revocation event from the SSE stream.</t>
      </section>
      <section anchor="sect-5.4" numbered="true" toc="default">
        <name>Key Rotation</name>
        <t>
   A principal rotates an agent's key by submitting a PUT request to
   /v1/agents/{agentId}/key, authenticated with the current private
   key.  The request body MUST contain the new public key.</t>
        <dl newline="true" spacing="normal" indent="5">
          <dt>The registry MUST:</dt>
          <dd>
	(a)  Set "revokedAt" on the current keyHistory entry to the current
        timestamp;
	</dd>
          <dt>(b)</dt>
          <dd>
            <t>
	Append a new keyHistory entry with the new public key;
            </t>
            <t>
	(c)  Update the "publicKey" field on the Agent Record;
   (d)  Emit a rotation event on the revocations SSE stream so that
        proxies can invalidate their cached Agent Records immediately.
            </t>
          </dd>
        </dl>
        <t>
   The Agent ID does NOT change on key rotation.</t>
      </section>
      <section anchor="sect-5.5" numbered="true" toc="default">
        <name>Agent Revocation</name>
        <t>
   A principal revokes an agent by sending a DELETE request to
   /v1/agents/{agentId}.  The registry MUST set the agent's status
   to "revoked" and emit a revocation event on the SSE stream.</t>
        <t>
   Proxies MUST reject AIP Tokens from revoked agents with error
   AIP-E012.  Revoked Agent Records MUST be retained in the registry
   for audit log verification but MUST NOT be returned as "active".</t>
      </section>
      <section anchor="sect-5.6" numbered="true" toc="default">
        <name>The AIP Token (Agent Attestation Token)</name>
        <t>
   The AIP Token is a compact signed JSON object that the agent
   constructs and attaches to every outbound tool call.  It is the
   mechanism by which the agent asserts its identity to the proxy.</t>
        <section anchor="sect-5.6.1" numbered="true" toc="default">
          <name>Token Fields</name>
          <dl newline="true" spacing="normal" indent="3">
            <dt>aipVersion (string, REQUIRED):</dt>
            <dd>
	Protocol version.  MUST be "1" for this specification.
	</dd>
            <dt>agentId (string, REQUIRED):</dt>
            <dd>
	The agent's Agent ID as registered with the AIP Registry.
	</dd>
            <dt>tool (string, REQUIRED):</dt>
            <dd>
	The name of the tool being called, exactly as declared in the
      tool server's manifest.
	</dd>
            <dt>argumentsHash (string, REQUIRED):</dt>
            <dd>
	Lowercase hex-encoded SHA-256 hash of the canonical JSON
      serialization of the tool call arguments.  This binds the
      token to the specific arguments being passed.
	</dd>
            <dt>nonce (string, REQUIRED):</dt>
            <dd>
	A 128-bit cryptographically random value, hex-encoded.  MUST
      be unique per token.  MUST be generated by a CSPRNG.
	</dd>
            <dt>timestamp (string, REQUIRED):</dt>
            <dd>
	ISO 8601 UTC timestamp of token construction.
	</dd>
            <dt>signature (string, REQUIRED):</dt>
            <dd>
	Base64url-encoded signature over the canonical
      serialization of the token (<xref target="sect-5.6.2" format="default"/>).
	</dd>
          </dl>
        </section>
        <section anchor="sect-5.6.2" numbered="true" toc="default">
          <name>Canonical Serialization</name>
          <t>
   To produce the bytes that are signed:</t>
          <dl newline="false" spacing="normal" indent="5">
            <dt>(a)</dt>
            <dd>
              <t>
	Construct a JSON object containing all token fields except
              </t>
              <t>
	"signature";
              </t>
            </dd>
            <dt>(b)</dt>
            <dd>
              <t>
	Serialize with no insignificant whitespace;
              </t>
              <t>
	(c)  Sort object keys lexicographically;
   (d)  Encode as UTF-8.
              </t>
            </dd>
          </dl>
          <t>
   The signature field is then set to the base64url encoding of the signature over these bytes.</t>
        </section>
        <section anchor="sect-5.6.3" numbered="true" toc="default">
          <name>Example Token (before base64url encoding for transport)</name>
          <artwork name="" type="" align="left" alt=""><![CDATA[
{
  "aipVersion": "1",
  "agentId": "reg.agentidentityprotocol.io/01933f4a-9b2c-7d8e-af01",
  "tool": "read_file",
  "argumentsHash": "e3b0c44298fc1c149afb4c8996fb924...",
  "nonce": "a3f8b2c1d4e5f607a8b9c0d1e2f3a4b5",
  "timestamp": "2026-02-24T14:30:00Z",
  "signature": "TUlJQ0lqQU5CZ2txaGtpRzl3MEJB..."
}
]]></artwork>
        </section>
      </section>
      <section anchor="sect-5.7" numbered="true" toc="default">
        <name>Token Verification</name>
        <t>
   The AIP Proxy MUST perform the following checks in order.  A
   failure at any step MUST produce a DENY decision with the
   corresponding error code (<xref target="sect-7.2" format="default"/>) and an audit log entry.</t>
        <dl newline="true" spacing="normal" indent="3">
          <dt>Step 1 -- Presence check.</dt>
          <dd>
	Confirm the AIP Token is present in the request.
      On failure: AIP-E010.
	</dd>
          <dt>Step 2 -- Agent Record lookup.</dt>
          <dd>
	Resolve the Agent ID from the token against the AIP Registry
      (or local cache).  Confirm the Agent Record status is "active".
      On failure: AIP-E011 (unresolvable) or AIP-E012 (revoked).
	</dd>
          <dt>Step 3 -- Signature verification.</dt>
          <dd>
	Compute the canonical serialization (<xref target="sect-5.6.2" format="default"/>) and verify
      the key signature against the public key in the Agent Record.
      This operation MUST be performed in constant time.
      On failure: AIP-E013.
	</dd>
          <dt>Step 4 -- Nonce replay check.</dt>
          <dd>
	Check the nonce against the proxy's local nonce cache (minimum
      TTL: 600 seconds).  If the nonce has been seen before, reject.
      On failure: AIP-E004.
	</dd>
          <dt>Step 5 -- Timestamp freshness.</dt>
          <dd>
	Reject the token if its timestamp is more than 300 seconds in
      the past or 30 seconds in the future relative to the proxy clock.
      On failure: AIP-E005.
	</dd>
        </dl>
        <t>
   If all five steps pass, the token is verified and the call proceeds
   to policy evaluation (<xref target="sect-6.3" format="default"/>).</t>
      </section>
    </section>
    <section anchor="sect-6" numbered="true" toc="default">
      <name>Layer 2: Enforcement Proxy</name>
      <section anchor="sect-6.1" numbered="true" toc="default">
        <name>Proxy Architecture</name>
        <t>
   The AIP Proxy is a forward proxy interposed between the AI client
   and one or more tool servers.  It is transparent: it presents itself
   to the AI client as the tool server endpoint, and to the tool server
   as an authorized caller.</t>
        <t>
   The proxy operates in one of two modes, set per agent in the
   AgentPolicy:</t>
        <dl newline="false" spacing="normal" indent="10">
          <dt>enforce:</dt>
          <dd>
            <t>
	Policy violations result in DENY responses.  The tool
            </t>
            <t>
	server is never reached for blocked calls.  This is the
             default and RECOMMENDED mode.
            </t>
          </dd>
          <dt>monitor:</dt>
          <dd>
            <t>
	Policy violations are logged but calls are forwarded
            </t>
            <t>
	regardless.  Used for baselining and policy development
             before switching to enforce mode.
            </t>
          </dd>
        </dl>
        <t>
   The proxy MUST maintain locally:</t>
        <artwork name="" type="" align="left" alt=""><![CDATA[
o  The AgentPolicy for each agent it serves;
o  A bounded nonce cache (TTL >= 600 seconds, LRU eviction);
o  A revocation cache (refresh interval <= 60 seconds);
o  An append-only audit log.
]]></artwork>
      </section>
      <section anchor="sect-6.2" numbered="true" toc="default">
        <name>AgentPolicy</name>
        <t>
   The AgentPolicy is a YAML file that declares the enforcement rules
   for a specific agent.  One AgentPolicy file corresponds to one
   Agent ID. A AgentPolicy file can apply to multiple Agent IDs.</t>
        <section anchor="sect-6.2.1" numbered="true" toc="default">
          <name>Schema</name>
          <sourcecode name="" type="" markers="true"><![CDATA[
   agentId: <Agent ID>
   mode: <enforce | monitor>

   tools:
     allowed:
       - <tool-name>
     rules:
       - tool: <tool-name>
         action: <allow | ask | block>
         args:
           <arg-name>:
             pattern: <PCRE regex>
             maxLength: <integer>

   dlp:
     - name: <pattern name>
       regex: <PCRE regex>
       action: <redact | block>
       scope: <request | response | both>

   hitl:
     approvers:
       - <email or identifier of approver>
     timeout_seconds: <integer, default 300>  # seconds to wait for approval
     on_timeout: <deny | allow>               # action if no response received
]]></sourcecode>
        </section>
        <section anchor="sect-6.2.2" numbered="true" toc="default">
          <name>Tool Allowlist</name>
          <t>
   The tools.allowed list defines every tool the agent is permitted
   to call.  Any call to a tool not on this list MUST be denied with
   AIP-E001 when the proxy is in enforce mode.</t>
        </section>
        <section anchor="sect-6.2.3" numbered="true" toc="default">
          <name>Tool Rules</name>
          <t>
   Each entry in tools.rules applies additional handling to a named
   tool:</t>
          <dl newline="false" spacing="normal" indent="8">
            <dt>allow:</dt>
            <dd>
              <t>
	The tool is on the allowlist and is forwarded after
              </t>
              <t>
	argument validation.  This is the default when no rule
           is specified.
              </t>
            </dd>
            <dt>ask:</dt>
            <dd>
              <t>
	The call is held for HITL approval before forwarding,
              </t>
              <t>
	regardless of any other policy check.
              </t>
            </dd>
            <dt>block:</dt>
            <dd>
              <t>
	The call is unconditionally denied.  This overrides the
              </t>
              <t>
	allowlist and cannot be circumvented.  Use this for tools
           that must never be reachable by the agent under any
           circumstances.
              </t>
            </dd>
          </dl>
          <t>
   Argument rules (args) apply PCRE regex pattern matching and a
   maximum length check to named arguments before the call is
   forwarded.  A violation produces AIP-E002.</t>
        </section>
        <section anchor="sect-6.2.4" numbered="true" toc="default">
          <name>DLP Rules</name>
          <t>
   Each DLP rule specifies a regex pattern, an action, and a scope:</t>
          <dl newline="false" spacing="normal" indent="20">
            <dt>redact / request:</dt>
            <dd>
              <t>
	Matching content in arguments is replaced with
              </t>
              <t>
	"[REDACTED:&lt;name&gt;]" and the call proceeds.
              </t>
            </dd>
            <dt>redact / response:</dt>
            <dd>
              <t>
	Matching content in the tool response is
              </t>
              <t>
	replaced with "[REDACTED:&lt;name&gt;]" before the
                       response is returned to the agent.
              </t>
            </dd>
            <dt>block / both:</dt>
            <dd>
              <t>
	If a match is found anywhere in the request
              </t>
              <t>
	or response, the call or response is rejected
                       with AIP-E008.
              </t>
            </dd>
          </dl>
        </section>
        <section anchor="sect-6.2.5" numbered="true" toc="default">
          <name>HITL Configuration</name>
          <t>
   The hitl block identifies who may approve held calls, how long the
   proxy waits, and what to do on timeout.  The default on_timeout is
   "deny".  Setting on_timeout to "allow" SHOULD only be used for
   non-sensitive, low-impact tools.</t>
        </section>
      </section>
      <section anchor="sect-6.3" numbered="true" toc="default">
        <name>Intercept Flow</name>
        <t>
   The following is the normative sequence for every tool call received
   by the proxy.</t>
        <artwork name="" type="" align="left" alt=""><![CDATA[
1.  Receive the tool call from the AI client.

2.  Run token verification (Section 5.7).
    Any failure -> DENY with the corresponding AIP-Exxx code.

3.  Check tools.allowed.
    Tool not present and mode == enforce -> DENY AIP-E001.

4.  Check tools.rules for this tool.
    action == block -> DENY AIP-E003.
    action == ask   -> go to step 7 (HITL).

5.  Validate arguments against any matching tools.rules.args.
    Violation -> DENY AIP-E002.

6.  Run DLP scan on request arguments.
    block match -> DENY AIP-E008.
    redact match -> replace content, continue.

7.  If action == ask: submit to HITL queue (Section 6.5).
    Approved -> continue to step 8.
    Denied   -> DENY AIP-E015.
    Timed out -> resolve per on_timeout.

8.  ALLOW: forward the call to the tool server.

9.  Receive the tool server response.

10. Run DLP scan on the response.
    block match -> return AIP-E008 to agent, suppress response.
    redact match -> replace content, continue.
]]></artwork>
        <t>
   11. Return the (possibly redacted) response to the agent.</t>
        <t>
   12. Write audit log record (<xref target="sect-6.7" format="default"/>).</t>
      </section>
      <section anchor="sect-6.4" numbered="true" toc="default">
        <name>Decision Outcomes</name>
        <dl newline="false" spacing="normal" indent="8">
          <dt>ALLOW:</dt>
          <dd>
            <t>
	The call passed all checks and was forwarded.  The tool
            </t>
            <t>
	server response was returned to the agent.
            </t>
          </dd>
          <dt>DENY:</dt>
          <dd>
            <t>
	The call was rejected before reaching the tool server.
            </t>
            <t>
	The proxy returns a JSON-RPC 2.0 error (<xref target="sect-7.2" format="default"/>).
           The tool server receives nothing.
            </t>
          </dd>
          <dt>HOLD:</dt>
          <dd>
            <t>
	The call is queued.  The proxy returns a pending response
            </t>
            <t>
	to the agent.  The call is resolved when a human approver
           responds or the HITL timeout is reached.
            </t>
          </dd>
        </dl>
      </section>
      <section anchor="sect-6.5" numbered="true" toc="default">
        <name>Human-in-the-Loop (HITL)</name>
        <t>
   When a call is held, the proxy MUST notify all addresses listed in
   hitl.approvers.  The notification MUST include:</t>
        <ul spacing="normal">
          <li>
            <t>The Agent ID and agent name;</t>
          </li>
          <li>
            <t>The tool name and (post-redaction) arguments;</t>
          </li>
          <li>
            <t>The policy rule that triggered the hold;</t>
          </li>
          <li>
            <t>A unique hold_id.</t>
          </li>
        </ul>
        <t>
   Notification delivery (email, webhook, Slack, web UI) is out of
   scope for this specification.</t>
        <t>
   Approvers submit a decision to the proxy using the HITL API.
   Approval and denial endpoints are:</t>
        <artwork name="" type="" align="left" alt=""><![CDATA[
   POST /v1/hitl/{hold_id}/approve
   POST /v1/hitl/{hold_id}/deny
]]></artwork>
        <t>
   These endpoints MUST be authenticated.  If no response is received
   within hitl.timeout_seconds, the proxy resolves the hold according
   to hitl.on_timeout and writes the outcome to the audit log.</t>
      </section>
      <section anchor="sect-6.6" numbered="true" toc="default">
        <name>Data Loss Prevention (DLP)</name>
        <t>
   The DLP scanner applies the dlp rules from the AgentPolicy to both
   the inbound tool call arguments and the outbound tool server
   response.  Rules are evaluated in the order they are listed.  The
   first matching rule wins.</t>
        <t>
   Implementations SHOULD provide a standard rule library covering
   common sensitive data types:</t>
        <ul spacing="normal">
          <li>
            <t>Cloud provider credentials (AWS, GCP, Azure key patterns);</t>
          </li>
          <li>
            <t>Private key material (PEM headers);</t>
          </li>
          <li>
            <t>Common PII patterns (email, phone, SSN formats);</t>
          </li>
          <li>
            <t>Generic high-entropy secrets (long alphanumeric tokens).</t>
          </li>
        </ul>
      </section>
      <section anchor="sect-6.7" numbered="true" toc="default">
        <name>Audit Logging</name>
        <t>
   The proxy MUST write one log record per tool call outcome.  Records
   MUST be appended to an append-only log and MUST NOT be modified after
   writing.</t>
        <t>
   Log records SHOULD be hash-chained: each record includes the SHA-256
   hash of the previous record, enabling tamper detection.</t>
        <t>
   See <xref target="sect-7.3" format="default"/> for the normative record format.</t>
        <t>
   Log records MUST be retained for a minimum of 90 days.</t>
      </section>
    </section>
    <section anchor="sect-7" numbered="true" toc="default">
      <name>Wire Formats</name>
      <section anchor="sect-7.1" numbered="true" toc="default">
        <name>AIP-Token Header</name>
        <t>
   For HTTP-based tool transports, the AIP Token is conveyed in the
   request header:</t>
        <dl newline="false" spacing="normal" indent="3">
          <dt/>
          <dd>
      AIP-Token: &lt;base64url-encoded UTF-8 JSON token&gt;</dd>
        </dl>
        <t>
   base64url encoding is defined in <xref target="RFC4648" format="default"/> <xref target="sect-5" format="default"/> (no padding).</t>
        <t>
   For MCP stdio transports, the AIP Token is conveyed as a "_aip"
   field at the top level of the JSON-RPC request object:</t>
        <artwork name="" type="" align="left" alt=""><![CDATA[
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "id": 1,
  "params": {
    "name": "read_file",
    "arguments": { "path": "/data/report.txt" }
  },
  "_aip": {
    "aipVersion": "1",
    "agentId": "reg.agentidentityprotocol.io/01933f4a...",
    "tool": "read_file",
    "argumentsHash": "e3b0c44298...",
    "nonce": "a3f8b2c1d4e5f607...",
    "timestamp": "2026-02-24T14:30:00Z",
    "signature": "TUlJQ0lq..."
  }
}
]]></artwork>
      </section>
      <section anchor="sect-7.2" numbered="true" toc="default">
        <name>Error Response Format</name>
        <t>
   Error responses MUST conform to JSON-RPC 2.0 <xref target="JSON-RPC" format="default"/>.
   AIP error codes are in the range -32001 to -32099:</t>
        <artwork name="" type="" align="left" alt=""><![CDATA[
Code     ID        Meaning
------   --------  -----------------------------------------------
-32001   AIP-E001  Tool not in allowlist
-32002   AIP-E002  Argument validation failed
-32003   AIP-E003  Tool unconditionally blocked
-32004   AIP-E004  Nonce replay detected
-32005   AIP-E005  Timestamp out of range
-32008   AIP-E008  DLP violation
-32010   AIP-E010  AIP Token missing
-32011   AIP-E011  Agent ID not found in registry
-32012   AIP-E012  Agent revoked
-32013   AIP-E013  Signature verification failed
-32015   AIP-E015  HITL approval denied
-32016   AIP-E016  HITL timed out
-32099   AIP-E099  Internal proxy error

Example error response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32001,
    "message": "AIP-E001: tool not in allowlist",
    "data": {
      "aipCode": "AIP-E001",
      "agentId": "reg.agentidentityprotocol.io/01933f4a...",
      "tool": "exec_command"
    }
  }
}
]]></artwork>
      </section>
      <section anchor="sect-7.3" numbered="true" toc="default">
        <name>Audit Log Record</name>
        <t>
   Each record is a single JSON object on one line (JSONL <xref target="JSONL" format="default"/>):</t>
        <artwork name="" type="" align="left" alt=""><![CDATA[
{
  "v": 1,
  "ts": "<ISO 8601 UTC>",
  "eventId": "<UUID v4>",
  "prevHash": "<SHA-256 hex of previous record, or null>",
  "decision": "<ALLOW | DENY | HOLD>",
  "errorCode": "<AIP-Exxx or null>",
  "agentId": "<Agent ID>",
  "principalId": "<principal identifier>",
  "tool": "<tool name>",
  "argumentsHash": "<SHA-256 hex>",
  "policyName": "<AgentPolicy agentId value>",
  "verificationStep": "<1-5 or null if passed>",
  "dlp": [
    { "rule": "<rule name>", "scope": "<request|response>",
      "action": "<redacted|blocked>" }
  ],
  "holdId": "<UUID or null>",
  "proxyVersion": "<semver>"
}
]]></artwork>
      </section>
    </section>
    <section anchor="sect-8" numbered="true" toc="default">
      <name>Deployment Topologies</name>
      <section anchor="sect-8.1" numbered="true" toc="default">
        <name>Localhost Proxy</name>
        <t>
   The localhost proxy is the simplest deployment: a single binary
   running on the developer's machine alongside the AI client.  It
   binds to 127.0.0.1:8787 (configurable), supports HTTP and MCP
   stdio interception, and uses a local SQLite database for the nonce
   cache, revocation cache, and audit log.  Policy is loaded from a
   YAML file at ~/.aip/policy.yaml.</t>
        <t>
   This mode is suitable for individual developers and is the
   recommended starting point for adopting AIP.  A Go proxy
   implementation is available at the working group's GitHub
   repository.</t>
      </section>
      <section anchor="sect-8.2" numbered="true" toc="default">
        <name>Kubernetes Sidecar</name>
        <t>
   For production deployments, the AIP Proxy runs as a sidecar
   container in the same pod as the agent container.  Outbound
   tool-server traffic is redirected through the proxy on port 15001
   via iptables REDIRECT rules.  Policy is loaded from a Kubernetes
   ConfigMap or Secret.  Storage uses Redis for the distributed nonce
   cache and a PersistentVolumeClaim for the audit log.  A Prometheus
   metrics endpoint is exposed at /metrics.</t>
        <t>
   Exported metrics include: aip_calls_total, aip_denials_total,
   aip_holds_total, and aip_verification_latency_seconds.</t>
      </section>
      <section anchor="sect-8.3" numbered="true" toc="default">
        <name>Enterprise Federation</name>
        <t>
   In enterprise environments the AIP Proxy integrates with existing
   identity infrastructure:</t>
        <ul spacing="normal">
          <li>
            <t>OIDC mapping:  The registry maintains a table mapping Agent IDs
      to OIDC subject claims.  When a tool server requires an OIDC
      token, the proxy can present one on the agent's behalf after AIP
      verification passes, without the agent holding OIDC credentials
      directly.</t>
          </li>
          <li>
            <t>SPIFFE/mTLS:  The proxy is issued a SPIFFE SVID and uses it to
      establish mTLS connections to tool servers, providing transport-
      layer mutual authentication in addition to AIP application-layer
      identity.</t>
          </li>
          <li>
            <t>Central policy management:  AgentPolicy files are managed via
      a policy API with versioning, rollback, and change auditing,
      rather than local YAML files.</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="sect-9" numbered="true" toc="default">
      <name>Security Considerations</name>
      <section anchor="sect-9.1" numbered="true" toc="default">
        <name>Cryptographic Algorithm</name>
        <t>
   AIP is built with the idea of using Ed25519 <xref target="RFC8032" format="default"/> for all signatures.  Ed25519 was chosen
   because it is fast (sign and verify in under 1ms), produces short
   keys and signatures (32 and 64 bytes respectively), is deterministic
   (no per-signature randomness required), and has broad library support
   across all major languages and platforms. However other cryptographic algorithms should be supported.</t>
        <artwork name="" type="" align="left" alt=""><![CDATA[
All Ed25519 operations MUST use a constant-time
implementation to prevent timing side-channels (Section 9.3).
]]></artwork>
      </section>
      <section anchor="sect-9.2" numbered="true" toc="default">
        <name>Prompt Injection Resistance</name>
        <t>
   The principal threat model for AIP at Layer 2 is the prompt
   injection attack: malicious content in the agent's context causes
   it to attempt tool calls outside its intended scope.</t>
        <t>
   The allowlist in the AgentPolicy prevents the agent from reaching
   tools it was not provisioned for, regardless of what the model
   produces.  The "block" action provides an unconditional deny for
   specified tools that cannot be overridden by any model output,
   injected prompt, or delegation claim.  The proxy operates entirely
   outside the model's trust boundary; the model cannot influence the
   proxy's decisions.</t>
        <artwork name="" type="" align="left" alt=""><![CDATA[
AIP does not protect against:
o  A compromised agent runtime that routes calls around the proxy;
o  Tool servers that accept calls from sources other than the proxy.
]]></artwork>
      </section>
      <section anchor="sect-9.3" numbered="true" toc="default">
        <name>Transport Security</name>
        <t>
   All communication between AIP Proxies and the AIP Registry MUST use
   TLS 1.3 <xref target="RFC8446" format="default"/>.  Server certificates MUST be validated against
   the system trust store.  Certificate pinning is RECOMMENDED for
   registry connections in production deployments.</t>
        <t>
   Proxy-to-tool-server connections MUST use TLS 1.2 <xref target="RFC5246" format="default"/> or
   later.  TLS 1.3 is RECOMMENDED.</t>
      </section>
      <section anchor="sect-9.4" numbered="true" toc="default">
        <name>Private Key Storage</name>
        <t>
   Agent private keys MUST be stored in a secure key store.  In order
   of preference:</t>
        <t>
   1.  Hardware Security Module (HSM) or Trusted Platform Module (TPM);
   2.  OS keychain (macOS Keychain, Windows DPAPI, Linux Secret Service);
   3.  Encrypted file with passphrase derived using Argon2id <xref target="RFC9106" format="default"/>.</t>
        <t>
   Private keys MUST NOT be stored in environment variables, plaintext
   configuration files, or source code repositories.</t>
      </section>
      <section anchor="sect-9.5" numbered="true" toc="default">
        <name>Registry Trust</name>
        <t>
   A proxy MUST be configured with an explicit list of trusted registry
   hostnames and the TLS certificate fingerprint (or CA) for each.
   Agent Records from registries not on this list MUST be rejected.</t>
      </section>
      <section anchor="sect-9.6" numbered="true" toc="default">
        <name>Nonce Cache Sizing</name>
        <t>
   The nonce cache must be large enough to hold all unique nonces
   generated within the TTL window (600 seconds).  Implementations
   MUST use a bounded cache with LRU eviction and MUST NOT silently
   drop old nonces without ensuring they are outside the TTL window.</t>
      </section>
      <section anchor="sect-9.7" numbered="true" toc="default">
        <name>Revocation Latency</name>
        <t>
   The proxy's revocation cache has a maximum refresh interval of
   60 seconds (<xref target="sect-6.1" format="default"/>).  In the worst case, a revoked agent can
   continue making calls for up to 60 seconds after revocation.
   Deployments with stricter requirements SHOULD subscribe to the
   registry's SSE revocation stream (<xref target="sect-5.3" format="default"/>) and invalidate the
   cache on receipt of a revocation event.</t>
      </section>
      <section anchor="sect-9.8" numbered="true" toc="default">
        <name>Denial-of-Service</name>
        <t>
   The proxy adds a small amount of latency to every tool call (one
   cache lookup and one key verification).  To prevent the proxy
   from becoming an availability bottleneck:</t>
        <ul spacing="normal">
          <li>
            <t>Agent Record lookups MUST be served from the local cache except
      on cache miss or invalidation;</t>
          </li>
          <li>
            <t>The proxy SHOULD enforce a per-agent call rate limit to prevent
      a runaway agent from flooding the registry with cache-miss
      lookups.</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="sect-10" numbered="true" toc="default">
      <name>Privacy Considerations</name>
      <section anchor="sect-10.1" numbered="true" toc="default">
        <name>Agent Record Visibility</name>
        <t>
   Agent Records are visible to any party that can query the registry.
   Principals SHOULD use non-identifying agent names for agents that
   handle sensitive workloads.</t>
      </section>
      <section anchor="sect-10.2" numbered="true" toc="default">
        <name>Audit Log Sensitivity</name>
        <t>
   Audit logs contain Agent IDs, tool names, and argument hashes.
   While argument values are not logged in plaintext, the combination
   of Agent ID and tool name may itself be sensitive in some contexts.
   Audit logs MUST be access-controlled appropriately.</t>
      </section>
      <section anchor="sect-10.3" numbered="true" toc="default">
        <name>DLP Redaction</name>
        <t>
   When DLP redaction is applied to a response, the proxy modifies the
   data the agent receives.  Operators MUST ensure that redaction does
   not cause the agent to produce incorrect or harmful downstream
   actions due to missing context.</t>
      </section>
      <section anchor="sect-10.4" numbered="true" toc="default">
        <name>Registry Data Retention</name>
        <t>
   Registry operators MUST publish a data retention policy.  Agent
   Records for revoked agents SHOULD be pseudonymized after the
   minimum retention period required for audit log verification.</t>
      </section>
    </section>
    <section anchor="sect-11" numbered="true" toc="default">
      <name>IANA Considerations</name>
      <section anchor="sect-11.1" numbered="true" toc="default">
        <name>HTTP Header Field</name>
        <t>
   This document defines the "AIP-Token" HTTP header field.  Registration
   is requested in the "Permanent Message Header Field Names" registry
   per <xref target="RFC3864" format="default"/>.  The header field name is "AIP-Token", applicable
   protocol is "http", status is "standard", the author/change
   controller is the IETF, and the specification document is this
   document (<xref target="sect-7.1" format="default"/>).</t>
      </section>
      <section anchor="sect-11.2" numbered="true" toc="default">
        <name>Media Type</name>
        <t>
   The media type "application/aip+json" is requested for AIP Tokens
   serialized as standalone JSON documents.  The type name is
   "application", the subtype name is "aip+json", the required
   parameter is "version" (value "1"), encoding considerations are
   UTF-8, and security considerations are described in <xref target="sect-9" format="default"/>.</t>
      </section>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="RFC8032" target="https://www.rfc-editor.org/info/rfc8032" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8032.xml">
          <front>
            <title>Edwards-Curve Digital Signature Algorithm (EdDSA)</title>
            <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
            <author fullname="I. Liusvaara" initials="I." surname="Liusvaara"/>
            <date month="January" year="2017"/>
            <abstract>
              <t>This document describes elliptic curve signature scheme Edwards-curve Digital Signature Algorithm (EdDSA). The algorithm is instantiated with recommended parameters for the edwards25519 and edwards448 curves. An example implementation and test vectors are provided.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8032"/>
          <seriesInfo name="DOI" value="10.17487/RFC8032"/>
        </reference>
        <reference anchor="RFC8446" target="https://www.rfc-editor.org/info/rfc8446" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8446.xml">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="RFC5246" target="https://www.rfc-editor.org/info/rfc5246" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5246.xml">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.2</title>
            <author fullname="T. Dierks" initials="T." surname="Dierks"/>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2008"/>
            <abstract>
              <t>This document specifies Version 1.2 of the Transport Layer Security (TLS) protocol. The TLS protocol provides communications security over the Internet. The protocol allows client/server applications to communicate in a way that is designed to prevent eavesdropping, tampering, or message forgery. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="5246"/>
          <seriesInfo name="DOI" value="10.17487/RFC5246"/>
        </reference>
        <reference anchor="RFC4648" target="https://www.rfc-editor.org/info/rfc4648" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4648.xml">
          <front>
            <title>The Base16, Base32, and Base64 Data Encodings</title>
            <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
            <date month="October" year="2006"/>
            <abstract>
              <t>This document describes the commonly used base 64, base 32, and base 16 encoding schemes. It also discusses the use of line-feeds in encoded data, use of padding in encoded data, use of non-alphabet characters in encoded data, use of different encoding alphabets, and canonical encodings. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="4648"/>
          <seriesInfo name="DOI" value="10.17487/RFC4648"/>
        </reference>
        <reference anchor="RFC4122" target="https://www.rfc-editor.org/info/rfc4122" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4122.xml">
          <front>
            <title>A Universally Unique IDentifier (UUID) URN Namespace</title>
            <author fullname="P. Leach" initials="P." surname="Leach"/>
            <author fullname="M. Mealling" initials="M." surname="Mealling"/>
            <author fullname="R. Salz" initials="R." surname="Salz"/>
            <date month="July" year="2005"/>
            <abstract>
              <t>This specification defines a Uniform Resource Name namespace for UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDentifier). A UUID is 128 bits long, and can guarantee uniqueness across space and time. UUIDs were originally used in the Apollo Network Computing System and later in the Open Software Foundation\'s (OSF) Distributed Computing Environment (DCE), and then in Microsoft Windows platforms.</t>
              <t>This specification is derived from the DCE specification with the kind permission of the OSF (now known as The Open Group). Information from earlier versions of the DCE specification have been incorporated into this document. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="4122"/>
          <seriesInfo name="DOI" value="10.17487/RFC4122"/>
        </reference>
        <reference anchor="RFC6749" target="https://www.rfc-editor.org/info/rfc6749" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6749.xml">
          <front>
            <title>The OAuth 2.0 Authorization Framework</title>
            <author fullname="D. Hardt" initials="D." role="editor" surname="Hardt"/>
            <date month="October" year="2012"/>
            <abstract>
              <t>The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf. This specification replaces and obsoletes the OAuth 1.0 protocol described in RFC 5849. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="6749"/>
          <seriesInfo name="DOI" value="10.17487/RFC6749"/>
        </reference>
        <reference anchor="RFC9106" target="https://www.rfc-editor.org/info/rfc9106" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9106.xml">
          <front>
            <title>Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications</title>
            <author fullname="A. Biryukov" initials="A." surname="Biryukov"/>
            <author fullname="D. Dinu" initials="D." surname="Dinu"/>
            <author fullname="D. Khovratovich" initials="D." surname="Khovratovich"/>
            <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
            <date month="September" year="2021"/>
            <abstract>
              <t>This document describes the Argon2 memory-hard function for password hashing and proof-of-work applications. We provide an implementer-oriented description with test vectors. The purpose is to simplify adoption of Argon2 for Internet protocols. This document is a product of the Crypto Forum Research Group (CFRG) in the IRTF.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9106"/>
          <seriesInfo name="DOI" value="10.17487/RFC9106"/>
        </reference>
        <reference anchor="JSON-RPC">
          <front>
            <title>JSON-RPC 2.0 Specification</title>
            <author>
              <organization>JSON-RPC Working Group</organization>
            </author>
            <date month="January" year="2013"/>
          </front>
        </reference>
        <reference anchor="RFC3864" target="https://www.rfc-editor.org/info/rfc3864" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3864.xml">
          <front>
            <title>Registration Procedures for Message Header Fields</title>
            <author fullname="G. Klyne" initials="G." surname="Klyne"/>
            <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
            <author fullname="J. Mogul" initials="J." surname="Mogul"/>
            <date month="September" year="2004"/>
            <abstract>
              <t>This specification defines registration procedures for the message header fields used by Internet mail, HTTP, Netnews and other applications. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="90"/>
          <seriesInfo name="RFC" value="3864"/>
          <seriesInfo name="DOI" value="10.17487/RFC3864"/>
        </reference>
      </references>
      <references>
        <name>Informative References</name>
        <reference anchor="MCP">
          <front>
            <title>Model Context Protocol</title>
            <author>
              <organization>Anthropic</organization>
            </author>
            <date month="November" year="2024"/>
          </front>
        </reference>
        <reference anchor="OIDC">
          <front>
            <title>OpenID Connect Core 1.0</title>
            <author>
              <organization>Sakimura, N. et al.</organization>
            </author>
            <date month="November" year="2014"/>
          </front>
        </reference>
        <reference anchor="SPIFFE">
          <front>
            <title>SPIFFE: Secure Production Identity Framework for Everyone</title>
            <author>
              <organization>CNCF SPIFFE Project</organization>
            </author>
            <date year="2024"/>
          </front>
        </reference>
        <reference anchor="JSONL">
          <front>
            <title>JSON Lines</title>
            <author initials="N." surname="Granger" fullname="N. Granger">
	</author>
            <date year="2014"/>
          </front>
        </reference>
      </references>
    </references>
    <section anchor="sect-a" numbered="true" toc="default">
      <name>Example AgentPolicy</name>
      <t>
   A complete AgentPolicy for a research assistant agent.</t>
      <sourcecode name="" type="" markers="true"><![CDATA[

   agentId: reg.agentidentityprotocol.io/01933f4a-9b2c-7d8e-af01
   mode: enforce

   tools:
     - allowed:
       - read_file
       - list_directory
       - web_search
       - git_status
       - write_file
       - create_issue
     - rules:
       - tool: write_file
         action: ask
       - tool: exec_command
         action: block
       - tool: delete_file
         action: block
       - tool: create_issue
         action: ask

   dlp:
     - name: aws-access-key
       regex: "AKIA[A-Z0-9]{16}"
       action: block
       scope: both
     - name: private-key-pem
       regex: "-----BEGIN [A-Z ]* PRIVATE KEY-----"
       action: block
       scope: both
     - name: generic-token
       regex: "[a-zA-Z0-9_\\-]{40,}"
       action: redact
       scope: response

   hitl:
     - approvers:
       - ops@acme.example
     - timeout_seconds: 300  # wait 5 minutes
     - on_timeout: deny

]]></sourcecode>
    </section>
    <section anchor="sect-b" numbered="true" toc="default">
      <name>Example AIP Token</name>
      <t>
   An AIP Token for a read_file call, shown before base64url encoding
   for transport in the AIP-Token header.</t>
      <artwork name="" type="" align="left" alt=""><![CDATA[
{
  "aipVersion": "1",
  "agentId": "reg.agentidentityprotocol.io/01933f4a-9b2c-7d8e-af01",
  "tool": "read_file",
  "argumentsHash": "e3b0c44298fc1c149afb4c8996fb92427ae41e4649b934ca495991b7852b855",
  "nonce": "a3f8b2c1d4e5f607a8b9c0d1e2f3a4b5",
  "timestamp": "2026-02-24T14:30:00Z",
  "signature": "TUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFOQ0E..."
}
]]></artwork>
    </section>
    <section anchor="sect-c" numbered="true" toc="default">
      <name>Error Code Reference</name>
      <dl newline="false" spacing="normal" indent="10">
        <dt>AIP-E001</dt>
        <dd>
          <t>
	Tool not in allowlist
          </t>
          <t>
	The requested tool is not listed in tools.allowed and
             the proxy is in enforce mode.
          </t>
        </dd>
        <dt>AIP-E002</dt>
        <dd>
          <t>
	Argument validation failed
          </t>
          <t>
	A tool argument failed a pattern or maxLength check
             defined in tools.rules.args.
          </t>
        </dd>
        <dt>AIP-E003</dt>
        <dd>
          <t>
	Tool unconditionally blocked
          </t>
          <t>
	The tool has action: block in tools.rules.
          </t>
        </dd>
        <dt>AIP-E004</dt>
        <dd>
          <t>
	Nonce replay
          </t>
          <t>
	The nonce in the AIP Token was already seen within the
             600-second cache window.
          </t>
        </dd>
        <dt>AIP-E005</dt>
        <dd>
          <t>
	Timestamp out of range
          </t>
          <t>
	The token timestamp is more than 300 seconds old or more
             than 30 seconds in the future.
          </t>
        </dd>
        <dt>AIP-E008</dt>
        <dd>
          <t>
	DLP violation
          </t>
          <t>
	A DLP rule with action: block matched content in the
             request or response.
          </t>
        </dd>
        <dt>AIP-E010</dt>
        <dd>
          <t>
	AIP Token missing
          </t>
          <t>
	The tool call arrived with no AIP-Token header or _aip
             field.
          </t>
        </dd>
        <dt>AIP-E011</dt>
        <dd>
          <t>
	Agent ID not found
          </t>
          <t>
	The agentId in the token could not be resolved at the
             registry.
          </t>
        </dd>
        <dt>AIP-E012</dt>
        <dd>
          <t>
	Agent revoked
          </t>
          <t>
	The Agent Record for this agentId has status: revoked.
          </t>
        </dd>
        <dt>AIP-E013</dt>
        <dd>
          <t>
	Signature verification failed
          </t>
          <t>
	The key signature did not verify against the public
             key in the Agent Record.
          </t>
        </dd>
        <dt>AIP-E015</dt>
        <dd>
          <t>
	HITL approval denied
          </t>
          <t>
	A human approver explicitly denied the held call.
          </t>
        </dd>
        <dt>AIP-E016</dt>
        <dd>
          <t>
	HITL timed out
          </t>
          <t>
	The HITL hold expired and on_timeout is set to deny.
          </t>
        </dd>
        <dt>AIP-E099</dt>
        <dd>
          <t>
	Internal proxy error
          </t>
          <t>
	An unexpected error occurred in the proxy.  See proxy
             logs for details.
          </t>
        </dd>
      </dl>
    </section>
  </back>
</rfc>
