<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
]>
<?rfc toc="yes"?>
<?rfc sortrefs="yes"?>
<?rfc symrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="no"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="std"
     docName="draft-nyantakyi-vaip-agent-identity-00"
     ipr="trust200902"
     submissionType="IETF"
     consensus="true"
     version="3">

  <front>
    <title abbrev="VAIP">Vorim Agent Identity Protocol (VAIP)</title>

    <seriesInfo name="Internet-Draft" value="draft-nyantakyi-vaip-agent-identity-00"/>

    <author fullname="Kwame Nyantakyi" initials="K." surname="Nyantakyi">
      <organization>Vorim AI</organization>
      <address>
        <email>kwame@vorim.ai</email>
        <uri>https://vorim.ai</uri>
      </address>
    </author>

    <date year="2026" month="April"/>

    <area>Security</area>
    <workgroup>Independent Submission</workgroup>

    <keyword>AI agents</keyword>
    <keyword>agent identity</keyword>
    <keyword>cryptographic identity</keyword>
    <keyword>audit trail</keyword>
    <keyword>permissions</keyword>
    <keyword>trust scoring</keyword>

    <abstract>
      <t>This document defines the Vorim Agent Identity Protocol (VAIP), a
      standard for establishing verifiable cryptographic identity,
      fine-grained permissions, trust scoring, and tamper-evident audit
      trails for autonomous AI agents.</t>

      <t>As AI agents increasingly perform actions autonomously in enterprise
      systems, existing identity protocols designed for human users or
      static services are insufficient. VAIP addresses this gap by
      providing cryptographic primitives and data structures for issuing,
      verifying, and managing agent identities in multi-tenant
      environments.</t>

      <t>The protocol uses Ed25519 for agent identity, SHA-256 for audit
      integrity, and defines seven hierarchical permission scopes with
      time-bounded grants and rate limiting.</t>
    </abstract>
  </front>

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

      <section anchor="problem-statement">
        <name>Problem Statement</name>
        <t>Autonomous AI agents are increasingly deployed to perform real-world
        tasks: executing code, sending messages, making financial
        transactions, and accessing sensitive resources. Unlike human users,
        agents lack a standardised identity layer. There is no widely
        adopted protocol for answering fundamental questions about an agent:</t>
        <ul>
          <li>Who is this agent? (Identity)</li>
          <li>What is it allowed to do? (Permissions)</li>
          <li>What has it done? (Audit)</li>
          <li>Should I trust it? (Trust)</li>
        </ul>
        <t>Existing identity systems (OAuth 2.0, API keys, X.509 certificates)
        were designed for human users or static services. They do not
        address the unique requirements of autonomous agents that act
        independently, accumulate behavioural history, and require dynamic
        trust assessment.</t>
        <t>Non-human identities outnumber human identities by approximately 50:1
        in the average enterprise, yet no standardised infrastructure exists
        for managing them.</t>
      </section>

      <section anchor="design-principles">
        <name>Design Principles</name>
        <ol>
          <li>Cryptographic verifiability: Every identity claim MUST be
          verifiable through public key cryptography without relying on a
          central authority at verification time.</li>
          <li>Minimal trust: Private keys are generated once and never stored
          by the issuing system. The agent or its operator is the sole
          custodian of its private key.</li>
          <li>Auditability: Every action performed by an agent MUST be logged
          in a tamper-evident ledger. Audit records MUST support
          independent integrity verification.</li>
          <li>Interoperability: The protocol uses widely supported cryptographic
          standards (Ed25519, SHA-256) and data formats (JSON, PEM) to
          enable cross-platform verification.</li>
          <li>Multi-tenancy: All identities, permissions, and audit records are
          scoped to an organisation. No data leaks across tenants.</li>
        </ol>
      </section>

      <section anchor="terminology">
        <name>Terminology</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"/> when, and only when, they appear in all
        capitals, as shown here.</t>
        <dl>
          <dt>Agent</dt>
          <dd>An autonomous software entity that performs actions on behalf of
          an organisation.</dd>
          <dt>Organisation</dt>
          <dd>A tenant entity that owns and manages agents.</dd>
          <dt>Operator</dt>
          <dd>A human user who registers and configures agents within an
          organisation.</dd>
          <dt>Scope</dt>
          <dd>A named permission that authorises a specific category of action.</dd>
          <dt>Trust Score</dt>
          <dd>A numeric assessment (0-100) of an agent's reliability based on
          behavioural history.</dd>
          <dt>Audit Event</dt>
          <dd>An immutable record of an action performed by or on behalf of an agent.</dd>
        </dl>
      </section>
    </section>

    <section anchor="agent-identity">
      <name>Agent Identity</name>

      <section anchor="identity-format">
        <name>Identity Format</name>
        <t>Every agent MUST be assigned a unique agent identifier upon
        registration. The identifier follows this format:</t>
        <artwork><![CDATA[
agid_{org_slug}_{random}
]]></artwork>
        <t>Where:</t>
        <ul>
          <li>"agid_" is a fixed prefix identifying the string as a VAIP agent identifier</li>
          <li>{org_slug} is a truncated (up to 8 characters) alphanumeric slug identifying the owning organisation</li>
          <li>{random} is a cryptographically random string (8 characters, derived from UUID v4)</li>
        </ul>
        <t>Example: agid_acme_a1b2c3d4</t>
        <t>Agent identifiers MUST be globally unique and MUST NOT be reused after revocation.</t>
      </section>

      <section anchor="keypair-generation">
        <name>Keypair Generation</name>
        <t>Each agent MUST be assigned an Ed25519 <xref target="RFC8032"/> keypair at
        registration time. Ed25519 was chosen for the following properties:</t>
        <ul>
          <li>128-bit security level</li>
          <li>Fast key generation, signing, and verification</li>
          <li>Small key and signature sizes (32-byte public keys, 64-byte signatures)</li>
          <li>Deterministic signatures (no nonce reuse vulnerabilities)</li>
          <li>Resistance to timing attacks</li>
        </ul>
        <t>The keypair MUST be generated as follows:</t>
        <ol>
          <li>Generate an Ed25519 keypair using the system's cryptographic random number generator</li>
          <li>Encode the public key in SPKI/PEM format</li>
          <li>Encode the private key in PKCS#8/PEM format</li>
          <li>Compute the key fingerprint</li>
          <li>Return the private key to the operator exactly once</li>
          <li>Store the public key and fingerprint; never store the private key</li>
        </ol>
      </section>

      <section anchor="key-fingerprint">
        <name>Key Fingerprint</name>
        <t>A key fingerprint is a SHA-256 <xref target="RFC6234"/> hash of the PEM-encoded
        public key, represented as a hexadecimal string (64 characters):</t>
        <artwork><![CDATA[
fingerprint = SHA-256(public_key_pem)[0:64]
]]></artwork>
        <t>The fingerprint serves as a compact, verifiable reference to an
        agent's identity. It MUST be included in trust verification
        responses and MAY be used for identity comparison without
        transmitting the full public key.</t>
      </section>

      <section anchor="agent-lifecycle">
        <name>Agent Lifecycle</name>
        <t>An agent MUST exist in exactly one of the following states at any time:</t>
        <ul>
          <li>pending: Registered but not yet activated</li>
          <li>active: Fully operational, permissions enforceable</li>
          <li>suspended: Temporarily disabled, can be reactivated</li>
          <li>revoked: Permanently disabled, cannot be reactivated</li>
          <li>expired: Past its expiration timestamp</li>
        </ul>
        <t>A revoked agent MUST NOT be reactivated. Its identifier MUST NOT be reused.</t>
      </section>

      <section anchor="key-rotation">
        <name>Key Rotation</name>
        <t>An agent's keypair MAY be rotated by revoking the current agent and
        registering a new agent with the same metadata. The new agent MUST
        receive a new agent_id and keypair.</t>
      </section>
    </section>

    <section anchor="permission-model">
      <name>Permission Model</name>

      <section anchor="scopes">
        <name>Scopes</name>
        <t>VAIP defines seven permission scopes. Each scope authorises a category of agent actions:</t>
        <table>
          <thead>
            <tr><th>Scope</th><th>Identifier</th><th>Risk Level</th></tr>
          </thead>
          <tbody>
            <tr><td>Read</td><td>agent:read</td><td>Low</td></tr>
            <tr><td>Write</td><td>agent:write</td><td>Medium</td></tr>
            <tr><td>Execute</td><td>agent:execute</td><td>Medium</td></tr>
            <tr><td>Transact</td><td>agent:transact</td><td>High</td></tr>
            <tr><td>Communicate</td><td>agent:communicate</td><td>Medium</td></tr>
            <tr><td>Delegate</td><td>agent:delegate</td><td>High</td></tr>
            <tr><td>Elevate</td><td>agent:elevate</td><td>Critical</td></tr>
          </tbody>
        </table>
        <t>Scopes are not hierarchical by default. Possessing agent:write does
        not imply agent:read. Each scope MUST be granted independently.</t>
      </section>

      <section anchor="permission-grants">
        <name>Permission Grants</name>
        <t>A permission grant binds a scope to an agent with optional constraints including:</t>
        <ul>
          <li>valid_from: When the grant becomes effective</li>
          <li>valid_until: Optional expiration time</li>
          <li>rate_limit: Maximum uses within a time window</li>
          <li>conditions: Additional constraints (e.g., IP allowlists)</li>
        </ul>
      </section>

      <section anchor="rate-limits">
        <name>Rate Limits</name>
        <t>A rate limit constrains how frequently a scope can be exercised:</t>
        <artwork><![CDATA[
{ "max": 1000, "window": "1h" }
]]></artwork>
        <t>Supported windows: "1m" (minute), "1h" (hour), "1d" (day).</t>
        <t>When an agent exceeds its rate limit, permission checks MUST return
        denied with reason RATE_LIMIT_EXCEEDED.</t>
      </section>

      <section anchor="permission-check-flow">
        <name>Permission Check Flow</name>
        <t>When an agent requests to perform an action, the system MUST:</t>
        <ol>
          <li>Validate agent_id exists and status is active</li>
          <li>Check cache for recent permission decision</li>
          <li>If cache miss: query grants, filter by validity and revocation, evaluate rate limits and conditions</li>
          <li>Cache the decision (RECOMMENDED TTL: 300 seconds)</li>
          <li>Return the permission check result</li>
        </ol>
        <t>Valid denial reasons: AGENT_NOT_FOUND, AGENT_NOT_ACTIVE,
        SCOPE_NOT_GRANTED, GRANT_EXPIRED, RATE_LIMIT_EXCEEDED,
        CONDITION_NOT_MET.</t>
      </section>
    </section>

    <section anchor="audit-trail">
      <name>Audit Trail</name>

      <section anchor="event-schema">
        <name>Event Schema</name>
        <t>Every auditable action MUST produce an audit event including:</t>
        <ul>
          <li>event_id: Unique, time-sortable identifier (e.g., ULID)</li>
          <li>agent_id: Agent that performed the action</li>
          <li>org_id: Organisation context</li>
          <li>event_type: Category (tool_call, api_request, message_sent, permission_change, status_change, key_rotation)</li>
          <li>action: Specific action performed</li>
          <li>result: Outcome (success, denied, error)</li>
          <li>timestamp: ISO 8601 timestamp</li>
        </ul>
        <t>Optional fields include resource, input_hash, output_hash, permission, latency_ms, error_code, signature, and metadata.</t>
      </section>

      <section anchor="hash-format">
        <name>Hash Format</name>
        <t>All hashes in audit events MUST use the format:</t>
        <artwork><![CDATA[
sha256:{hex_digest}
]]></artwork>
        <t>Where {hex_digest} is the lowercase hexadecimal representation of the SHA-256 hash.</t>
      </section>

      <section anchor="event-signatures">
        <name>Event Signatures</name>
        <t>Audit events MAY be signed by the agent that produced them. When present,
        the signature field MUST contain an Ed25519 signature of the canonical
        JSON <xref target="RFC8259"/> representation of the event (excluding the
        signature field itself), encoded as:</t>
        <artwork><![CDATA[
ed25519:{base64_signature}
]]></artwork>
      </section>

      <section anchor="immutability">
        <name>Immutability</name>
        <t>Audit events MUST be append-only. Once written, an event MUST NOT be
        modified or deleted except by automated retention policies.</t>
      </section>

      <section anchor="signed-audit-bundles">
        <name>Signed Audit Bundles</name>
        <t>Conforming systems MUST support exporting audit events as signed bundles.
        A bundle contains the events array, event count, time range, organisation
        identifier, and a manifest field containing a SHA-256 hash of the
        JSON-serialised events array.</t>
        <t>Any modification to any event produces a different manifest hash,
        making tampering detectable.</t>
      </section>
    </section>

    <section anchor="trust-scoring">
      <name>Trust Scoring</name>

      <section anchor="trust-overview">
        <name>Overview</name>
        <t>Trust scoring provides a quantitative assessment of an agent's
        reliability. The score is a number from 0 to 100, computed from
        multiple behavioural and configuration factors. Trust scores are
        dynamic, public, and composite.</t>
      </section>

      <section anchor="scoring-algorithm">
        <name>Scoring Algorithm</name>
        <t>The trust score is computed as:</t>
        <artwork><![CDATA[
score = base_score + status_factor + age_factor
        + success_rate_factor - denial_penalty
        - scope_breadth_penalty
]]></artwork>
        <t>Base score: 50. Status factor: active (+10), suspended (-20),
        revoked (score fixed at 0). Age factor: >90 days (+15), >30 days
        (+10), >7 days (+5). Success rate factor: round(success_rate * 15)
        over trailing 30-day window. Denial penalty: -10 if denied_count
        exceeds 10% of total events. Scope breadth penalty: -5 if agent
        holds more than 5 active scopes. Final score clamped to [0, 100].</t>
      </section>

      <section anchor="trust-verification">
        <name>Trust Verification</name>
        <t>Conforming implementations MUST provide a public, unauthenticated
        endpoint for trust verification. The response includes agent_id,
        verification status, trust score, active scopes, key fingerprint,
        and revocation status.</t>
      </section>

      <section anchor="trust-badges">
        <name>Trust Badges</name>
        <t>Conforming implementations SHOULD provide embeddable SVG trust badges
        displaying protocol name, verification status, and trust score with
        colour coding: green (80-100), amber (50-79), red (0-49).</t>
      </section>
    </section>

    <section anchor="conformance-levels">
      <name>Conformance Levels</name>
      <t>Implementations MAY conform to one or more levels:</t>
      <dl>
        <dt>Level 1 - Identity</dt>
        <dd>Agent registration with Ed25519 keypairs, key fingerprints, lifecycle management.</dd>
        <dt>Level 2 - Permissions</dt>
        <dd>Level 1 plus seven permission scopes, time-bounded grants, rate limiting, cached permission checks.</dd>
        <dt>Level 3 - Audit</dt>
        <dd>Level 2 plus audit event ingestion, schema compliance, SHA-256 hashing, event query with filtering.</dd>
        <dt>Level 4 - Trust</dt>
        <dd>Level 3 plus trust score computation, public verification endpoint, embeddable trust badges.</dd>
        <dt>Level 5 - Full Conformance</dt>
        <dd>Level 4 plus signed audit bundle export, Ed25519 event signatures, multi-format export, API key management.</dd>
      </dl>
    </section>

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

      <section anchor="cryptographic-choices">
        <name>Cryptographic Choices</name>
        <table>
          <thead>
            <tr><th>Primitive</th><th>Algorithm</th><th>Rationale</th></tr>
          </thead>
          <tbody>
            <tr><td>Agent identity</td><td>Ed25519</td><td>Fast, compact, timing-attack resistant</td></tr>
            <tr><td>Fingerprints</td><td>SHA-256</td><td>Widely supported, collision resistant</td></tr>
            <tr><td>Audit integrity</td><td>SHA-256</td><td>Industry standard for data integrity</td></tr>
            <tr><td>Password hashing</td><td>bcrypt (cost 12)</td><td>Memory-hard, adjustable work factor</td></tr>
            <tr><td>API key storage</td><td>SHA-256</td><td>One-way hashing for stored secrets</td></tr>
          </tbody>
        </table>
      </section>

      <section anchor="private-key-handling">
        <name>Private Key Handling</name>
        <t>Conforming implementations:</t>
        <ul>
          <li>MUST generate private keys server-side using a cryptographic random number generator</li>
          <li>MUST return the private key to the operator exactly once</li>
          <li>MUST NOT store, log, or persist the private key after returning it</li>
          <li>MUST NOT transmit private keys over unencrypted channels</li>
        </ul>
      </section>

      <section anchor="multi-tenant-isolation">
        <name>Multi-Tenant Isolation</name>
        <t>All database queries MUST be scoped to the authenticated organisation's
        identifier. No agent, permission, or audit record from one organisation
        may be accessible by another.</t>
      </section>

      <section anchor="transport-security">
        <name>Transport Security</name>
        <t>All API communications MUST use TLS 1.2 or higher. TLS 1.3 is RECOMMENDED.</t>
      </section>

      <section anchor="threat-model">
        <name>Threat Model</name>
        <table>
          <thead>
            <tr><th>Threat</th><th>Mitigation</th></tr>
          </thead>
          <tbody>
            <tr><td>Key compromise</td><td>Immediate revocation, new registration</td></tr>
            <tr><td>Audit tampering</td><td>SHA-256 manifest, append-only storage</td></tr>
            <tr><td>Cross-tenant access</td><td>Organisation-scoped queries</td></tr>
            <tr><td>Replay attacks</td><td>Time-sortable event IDs, timestamp validation</td></tr>
            <tr><td>Brute-force auth</td><td>bcrypt hashing, API key entropy (192 bits)</td></tr>
            <tr><td>Trust manipulation</td><td>Score from audited behaviour, not self-reported</td></tr>
          </tbody>
        </table>
      </section>
    </section>

    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document requests the registration of the following media type:</t>
      <dl>
        <dt>Type name</dt><dd>application</dd>
        <dt>Subtype name</dt><dd>vaip+json</dd>
        <dt>Required parameters</dt><dd>none</dd>
        <dt>Optional parameters</dt><dd>none</dd>
        <dt>Encoding considerations</dt><dd>binary (UTF-8 JSON)</dd>
        <dt>Security considerations</dt><dd>See the Security Considerations section of this document.</dd>
        <dt>Interoperability considerations</dt><dd>Implementations MUST support JSON encoding as defined in RFC 8259.</dd>
        <dt>Published specification</dt><dd>This document.</dd>
        <dt>Applications that use this media type</dt><dd>AI agent identity management systems, audit trail systems, trust verification services.</dd>
      </dl>
    </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 fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
        </reference>

        <reference anchor="RFC8032" target="https://www.rfc-editor.org/info/rfc8032">
          <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"/>
          </front>
          <seriesInfo name="RFC" value="8032"/>
        </reference>

        <reference anchor="RFC6234" target="https://www.rfc-editor.org/info/rfc6234">
          <front>
            <title>US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)</title>
            <author fullname="D. Eastlake 3rd" initials="D." surname="Eastlake"/>
            <author fullname="T. Hansen" initials="T." surname="Hansen"/>
            <date month="May" year="2011"/>
          </front>
          <seriesInfo name="RFC" value="6234"/>
        </reference>

        <reference anchor="RFC8259" target="https://www.rfc-editor.org/info/rfc8259">
          <front>
            <title>The JavaScript Object Notation (JSON) Data Interchange Format</title>
            <author fullname="T. Bray" initials="T." surname="Bray"/>
            <date month="December" year="2017"/>
          </front>
          <seriesInfo name="RFC" value="8259"/>
        </reference>
      </references>

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

        <reference anchor="RFC6749" target="https://www.rfc-editor.org/info/rfc6749">
          <front>
            <title>The OAuth 2.0 Authorization Framework</title>
            <author fullname="D. Hardt" initials="D." surname="Hardt"/>
            <date month="October" year="2012"/>
          </front>
          <seriesInfo name="RFC" value="6749"/>
        </reference>

        <reference anchor="RFC5280" target="https://www.rfc-editor.org/info/rfc5280">
          <front>
            <title>Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile</title>
            <author fullname="D. Cooper" initials="D." surname="Cooper"/>
            <author fullname="S. Santesson" initials="S." surname="Santesson"/>
            <author fullname="S. Farrell" initials="S." surname="Farrell"/>
            <author fullname="S. Boeyen" initials="S." surname="Boeyen"/>
            <author fullname="R. Housley" initials="R." surname="Housley"/>
            <author fullname="W. Polk" initials="W." surname="Polk"/>
            <date month="May" year="2008"/>
          </front>
          <seriesInfo name="RFC" value="5280"/>
        </reference>
      </references>
    </references>

    <section anchor="reference-implementation">
      <name>Reference Implementation</name>
      <t>A reference implementation of VAIP is available at:</t>
      <ul>
        <li>TypeScript SDK: https://www.npmjs.com/package/@vorim/sdk</li>
        <li>Python SDK: https://pypi.org/project/vorim/</li>
        <li>Protocol specification: https://github.com/Kzino/vorim-protocol</li>
        <li>MCP Server: https://www.npmjs.com/package/@vorim/mcp-server</li>
      </ul>
    </section>

    <section anchor="existing-standards">
      <name>Relationship to Existing Standards</name>
      <t>VAIP is designed to complement, not replace, existing identity and security standards:</t>
      <dl>
        <dt>OAuth 2.0 (RFC 6749)</dt>
        <dd>OAuth focuses on delegated authorisation for human users. VAIP extends the concept to autonomous agents that act independently without human-in-the-loop authorisation.</dd>
        <dt>W3C Decentralized Identifiers (DID)</dt>
        <dd>VAIP agent identifiers could be extended to DID format for decentralised resolution. The current format prioritises simplicity and readability.</dd>
        <dt>SPIFFE</dt>
        <dd>SPIFFE provides workload identity attestation. VAIP adds trust scoring, audit trails, and permission models beyond identity.</dd>
        <dt>X.509 (RFC 5280)</dt>
        <dd>VAIP uses Ed25519 directly rather than certificate chains, prioritising simplicity and agent-specific semantics over PKI hierarchies.</dd>
      </dl>
    </section>

    <section anchor="regulatory-alignment">
      <name>Regulatory Alignment</name>
      <t>VAIP's identity, permission, and audit features support compliance with emerging AI governance frameworks including:</t>
      <ul>
        <li>EU AI Act (enforced August 2025): Traceability and audit trail requirements for high-risk AI systems.</li>
        <li>US Executive Order on AI (EO 14110): Risk management, transparency, and accountability for AI systems.</li>
        <li>Colorado AI Act: Automated decision-making documentation requirements.</li>
        <li>NIST AI Risk Management Framework: AI system governance and accountability controls.</li>
      </ul>
    </section>

    <section anchor="acknowledgements">
      <name>Acknowledgements</name>
      <t>The author thanks the open-source community and early adopters of
      the Vorim Agent Identity Protocol for their feedback and
      contributions to this specification.</t>
    </section>
  </back>
</rfc>
