Machine identity · standards-aligned · ship today

Every AI agent needs an identity. The CodeB Business Wallet is that identity.

Your autonomous agents already read your inboxes, place orders, triage tickets, book flights. Downstream services have no way to answer the four questions that matter: which agent is calling, who owns it, what it may do, and how to revoke it. The CodeB Business Wallet gives every agent a DID, a stored capability list, revocable ES256 capability tokens signed by your tenant issuer, and a public manifest for downstream services. Built on W3C DID Core, W3C VCDM 2.0, OpenID4VCI, HAIP Wallet Attestation and W3C Bitstring Status List. No new stack. No new database.

Open your Business Wallet Read the API
Live · server-backed. The agent role, capability tokens, agent manifest, verify-token endpoint, and Bitstring Status List credential are all shipping in the reference implementation today. Add an employee with role AI Agent in web-business-wallet.html, mint a scoped token, and hand it to your agent runtime.

The problem: agents have no standardised identity

The last eighteen months of production AI agent deployments have surfaced the same gap in every team we have spoken to.

API keys

Long-lived, high-entropy secrets. Any process on the box can steal one and replay it. Rotation is a manual chore. There is no ownership signal — the key does not know it belongs to a specific agent, model, or purpose.

OAuth service accounts

Better than API keys, but still opaque: the downstream server sees a client ID and a JWT with a scope. It cannot answer which of my five agents presented this token, or what the agent was designed to do.

MCP + A2A gap

The Model Context Protocol and A2A both standardise how agents talk to tools and to each other — neither specifies how the server verifies which agent is on the socket. Every team writes their own identity glue.

Compliance vacuum

The upcoming EU AI Act asks who is accountable for an agent's actions. If your only audit record is "an API call landed at 09:12 with a bearer token", you cannot answer that question. You need agent-level attribution baked in.

The stack: standards you already trust, applied to agents

Every building block already exists in the CodeB Business Wallet. This feature stitches them together for a machine-identity use case.

DID Decentralized Identifier

Each agent gets a fragment DID under its wallet: did:web:tenant:business-wallets:acme#agent-e_abc123. Owner DID is the wallet itself. Resolvable via the wallet's DID Document.

VC Verifiable Credential

Every capability token is a JWT-format Verifiable Credential (ES256, W3C VCDM-shaped payload). Downstream services verify with the tenant issuer public key from the DID document.

WIA Wallet-Instance-Attestation

HAIP §5.11 Wallet Attestation is already implemented per-employee. Agents inherit the same attestation primitive when they need to prove wallet residency.

Cap Capability tokens

Short-lived (max 24 h, configurable per-agent) ES256 JWTs with typ=codeb-agent-token+jwt. Explicit scope claim. TTL clamped by the operator-set agent_max_ttl_sec.

Rev W3C Bitstring Status List

Public revocation URL published in every agent manifest. Agent-level revocation via deactivate-agent is immediate; per-token bit-flipped revocation is on the roadmap.

Audit Append-only log

Every mint and every deactivate is written to the wallet audit log with {ts, actor, action, target}. Downloadable as JSON. Rotated at 5000 entries.

How it works

STEP 1

Create a wallet

Open web-business-wallet.html, sign in with OIDC, mint a wallet for your company. You are auto-enrolled as director.

STEP 2

Add agents

Add an employee with role “AI Agent”. Fill in model tier, purpose, allowed capabilities, and max token TTL.

STEP 3

Mint tokens

Click Mint capability token. Pick a scope subset. Copy the ES256 JWT. Ship it to your agent runtime as a bearer credential.

STEP 4

Downstream verifies

Your server calls verify-agent-token or fetches the public agent manifest to pin the issuer JWK, then verifies tokens offline.

STEP 5

Revoke instantly

Click Deactivate in the UI. The manifest starts returning active:false. All new verify calls fail with agent_deactivated.

Mint a token

POST /business-wallet.ashx?action=mint-agent-token&bw=acme-ltd
Authorization: Bearer <OIDC token from director>
Content-Type: application/json

{
  "empId": "e_abc123",
  "ttl_sec": 3600,
  "scope": ["list-docs","download-doc","verify-vc"],
  "audience": "https://downstream.example/api",
  "purpose_hint": "Q3 invoice triage batch"
}

Verify from downstream (public)

POST https://tenant.example/business-wallet.ashx?action=verify-agent-token
Content-Type: application/json

{"token": "eyJhbGciOiJFUzI1NiIsInR5cCI6ImNvZGViLWFnZW50LXRva2VuK2p3dCJ9..."}

# Response
{
  "verified": true,
  "reason": "ok",
  "agent_did": "did:web:tenant.example:business-wallets:acme-ltd#agent-e_abc123",
  "owner_did": "did:web:tenant.example:business-wallets:acme-ltd",
  "scope": ["list-docs","download-doc","verify-vc"],
  "exp": 1786320000,
  "typ": "codeb-agent-token+jwt"
}

Fetch the manifest (public, cache 60 s)

GET https://tenant.example/business-wallet.ashx?action=agent-manifest&bw=acme-ltd&emp=e_abc123

# Returns name, model, capabilities, owner DID, issuer JWK, revocation URL.
# Verifiers pin issuer_key.x and issuer_key.y once, then verify tokens offline.

Compared to the alternatives

QuestionAPI keysOAuth service accountsBusiness Wallet agent identity
Which agent is calling? no client-id, not agent agent DID
Who owns the agent? no tenant owner DID + wallet
What model / purpose? no no manifest field
Explicit scope per token? no yes yes, clamped by stored caps
Rotation manual library ttl_sec clamp
Immediate revocation rotate + redeploy revocation list deactivate-agent
Public verifier endpoint no JWKS verify-agent-token + manifest
Standards-based no OAuth 2.1 W3C DID + VCDM + Bitstring
Portable across services shared secret leak per-integration bearer JWT anywhere
Aligns with MCP + A2A no bolt-on yes — transport-agnostic

Five use cases that need it today

01

Agentic email triage

An agent reads shared inboxes, files invoices to accounting, flags contracts to legal, drafts replies to routine customer emails. The mail server, the accounting API and the ticketing tool all need to know: who authorised this action, and can it be undone? A capability token with scope read-mail,file-invoice,create-ticket gives each downstream service a machine-verifiable answer.

02

Autonomous procurement

An agent shops for cloud resources, negotiates SaaS renewals, purchases API credits under a spending cap. Every purchase order carries the agent DID, the owner DID and an explicit purchase-goods,max-eur-500 scope. Vendor audit trails now attribute spend correctly. Kill switch is one deactivate-agent call away.

03

RPA fleet

A hundred robotic-process-automation bots run overnight against SAP, Salesforce, and an on-prem AS/400. Instead of a shared service account per system, each bot gets its own capability token scoped to exactly the actions its workflow requires. When one bot goes rogue, revocation is bot-scoped, not fleet-scoped.

04

Developer copilots

Coding agents commit patches, open PRs, run CI pipelines, deploy to staging. Each action is signed by the developer’s personal agent. When a suspicious commit appears at 02:00, the audit log tells you which agent, which owner, which scope — not just “the CI service account”.

05

Customer-support agents

A public-facing agent answers billing questions, issues refunds up to a threshold, escalates edge cases to humans. Downstream refund and CRM systems verify the incoming token, see the scope issue-refund,max-eur-100, and honour or reject accordingly. No shared credential; no way for a hostile prompt to elevate privileges beyond the minted scope.

Standards we align with

Nothing here is invented. This layer is a pragmatic assembly of published specifications applied to the AI agent use case.

W3C DID Core 1.0

Every agent identifier is a well-formed did:web with a fragment. Owner DIDs are resolvable at /business-wallets/<cid>/did.json.

W3C VCDM 2.0

The agent status list is a BitstringStatusListCredential in the W3C Verifiable Credentials Data Model 2.0 shape.

OpenID for VC Issuance

The tenant issuer that signs capability tokens is the same ES256 key that signs OID4VCI credential offers. One trust anchor, many usages.

HAIP §5.11 Wallet Attestation

Agents can present a Wallet-Instance-Attestation when the downstream service wants proof that the caller runs inside a specific wallet.

W3C Bitstring Status List v1.0

Per-tenant revocation credential published at a stable public URL and linked from every agent manifest.

MCP + A2A alignment

Capability tokens are bearer credentials on the wire. They plug into any MCP tool server or A2A dispatcher that already accepts bearer authentication.

European Digital Identity Wallet

Built on the same architecture as the CodeB EUDI wallet stack: eIDAS 2.0 primitives, ARF 3.0 alignment, and future-proof against the emerging EU Business Wallet vocabulary.

OAuth 2.1 compatibility

A capability token is a bearer JWT: any OAuth 2.1 resource server that accepts JWT bearer tokens and can fetch a JWK from a discovery URL can accept an agent token unchanged.

Questions readers ask

Why does an AI agent need a verifiable identity?

So downstream services can answer the four questions that matter: which agent is calling, who owns it, what it is allowed to do, and how to shut it off. API keys answer none of these. OAuth service accounts only answer the first two, and their credentials are long-lived and manually rotated. A verifiable-credential-backed identity answers all four, with revocation, audit and cryptographic ownership by construction.

How does this differ from an OAuth service account?

A service account is a static shared secret that any process on the machine can steal and replay. A capability token is a short-lived ES256 JWT signed by a tenant issuer key. It carries the agent DID, the owner DID and an explicit scope; the downstream verifier fetches the public agent manifest to check the agent is still active and to obtain the issuer public key. Nothing is shared. Nothing has to be stored on the verifier.

Does this align with the Model Context Protocol (MCP) and A2A?

Yes. MCP standardises how an agent talks to a tool server; A2A standardises how agents talk to each other. Neither specifies how the downstream server proves which agent is on the other end of the socket. The CodeB agent identity layer fills that gap: the agent presents a bearer capability token, the server calls verify-agent-token, done. It is transport-agnostic and works with MCP, A2A, HTTP APIs, gRPC, message queues, or anything else that can carry a bearer token.

Can I revoke an agent immediately?

Yes. Call deactivate-agent on the wallet. The public agent manifest starts returning active:false, and every verify-agent-token check for that DID starts failing with reason: agent_deactivated. Existing tokens are cryptographically valid but the agent is denied, exactly like an OAuth revocation. Per-token bit-flipped revocation via W3C Bitstring Status List is on the roadmap for token-granularity cases.

What is the token format?

An ES256 (ECDSA P-256 SHA-256) compact-serialisation JWT with header typ=codeb-agent-token+jwt. Payload: iss (owner DID), sub (agent DID), agent_did, owner_did, role, scope (array), iat, nbf, exp, wallet_id (URN), wallet_link, manifest, did_doc, optional aud and purpose_hint, and a random jti. Signed by the tenant issuer key which is discoverable via the DID document.

Do downstream services need an account on my tenant to verify tokens?

No. verify-agent-token and agent-manifest are public endpoints. A downstream service fetches the manifest once (60 s cache), pins the issuer JWK, and can then verify tokens fully offline. If it prefers, it can call verify-agent-token on every request to also get an active-flag check without maintaining state itself.

How is the agent DID formatted?

did:web:<tenant>:business-wallets:<companyId>#agent-<empId>. The wallet DID itself is resolvable at /business-wallets/<companyId>/did.json; the #agent-* fragment identifies a specific agent within that wallet. Owner DIDs are always without the fragment.

What capabilities can I attach?

Any of the read-only wallet actions (list-docs, download-doc, list-vc, verify-vc, get-state, list-my-wallets), plus any custom capability slug you want to define. Custom slugs are opaque to the wallet: it just carries them in the token, and your downstream service interprets them. Mutating wallet operations (upload-doc, add-employee, wallet-export, and so on) are permanently off-limits to agents by design.