bankee.ai
Protocol Layer
Protocol LayerDIF TAAWGKYA-OS v1.0

KYA-OS in production: how we gave AI agents a cryptographic identity

KYA-OS is the DIF TAAWG protocol that gives every AI agent a verifiable identity, a delegation chain, and a tamper-evident audit trail. We built a complete 4-service payment infrastructure on it, deployed it live, and verified every step. This is how it works and what it proves.

JC
Jonathan Chapman
Co-founder, Bankee · jonathan@bankee.ai5 June 2026
bankee-ai/bankee-kya-os bankee.ai/.well-known/did.json

The problem: agents making payments are cryptographically anonymous

When an AI agent calls a payment tool today, the payment system receives a request authenticated by an API key. It knows the request came from a client. It does not know which agent, acting on whose behalf, under what authority, within what scope. If something goes wrong — an overspend, an erroneous payment, a compliance audit — there is no cryptographic chain of evidence.

This is the agent identity gap. Traditional payment authorization is built around human identity: a card requires physical possession, open banking requires SCA with a bank. As AI agents become economic actors — spending money, executing contracts, managing subscriptions — the same question applies: who, exactly, is doing this?

KYC for agents
AML/KYC regulations require financial institutions to know their customers. As agents become autonomous payment initiators, the same logic applies at the infrastructure level: know your agent — not just which company owns the API key, but which specific agent, acting under what chain of human authority, executed this specific transaction. KYA-OS is the protocol that makes this possible.

What KYA-OS provides: three primitives

KYA-OS (Know Your Agent Operating System) is an open standard from the DIF Trust and Agent Authorization Working Group. It describes itself as analogous to TLS: not a transport, but a security layer that transports embed. It does three distinct things:

Identity
did:web:bankee.ai

Every agent holds an Ed25519 key pair encoded as a Decentralized Identifier. Stable, self-certifying, resolvable over HTTPS. No central registry.

Authority
W3C Verifiable Credentials

Delegation chains root at a Responsible Party. Each hop narrows scope. High-risk tools are gated by consent — a human must issue a signed VC before the tool runs.

Accountability
Detached JWS proofs

Every tool response carries a JSON Web Signature over the SHA-256 hashes of the request and response. Invisible to the LLM. Verifiable by anyone with the public key.

The key insight is that all three work together. A proof without identity is useless — you cannot verify who signed it. Identity without accountability is insufficient — you know who the agent is but not what it did. Accountability without authority is incomplete — you have a record but no proof the agent was permitted to act. KYA-OS binds all three into a single, verifiable chain.

The architecture: four services, one identity

We built a complete end-to-end implementation as four Docker services running in the Bankee.ai dev environment. All four services share a single persistent identity: did:web:bankee.ai.

Bankee KYA-OS — 4-service architecture · Bankee.ai dev environment
Payment MCP Server
Tools + KYA-OS proofs
:3001
Consent Service
VC issuance + StatusList2021
:3002
Audit Service
Proof records + verification
:3003
Web UI
Management dashboard
:3010
📡 MCP over SSE / Streamable HTTP🔏 Proof webhook → audit🔑 VC issuance → payment server🌐 bankee-net + openclaw-net

The payment server is the MCP-facing surface: it exposes five payment tools, wraps every response with a KYA-OS proof, and gates high-value operations behind a consent check. The consent service acts as the Responsible Party — it issues W3C Verifiable Credentials when a human approves a request, maintains a StatusList2021 revocation list, and supports multi-hop sub-delegation. The audit service records every proof from the payment server and can verify any proof offline using a pre-loaded trusted key cache. The web UI aggregates all three into a management dashboard at port 3010 on the Tailscale network.

The identity is anchored at bankee.ai/.well-known/did.json — a standard W3C DID document containing the Ed25519 public key in both multibase and JWK formats. Any external party can resolve this DID, retrieve the public key over HTTPS, and independently verify any proof or credential produced by this infrastructure.

What a proof looks like — and what it proves

Every tool response from the payment server carries a detached JWS proof in the _meta field. The language model never sees it — it lives in the metadata envelope, not the tool content. Here is the structure:

proof structure · JSON
// Attached to every tool response in _meta.proof
{
  "jws": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDp3ZWI6YmFua2VlLmFpI2tleS0xIn0
          ..MEUCIByz1mP8v3kNqS7xA2R4pDf9cQeYW6nR5KtLvMoXs8UcAiEA3j5Q...",

  "meta": {
    "did":          "did:web:bankee.ai",          // who signed
    "kid":          "did:web:bankee.ai#key-1",    // which key
    "ts":            1780657765,                  // unix timestamp
    "nonce":        "xK9mP2rTvW...",             // anti-replay
    "sessionId":    "kyaos_39e5b35c-f1b8-43e3-8ed4-bdf0617a817d",
    "requestHash":  "sha256:c66cf361137f40cf8b506cd...",  // what was asked
    "responseHash": "sha256:f9e1a5316cc6abf511f3c82..."   // what was answered
  }
}

The jws is a detached JSON Web Signature. The signing input is header.payload where the payload is the canonical form of the meta object. The signature is produced with the Ed25519 private key corresponding to did:web:bankee.ai#key-1. To verify: resolve the DID, extract the public key, reconstruct the canonical payload, check the signature. Any party in the world can do this — no callback to Bankee required.

The requestHash and responseHash bind the proof to the specific tool call. If an attacker intercepts the proof and replays it with a different response, the hash mismatch will be detected. The nonce prevents replay of the proof itself — each nonce is stored in a cache and rejected if seen again.

What a Verifiable Credential looks like — and what it authorises

Some tools should not run without a human saying yes. create_payment above £100 is wrapped with wrapWithDelegation. Without a valid delegation credential, the agent receives a structured refusal — not an error, but a specific needs_authorization response with a consent URL:

step 5 — consent gate fires · terminal output
  ⚠  Payment blocked: needs_authorization
  ℹ  Consent URL: /consent?tool=create_payment
                          &scopes=payments%3Awrite
                          &agent_did=did%3Aweb%3Abankee.ai
                          &resume_token=3bc697c0-61b6-5436-7901-6106db18362e
  ℹ  Resume token: 3bc697c0-61b6-5436-7901-6106db18362e
  🔏 Proof attached: did:web:bankee.ai  (even refusals are signed)

The human navigates to the consent URL, reviews the request, and approves. The consent service issues a W3C Verifiable Credential:

delegation VC · JSON
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/kya-os/v1"
  ],
  "id": "delegation-1780657765174-647rnk",
  "type": ["VerifiableCredential", "DelegationCredential"],
  "issuer": "did:web:bankee.ai",           // Responsible Party signs
  "issuanceDate": "2026-06-05T11:09:25Z",
  "credentialSubject": {
    "id": "did:web:bankee.ai",             // subject: the agent
    "scopes": ["payments:write"],          // what it's allowed to do
    "notAfter": 1780661365                 // expires in 1 hour
  },
  "credentialStatus": {
    "type": "StatusList2021Entry",
    "statusListIndex": "0",               // bit 0 in the revocation list
    "statusListCredential":
      "https://bankee.ai/api/status-list"
  },
  "proof": {
    "type": "Ed25519Signature2020",
    "verificationMethod": "did:web:bankee.ai#key-1",
    "proofValue": "z5k2Zr4bVe..."         // signed by Responsible Party
  }
}

The VC is stored on the payment server under the resume_token. When the agent retries, the server auto-applies the delegation. The tool executes. The response carries a proof that references the VC — binding identity, authority, and the specific action into a single, non-repudiable record. The credentialStatus field means the VC can be revoked at any time by flipping bit 0 in the StatusList2021 revocation list. Anyone checking revocation fetches the compressed bitstring from the statusListCredential URL and checks the bit — no need to contact the issuer.

The live demo: 11 steps, all verified

We ran the full end-to-end demo against the live Bankee.ai infrastructure. Here is the unedited output, with annotations on what each step proves.

Steps 0–1: Services ready, identity confirmed, session established

step 0–1 · terminal
━━━━ Step 0: Waiting for services ━━━━━━━━━━━━━━━━━━━━━━━
  ✓ Payment server is ready
  ✓ Consent service is ready
  ✓ Audit service is ready
  ℹ Payment server DID: did:web:bankee.ai      ← resolvable at bankee.ai
  ℹ High-value threshold: £100.00

━━━━ Step 1: Connect MCP client + KYA-OS handshake ━━━━━━
  → Connecting to payment server via SSE…
  ✓ Connected via SSE transport
  → Performing KYA-OS session handshake…
  ✓ KYA-OS session handshake complete

The handshake establishes a KYA-OS session: the client sends a nonce, a timestamp, and the server's expected DID. The server validates all three — timestamp within ±120 seconds, nonce not previously seen, audience matches its own DID — and returns a session ID. This session ID is included in every subsequent proof, binding all tool calls to a single authenticated session and preventing cross-session replay.

Steps 2–3: Proof-only tools — every response is signed

step 2–3 · terminal
━━━━ Step 2: get_balance (proof only) ━━━━━━━━━━━━━━━━━━━
  ✓ Balance: £1250.00 available, £32.00 pending
  🔏 Proof attached:
    DID:      did:web:bankee.ai
    Session:  kyaos_39e5b35c-f1b8-43e3-8ed4-bdf0617a817d
    Req hash: sha256:c66cf361137f40cf8b506cd…
    Res hash: sha256:f9e1a5316cc6abf511f3c82…

━━━━ Step 3: get_exchange_rate (proof only) ━━━━━━━━━━━━━
  ✓ GBP/USDC rate: 1.265
  🔏 Proof attached:
    DID:      did:web:bankee.ai
    Session:  kyaos_39e5b35c-f1b8-43e3-8ed4-bdf0617a817d
    Req hash: sha256:6aa288e279f69e3a60e1cec…
    Res hash: sha256:38edf94ff7397e14f8baa58…

These tools require no delegation — they carry only proof. The proof binds the specific question asked (requestHash) and the specific answer given (responseHash) to the server's DID and session. If either is tampered with in transit, the hashes will not match. The LLM sees only the tool result; the infrastructure sees the cryptographic receipt.

Step 4: Autonomous payment — below the consent threshold

step 4 · terminal
━━━━ Step 4: create_payment £50 (autonomous) ━━━━━━━━━━━━
  → Creating £50 payment — no consent required…
  ✓ Payment created: pay_1780657765156_ytmgzs
  ✓ Status: completed | Amount: £50.00
  ✓ Agent DID in payment record: did:web:bankee.ai
  🔏 Proof attached:
    DID:      did:web:bankee.ai
    Session:  kyaos_39e5b35c-f1b8-43e3-8ed4-bdf0617a817d
    Req hash: sha256:4712d4c3b1e677971d8df38…
    Res hash: sha256:26e53eb2887d6e8758bb989…

The £50 payment is below the £100 high-value threshold. It executes autonomously — no consent required. Notice that did:web:bankee.ai is recorded directly in the payment record as the agent DID. Any downstream AML system can trace this payment back to the identity, verify the signature, and confirm the request/response integrity — all without calling Bankee.

Steps 5–7: Consent gate, VC issuance, and retry

steps 5–7 · terminal
━━━━ Step 5: create_payment £500 (high-value) ━━━━━━━━━━━
  → Attempting £500 payment — expecting needs_authorization…
  ⚠  Payment blocked: needs_authorization
  ℹ  Resume token: 3bc697c0-61b6-5436-7901-6106db18362e
  🔏 Proof attached (even the refusal is signed)

━━━━ Step 6: Human approves via consent service ━━━━━━━━━
  → Operator approving payment via consent service API…
  ✓ Delegation VC issued: delegation-1780657765174-647rnk
  ✓ Issuer DID:   did:web:bankee.ai   ← Responsible Party signed
  ✓ Subject DID:  did:web:bankee.ai   ← agent granted authority

━━━━ Step 7: Retry create_payment £500 (VC auto-applied) ━
  → Retrying — delegation VC now stored on server…
  ✓ Payment executed
  🔏 Proof attached:
    DID:     did:web:bankee.ai
    Session: kyaos_39e5b35c-f1b8-43e3-8ed4-bdf0617a817d

Three things happen in sequence: the gate fires, a human explicitly approves, a credential is issued, and the credential is automatically applied on retry. The delegation VC is stored on the payment server under the resume_token. On retry, the server checks for a stored VC matching the agent's session, verifies it is signed by the trusted Responsible Party DID, checks the scope and expiry, and permits the tool to execute. The response proof then references the delegation chain — creating a complete, verifiable audit record: who asked → who authorised → what was done.

Steps 8–10: Status, history, and the audit trail

steps 8–10 · terminal
━━━━ Step 8: get_payment_status (proof only) ━━━━━━━━━━━━
  ✓ Payment pay_1780657765156_ytmgzs: completed
  🔏 Proof: did:web:bankee.ai — session kyaos_39e5b35c…

━━━━ Step 9: list_payments (proof only) ━━━━━━━━━━━━━━━━━
  ✓ Total payments: 4
  ℹ  pay_1780655758815_cwkygb — £50.00 GBP — completed
  ℹ  pay_1780656088916_kpvjzg — £50.00 GBP — completed
  ℹ  pay_1780656387431_shte2e — £50.00 GBP — completed
  ℹ  pay_1780657765156_ytmgzs — £50.00 GBP — completed
  🔏 Proof: did:web:bankee.ai — session kyaos_39e5b35c…

━━━━ Step 10: Query audit service — full proof trail ━━━━━
  ✓ Audit records on file: 2
  ℹ  create_payment   DID: did:web:bankee.ai…   scope: -  ✓ verified
  ℹ  create_payment   DID: did:web:bankee.ai…   scope: -  ✓ verified

Every tool call generates a proof record that is forwarded to the audit service via webhook. Records are append-only and immediately verified on receipt. The audit service uses a pre-loaded trusted key cache — it holds did:web:bankee.ai's Ed25519 public key locally, so it can verify proofs without any outbound network call.

Step 11: Cryptographic proof verification — the final confirmation

step 11 · terminal
━━━━ Step 11: Verify a detached proof via audit service ━━
  → Submitting balance response proof for verification…

  ✓  PROOF VALID
  ✓  Signer DID:  did:web:bankee.ai
  ✓  Signed at:   2026-06-05T11:09:25.000Z
  ✓  Session:     kyaos_39e5b35c-f1b8-43e3-8ed4-bdf0617a817d

This is the critical step. An independent service — the audit service — took a proof from a completely different part of the system (the balance tool response from step 2), resolved the signer's DID using the pre-loaded trusted key, reconstructed the canonical payload from the proof metadata, and verified the Ed25519 signature. It confirmed: the signer was did:web:bankee.ai, the signature was produced at a specific time, and the session is traceable. The entire verification is deterministic and requires no trust in Bankee — only in the mathematics of Ed25519.

Test results: 11/11 steps verified

Unedited results from the live Bankee.ai dev environment:

STEP 0All 3 services ready — DID: did:web:bankee.ai confirmed✓ PASS
STEP 1KYA-OS handshake — session kyaos_39e5b35c established✓ PASS
STEP 2get_balance — proof attached, DID + hashes confirmed✓ PASS
STEP 3get_exchange_rate — proof attached✓ PASS
STEP 4create_payment £50 — autonomous, completed, DID in record✓ PASS
STEP 5create_payment £500 — consent gate fired, needs_authorization✓ PASS
STEP 6Human approval — VC delegation-1780657765174 issued by did:web:bankee.ai✓ PASS
STEP 7Retry £500 — delegation auto-applied, payment executed + proof✓ PASS
STEP 8get_payment_status — completed, proof attached✓ PASS
STEP 9list_payments — 4 payments, proof attached✓ PASS
STEP 10Audit trail — 2 records, both verified ✓✓ PASS
STEP 11Proof verification — VALID — signer confirmed, timestamp confirmed✓ PASS

Why this matters for compliance

PSD2/PSD3 Strong Customer Authentication

PSD2 SCA requires at least two independent authentication factors for payment initiation. KYA-OS's Ed25519 key pair satisfies the possession factor cryptographically — the agent proves it controls the private key by signing the proof. The consent gate + delegation VC provides the human approval factor. Together they produce a PSD3-compatible authentication record for machine-initiated payments, without a human being present in the transaction loop.

AML — beneficial owner tracing

Anti-money laundering monitoring requires knowing the beneficial owner of a transaction. When an AI agent initiates a payment, the did:web:bankee.ai in the proof points to the Responsible Party — the human or organisation ultimately accountable. The delegation chain shows exactly which human approved the specific action. The audit trail is cryptographically non-repudiable.

GDPR Article 22 — automated decision-making

Article 22 requires that automated decisions affecting individuals are subject to human review and explainability. KYA-OS's audit trail provides the explainability record. The consent gate provides the human review intervention point. The signed VC is the documented, verifiable record that a human explicitly approved a specific agent action.

StatusList2021 revocation — revoking authority instantly

If a delegation credential needs to be revoked — agent compromised, scope exceeded, human changes their mind — a single API call flips bit 0 in the StatusList2021 bitstring. The revocation list is publicly accessible at /api/status-list. Any verifier checking the credential can download the compressed list and check the bit in milliseconds. No need to contact the issuer. No centralised revocation oracle.

What makes this different from API key auth

API key authentication answers one question: is this a valid key? KYA-OS answers five:

Who is the agent?
did:web:bankee.ai — a stable DID with a verifiable public key
Under whose authority?
Delegation VC chain rooted at the Responsible Party
What were they permitted to do?
Scoped VC: payments:write, expires 1h, revocable
What did they actually do?
Request hash + response hash, both signed
When, in which session?
Timestamp + session ID + nonce — all in the proof
Bankee is a contributing member of the Decentralized Identity Foundation
We are an active participant in the DIF Trust and Agent Authorization Working Group (TAAWG) — the body maintaining the KYA-OS specification. Our fork of the reference implementation is at bankee-ai/kya-os-mcp. The production infrastructure described in this article is at bankee-ai/bankee-kya-os. The DID document for did:web:bankee.ai is live at bankee.ai/.well-known/did.json.

Run it yourself

The full source, Docker Compose files, and deployment guide are in the public repo. Clone it, generate an identity, and run the 11-step demo against live infrastructure in under 5 minutes.

bankee-ai/bankee-kya-os View DID documentSDK Docs
Back to Protocol Layer