# Greenhelix Agent Credential Wallets

> Agent Credential Wallets: Verifiable Intent & Delegation Chains. Build agent credential wallets with Verifiable Intent, SD-JWT delegation chains, cross-protocol presentation (AP2/UCP/ACP/x402), eIDAS 2.0 EUDI compliance, and reputation-bound credentials. Includes detailed Python code examples for every pattern.

- Skill: `lord1egypt/greenhelix-agent-credential-wallets` (Agent Skill)
- Install (CLI): `npx skillmds@latest add lord1egypt/greenhelix-agent-credential-wallets`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lord1egypt/greenhelix-agent-credential-wallets/raw
- Safety review: pending (external: skill-scanner PASS, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: Lord1Egypt (https://skillmd.com/u/lord1egypt)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/lord1egypt/greenhelix-agent-credential-wallets

---

# Agent Credential Wallets: Verifiable Intent & Delegation Chains

> **Notice**: This is an educational guide with illustrative code examples.
> It does not execute code or install dependencies.
> All examples use the GreenHelix sandbox (https://sandbox.greenhelix.net) which
> provides 500 free credits — no API key required to get started.
>
> **Referenced credentials** (you supply these in your own environment):
> - `GREENHELIX_API_KEY`: API authentication for GreenHelix gateway (read/write access to purchased API tools only)


Your agent just tried to buy cloud compute on behalf of your company. The vendor's agent asked for proof of authorization. Your agent presented an API key. The vendor's agent rejected it -- not because the key was invalid, but because an API key proves nothing about delegation. It does not answer the question the vendor actually asked: "Can this agent spend up to $5,000 on GPU instances for Acme Corp, and did a human authorize that specific action?" An API key says "this entity has access." A verifiable credential says "this entity was authorized by this principal to perform these actions within these constraints, and here is the cryptographic proof chain from the human who approved it." That distinction is the entire difference between agents that can transact in the open economy and agents that remain trapped inside their owner's perimeter. On March 5, 2026, Mastercard open-sourced the Verifiable Intent specification alongside Google, Fiserv, IBM, and Checkout.com, defining exactly how agents prove delegated authority to spend. Prove launched Verified Agent targeting the $1.7 trillion agentic commerce market with carrier-grade identity verification for non-human entities. The EU finalized eIDAS 2.0 implementation rules mandating EUDI Wallets by December 2026. Google's Agent-to-Agent Protocol (AP2), the Universal Commerce Protocol (UCP), and OpenAI's Agent Commerce Protocol (ACP) all require verifiable agent identity as the foundation layer. The decentralized identity market hit $7.4 billion in 2026. The convergence is real, and it is happening on a twelve-month timeline. This guide walks you through building a production credential wallet for your agents: SD-JWT-VC issuance, delegation chains from human to agent, cross-protocol credential presentation, eIDAS 2.0 compliance, reputation binding, and fleet-wide deployment. Every implementation uses the GreenHelix A2A Commerce Gateway API. Every pattern is designed for the December 2026 deadline.
1. [The Agent Credential Problem](#chapter-1-the-agent-credential-problem)
2. [W3C Verifiable Credentials & SD-JWT Primer](#chapter-2-w3c-verifiable-credentials--sd-jwt-primer)

## What You'll Learn
- Chapter 1: The Agent Credential Problem
- Chapter 2: W3C Verifiable Credentials & SD-JWT Primer
- Chapter 3: Building Your Agent's Credential Wallet
- Chapter 4: Implementing Verifiable Intent
- Chapter 5: Cross-Protocol Credential Presentation
- Chapter 6: eIDAS 2.0 Compliance
- Chapter 7: Trust Scoring, Reputation Binding & Credential Revocation
- Next Steps
- What You Get

## Full Guide

# Agent Credential Wallets: Verifiable Intent & Delegation Chains for Agentic Commerce

Your agent just tried to buy cloud compute on behalf of your company. The vendor's agent asked for proof of authorization. Your agent presented an API key. The vendor's agent rejected it -- not because the key was invalid, but because an API key proves nothing about delegation. It does not answer the question the vendor actually asked: "Can this agent spend up to $5,000 on GPU instances for Acme Corp, and did a human authorize that specific action?" An API key says "this entity has access." A verifiable credential says "this entity was authorized by this principal to perform these actions within these constraints, and here is the cryptographic proof chain from the human who approved it." That distinction is the entire difference between agents that can transact in the open economy and agents that remain trapped inside their owner's perimeter. On March 5, 2026, Mastercard open-sourced the Verifiable Intent specification alongside Google, Fiserv, IBM, and Checkout.com, defining exactly how agents prove delegated authority to spend. Prove launched Verified Agent targeting the $1.7 trillion agentic commerce market with carrier-grade identity verification for non-human entities. The EU finalized eIDAS 2.0 implementation rules mandating EUDI Wallets by December 2026. Google's Agent-to-Agent Protocol (AP2), the Universal Commerce Protocol (UCP), and OpenAI's Agent Commerce Protocol (ACP) all require verifiable agent identity as the foundation layer. The decentralized identity market hit $7.4 billion in 2026. The convergence is real, and it is happening on a twelve-month timeline. This guide walks you through building a production credential wallet for your agents: SD-JWT-VC issuance, delegation chains from human to agent, cross-protocol credential presentation, eIDAS 2.0 compliance, reputation binding, and fleet-wide deployment. Every implementation uses the GreenHelix A2A Commerce Gateway API. Every pattern is designed for the December 2026 deadline.

---

## Table of Contents

1. [The Agent Credential Problem](#chapter-1-the-agent-credential-problem)
2. [W3C Verifiable Credentials & SD-JWT Primer](#chapter-2-w3c-verifiable-credentials--sd-jwt-primer)
3. [Building Your Agent's Credential Wallet](#chapter-3-building-your-agents-credential-wallet)
4. [Implementing Verifiable Intent](#chapter-4-implementing-verifiable-intent)
5. [Cross-Protocol Credential Presentation](#chapter-5-cross-protocol-credential-presentation)
6. [eIDAS 2.0 Compliance](#chapter-6-eidas-20-compliance)
7. [Trust Scoring, Reputation Binding & Credential Revocation](#chapter-7-trust-scoring-reputation-binding--credential-revocation)

---

## Chapter 1: The Agent Credential Problem

### Why API Keys and OAuth Tokens Break Under Delegation

API keys are bearer tokens. They prove possession, not authorization. When Agent A presents an API key to Agent B, Agent B knows that Agent A has a valid key. Agent B does not know who issued the key, what actions the key authorizes, whether the key can be further delegated, what spending limits apply, or whether a human ever approved the transaction that Agent A is attempting. OAuth 2.0 improves on this by introducing scopes and token lifetimes, but OAuth was designed for a three-party model: a user, a client application, and a resource server. Agentic commerce operates in a four-party model at minimum: a human principal, a delegating agent, a transacting agent, and a counterparty agent. OAuth has no native concept of delegation chains, spending constraints that propagate through layers, or verifiable proof that the token holder was authorized by a specific upstream principal.

The failure modes are concrete:

- **Stolen key replay**: A leaked API key gives the attacker the same permissions as the legitimate agent. There is no cryptographic binding between the key and the entity presenting it.
- **Scope inflation**: An agent granted "read marketplace" scope uses that token to call `create_intent` because the token endpoint does not distinguish between marketplace reads and payment actions at the granularity commerce requires.
- **Delegation opacity**: Agent A delegates to Agent B using a sub-key. Agent B delegates to Agent C. The vendor interacting with Agent C has no way to verify the chain back to the original human who authorized the spend.
- **Constraint evaporation**: A human sets a $500 daily limit. The limit is stored in Agent A's configuration. When Agent A delegates to Agent B, the limit is not cryptographically bound to the delegation -- Agent B's spending constraints are whatever Agent B chooses to enforce locally.

### The Four-Party Model Failure

Traditional payment rails use a four-party model: cardholder, merchant, issuing bank, acquiring bank. Every party has a defined role, and trust flows through the card network as an intermediary. Agentic commerce broke this model because the "cardholder" is now an AI agent acting on behalf of a human, the "merchant" is another AI agent, and neither the issuing bank nor the acquiring bank has any mechanism to verify that the agent-cardholder was authorized by the human-principal.

```
TRADITIONAL FOUR-PARTY MODEL
┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐
│  Human   │───>│ Issuing │───>│  Card   │───>│Acquiring│───>│ Merchant│
│(Cardhldr)│    │  Bank   │    │ Network │    │  Bank   │    │         │
└─────────┘    └─────────┘    └─────────┘    └─────────┘    └─────────┘
     │ Identity verified        Trust mediated         Identity verified
     │ via KYC + PIN            by network rules       via merchant agreement

AGENTIC FOUR-PARTY MODEL (BROKEN)
┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐
│  Human   │ ??>│ Agent A │ ??>│ Gateway │ ??>│ Agent B │
│(Principal│    │(Delegat.)│    │(Network)│    │(Vendor) │
└─────────┘    └─────────┘    └─────────┘    └─────────┘
     │ How does Agent A         No delegation       How does Agent B
     │ prove human approved?    chain verification  verify constraints?
```

The question marks are the credential gap. No API key, OAuth token, or session cookie answers the three questions every counterparty needs answered: (1) Who is the human principal? (2) What did they authorize? (3) What are the constraints?

### Protocol Convergence: Mastercard, Google, OpenAI

Three separate industry efforts converged on the same answer in the first quarter of 2026:

**Mastercard Verifiable Intent (March 5, 2026)**: Open-sourced with Google, Fiserv, IBM, and Checkout.com. Defines how an agent proves that a human authorized a specific payment action, including amount limits, merchant categories, and time bounds. Uses SD-JWT-VC (Selective Disclosure JSON Web Token Verifiable Credential) as the credential format and DID:web as the identity anchor.

**Google AP2 + Universal Commerce Protocol (UCP)**: Google's agent-to-agent protocol requires agents to present verifiable identity before any commercial transaction. UCP extends this with standardized credential presentation flows for cross-platform commerce. Both protocols accept W3C Verifiable Credentials in SD-JWT format.

**OpenAI Agent Commerce Protocol (ACP)**: Defines how agents discover, negotiate, and transact with each other. The identity layer requires verifiable credentials for any transaction above a configurable threshold. ACP's credential requirements align with the W3C VC Data Model 2.0 and accept SD-JWT-VC as a presentation format.

The convergence is not accidental. All three groups independently identified the same gap: agents need cryptographically verifiable delegation chains, not just access tokens. The answer they all arrived at was W3C Verifiable Credentials with selective disclosure.

| Protocol | Organization | Credential Format | Identity Anchor | Delegation Model |
|----------|-------------|-------------------|-----------------|------------------|
| Verifiable Intent | Mastercard + consortium | SD-JWT-VC | DID:web | Layered issuance |
| AP2 / UCP | Google | W3C VC (SD-JWT) | DID:web / DID:key | Presentation exchange |
| ACP | OpenAI | W3C VC (SD-JWT) | DID:key | Chained credentials |
| x402 | Open standard | W3C VC (optional) | DID:web | Payment-bound proofs |

### The $1.7 Trillion Market Context

The numbers define the urgency. Prove's Verified Agent launch targeted the $1.7 trillion agentic commerce market -- transactions where at least one party is an autonomous agent. Gartner projected that by the end of 2026, 30% of enterprise API traffic will be agent-originated, up from under 5% in 2024. The decentralized identity market reached $7.4 billion in 2026, driven primarily by agent identity requirements that existing IAM systems cannot address. McKinsey's March 2026 analysis estimated that credential-related transaction failures cost the agentic commerce ecosystem $2.3 billion annually in abandoned transactions, dispute resolution overhead, and fraud losses.

The cost of inaction is measurable. Every agent transaction that fails because the counterparty cannot verify delegation authority is a lost revenue event. Every disputed escrow that could have been prevented by a verifiable spending limit is an operational cost. Every EU transaction that lacks EUDI-compliant credentials after December 2026 is a regulatory violation. The credential wallet is not optional infrastructure -- it is the authorization layer that makes agent commerce possible at scale.

### What This Guide Builds

By the end of this guide, your agents will have:

1. A DID-anchored credential wallet managed through GreenHelix identity tools
2. SD-JWT delegation chains that cryptographically bind human authorization to agent actions
3. Credential presentation adapters for AP2, UCP, ACP, and x402
4. eIDAS 2.0 compliant EUDI wallet integration for EU commerce
5. Reputation-bound credentials with real-time revocation
6. Fleet-wide issuance, rotation, and monitoring for production deployment

---

## Chapter 2: W3C Verifiable Credentials & SD-JWT Primer

### Credential Anatomy

A Verifiable Credential (VC) is a tamper-evident data structure with three components:

**Credential metadata**: Who issued it, when, when it expires, what type it is. This is not the claims themselves -- it is the envelope that lets a verifier understand what they are looking at before examining the contents.

**Claims (the subject)**: The actual assertions. "Agent acme-buyer-01 is authorized to spend up to $5,000 per transaction on cloud compute services." Claims can be about identity (this agent is registered to Acme Corp), capability (this agent can purchase compute), or constraint (this agent's spending limit is $5,000).

**Proof**: The cryptographic mechanism that makes the credential tamper-evident. For SD-JWT-VC, this is a JSON Web Signature (JWS) over the credential payload plus disclosure digests. The proof binds the claims to the issuer's key -- if any claim is modified, the signature verification fails.

```
VERIFIABLE CREDENTIAL STRUCTURE
┌────────────────────────────────────────────────┐
│  CREDENTIAL METADATA                           │
│  ├── issuer: did:web:acme.com                  │
│  ├── issuanceDate: 2026-04-06T00:00:00Z        │
│  ├── expirationDate: 2026-04-07T00:00:00Z      │
│  └── type: [VerifiableCredential,              │
│             AgentDelegationCredential]          │
├────────────────────────────────────────────────┤
│  CLAIMS (credentialSubject)                    │
│  ├── id: did:key:z6Mkw...  (agent DID)        │
│  ├── delegatedBy: did:web:acme.com             │
│  ├── authorizedActions: [purchase_compute]     │
│  ├── spendingLimit: {amount: 5000, currency:   │
│  │                    USD, period: transaction} │
│  └── merchantCategory: [cloud_compute]         │
├────────────────────────────────────────────────┤
│  PROOF                                         │
│  ├── type: JsonWebSignature2020                │
│  ├── verificationMethod: did:web:acme.com#key1 │
│  └── jws: eyJhbGciOiJFZERTQSJ9...             │
└────────────────────────────────────────────────┘
```

### Selective Disclosure with SD-JWT

Standard JWTs are all-or-nothing: you present the entire token or nothing. An agent buying cloud compute should not have to reveal its owner's full legal name, tax ID, and home address to a vendor agent that only needs to verify spending authorization. Selective Disclosure JWT (SD-JWT) solves this by replacing sensitive claims with salted hashes in the JWT body. The actual claim values are carried as separate "disclosures" that the holder can choose to include or omit at presentation time.

The SD-JWT structure has three parts separated by tildes (`~`):

```
<issuer-signed JWT> ~ <disclosure 1> ~ <disclosure 2> ~ ... ~ <key binding JWT>
```

**Issuer-signed JWT**: Contains the credential metadata and hashed digests of all disclosable claims in an `_sd` array. The issuer signs this part. It is always present.

**Disclosures**: Each disclosure is a base64url-encoded JSON array of `[salt, claim_name, claim_value]`. The holder includes only the disclosures they want the verifier to see. The verifier hashes each received disclosure and checks it against the `_sd` digests in the JWT to confirm it was issued by the original issuer.

**Key Binding JWT**: An optional JWT signed by the holder's key that proves the presenter is the intended holder, not someone who intercepted the SD-JWT in transit. For agent credentials, key binding is mandatory -- without it, a stolen credential can be replayed by any agent.

```
SD-JWT SELECTIVE DISCLOSURE FLOW

ISSUANCE (all claims included):
┌──────────────────────────┐
│ Issuer signs JWT with    │     ┌─────────────┐
│ _sd: [hash1, hash2,     │────>│ Agent Wallet │
│       hash3, hash4]      │     │ stores full  │
│                          │     │ SD-JWT + all │
│ + disclosure(owner_name) │     │ disclosures  │
│ + disclosure(tax_id)     │     └─────────────┘
│ + disclosure(spend_limit)│
│ + disclosure(actions)    │
└──────────────────────────┘

PRESENTATION (selective):
┌─────────────┐     ┌──────────────────────────┐
│ Agent Wallet │────>│ JWT (with all 4 hashes)  │
│ reveals only │     │ + disclosure(spend_limit) │
│ 2 of 4      │     │ + disclosure(actions)     │
│ claims       │     │ + key_binding_jwt         │
└─────────────┘     └──────────────────────────┘
                    Verifier sees spend_limit & actions.
                    Cannot derive owner_name or tax_id
                    (only hashes remain in the JWT).
```

### SD-JWT-VC Format for Agent Credentials

SD-JWT-VC is the specific profile of SD-JWT designed for Verifiable Credentials. It is the format chosen by Mastercard's Verifiable Intent spec, accepted by Google AP2 and OpenAI ACP, and mandated by the EU's eIDAS 2.0 Architecture Reference Framework for EUDI Wallet credentials.

The key properties of SD-JWT-VC for agent developers:

- **`iss`**: The issuer's identifier, typically a DID:web URL that resolves to a DID Document containing the issuer's public key.
- **`sub`**: The subject of the credential -- the agent's DID.
- **`iat`** / **`exp`**: Issuance and expiration timestamps. For agent delegation credentials, expiration should be short (hours, not months).
- **`cnf`**: Confirmation claim that binds the credential to the holder's key. Contains the holder's public key or a reference to it. This is what enables key binding.
- **`_sd`**: Array of digests for selectively disclosable claims.
- **`vct`**: Verifiable Credential Type -- a URI identifying the credential schema (e.g., `https://greenhelix.net/credentials/agent-delegation/v1`).

### Delegation Chains as Layered SD-JWT Issuance

A delegation chain is a sequence of credentials where each credential's subject becomes the issuer of the next credential. The human principal issues a credential to their primary agent. That agent issues a sub-credential to a sub-agent, with equal or narrower constraints. The sub-agent can issue further sub-credentials, each layer narrowing the scope.

```
DELEGATION CHAIN (3 LAYERS)

Layer 0: Human Principal
  └── Issues VC to Agent A
      iss: did:web:alice.com
      sub: did:key:agentA
      spend_limit: $10,000/day
      actions: [purchase_compute, purchase_storage]

Layer 1: Agent A
  └── Issues VC to Agent B (sub-delegation)
      iss: did:key:agentA
      sub: did:key:agentB
      spend_limit: $2,000/transaction  (narrowed from $10k/day)
      actions: [purchase_compute]       (narrowed from 2 actions)
      parent_credential: <hash of Layer 0 VC>

Layer 2: Agent B
  └── Presents to Vendor Agent C
      Includes: Layer 2 VC + Layer 1 VC + Layer 0 VC
      Vendor verifies entire chain back to did:web:alice.com
```

The critical property is **constraint narrowing**: each layer can only narrow the constraints of its parent. Agent A received a $10,000/day limit and cannot issue Agent B a $20,000/day credential. Agent A received two authorized actions and cannot grant Agent B a third action. The verifier checks this by walking the chain from leaf to root and confirming that every child credential's constraints are a subset of its parent's.

---

## Chapter 3: Building Your Agent's Credential Wallet

### Prerequisites

You need a GreenHelix API key with pro tier access (identity tools `build_claim_chain`, `search_agents_by_metrics`, and `submit_metrics` require pro tier). Register an agent identity and create a wallet before building credentials.

### The CredentialWallet Class

```python
import requests
import json
import hashlib
import time
import base64
import secrets
from typing import Optional, Dict, List, Any
from dataclasses import dataclass, field, asdict

# --- GreenHelix sandbox session (free tier: 500 credits, no key required) ---
# To get started, visit https://sandbox.greenhelix.net — no signup needed.
# For production, set GREENHELIX_API_KEY in your environment.
import os

API_BASE = os.environ.get("GREENHELIX_API_URL", "https://sandbox.greenhelix.net")

session = requests.Session()
api_key = os.environ.get("GREENHELIX_API_KEY", "")
if api_key:
    session.headers["Authorization"] = f"Bearer {api_key}"
session.headers["Content-Type"] = "application/json"


def api_call(tool: str, input_data: dict) -> dict:
    """Call a GreenHelix REST endpoint for the given tool."""
    response = session.post(f"{API_BASE}/v1/tools/{tool}", json=input_data)
    response.raise_for_status()
    return response.json()


@dataclass
class Disclosure:
    """A single SD-JWT disclosure: [salt, claim_name, claim_value]."""
    salt: str
    claim_name: str
    claim_value: Any

    def encode(self) -> str:
        """Base64url-encode the disclosure array."""
        payload = json.dumps([self.salt, self.claim_name, self.claim_value])
        return base64.urlsafe_b64encode(payload.encode()).rstrip(b"=").decode()

    def digest(self) -> str:
        """SHA-256 digest of the encoded disclosure."""
        encoded = self.encode()
        return base64.urlsafe_b64encode(
            hashlib.sha256(encoded.encode()).digest()
        ).rstrip(b"=").decode()


@dataclass
class AgentCredential:
    """An SD-JWT-VC credential with selective disclosure support."""
    issuer_did: str
    subject_did: str
    credential_type: str
    claims: Dict[str, Any]
    disclosable_claims: List[str]  # claim names that support selective disclosure
    issued_at: float = field(default_factory=time.time)
    expires_at: Optional[float] = None
    parent_hash: Optional[str] = None  # hash of parent credential in chain
    disclosures: List[Disclosure] = field(default_factory=list)

    def __post_init__(self):
        if self.expires_at is None:
            self.expires_at = self.issued_at + 86400  # 24h default
        # Generate disclosures for disclosable claims
        self.disclosures = []
        for name in self.disclosable_claims:
            if name in self.claims:
                self.disclosures.append(Disclosure(
                    salt=secrets.token_urlsafe(16),
                    claim_name=name,
                    claim_value=self.claims[name],
                ))

    def sd_digests(self) -> List[str]:
        """Compute _sd array of disclosure digests."""
        return [d.digest() for d in self.disclosures]

    def jwt_payload(self) -> dict:
        """Build the issuer-signed JWT payload."""
        payload = {
            "iss": self.issuer_did,
            "sub": self.subject_did,
            "iat": int(self.issued_at),
            "exp": int(self.expires_at),
            "vct": self.credential_type,
            "_sd": self.sd_digests(),
            "_sd_alg": "sha-256",
        }
        # Include non-disclosable claims directly
        for name, value in self.claims.items():
            if name not in self.disclosable_claims:
                payload[name] = value
        if self.parent_hash:
            payload["parent_credential"] = self.parent_hash
        return payload

    def present(self, disclosed_claims: List[str]) -> dict:
        """Create a presentation with only the specified claims disclosed."""
        selected = [d for d in self.disclosures if d.claim_name in disclosed_claims]
        return {
            "jwt_payload": self.jwt_payload(),
            "disclosures": [d.encode() for d in selected],
            "disclosed_values": {
                d.claim_name: d.claim_value for d in selected
            },
        }

    def credential_hash(self) -> str:
        """SHA-256 hash of the credential payload for chain linking."""
        payload_bytes = json.dumps(self.jwt_payload(), sort_keys=True).encode()
        return hashlib.sha256(payload_bytes).hexdigest()


class CredentialWallet:
    """Agent credential wallet backed by GreenHelix identity tools.

    Manages the full credential lifecycle: registration, wallet creation,
    credential issuance, chain building, and selective presentation.
    """

    def __init__(self, agent_id: str, display_name: str, owner: str):
        self.agent_id = agent_id
        self.display_name = display_name
        self.owner = owner
        self.wallet_id: Optional[str] = None
        self.did: Optional[str] = None
        self.credentials: Dict[str, AgentCredential] = {}
        self.chain_ids: List[str] = []

    def register(self) -> dict:
        """Register the agent identity on GreenHelix.

        This creates the agent's DID and registers its public key.
        Must be called before any other wallet operation.
        """
        result = api_call("register_agent", {
            "agent_id": self.agent_id,
            "display_name": self.display_name,
            "owner": self.owner,
        })
        self.did = f"did:key:{self.agent_id}"
        return result

    def create_wallet(self) -> dict:
        """Create the agent's credential wallet (on-chain store).

        The wallet is a DID-anchored credential store that holds
        issued credentials and supports selective disclosure presentation.
        """
        result = api_call("create_wallet", {
            "agent_id": self.agent_id,
            "wallet_type": "credential",
            "metadata": {
                "owner": self.owner,
                "did": self.did,
                "created_at": time.time(),
            },
        })
        self.wallet_id = result.get("wallet_id", f"wallet-{self.agent_id}")
        return result

    def issue_credential(
        self,
        credential_id: str,
        subject_did: str,
        credential_type: str,
        claims: Dict[str, Any],
        disclosable_claims: List[str],
        ttl_seconds: int = 86400,
        parent_credential_id: Optional[str] = None,
    ) -> AgentCredential:
        """Issue an SD-JWT-VC credential to a subject.

        Args:
            credential_id: Unique ID for this credential.
            subject_did: DID of the agent receiving the credential.
            credential_type: VC type URI.
            claims: All claims to include.
            disclosable_claims: Claim names that support selective disclosure.
            ttl_seconds: Credential lifetime in seconds.
            parent_credential_id: ID of parent credential for delegation chains.

        Returns:
            The issued AgentCredential object.
        """
        parent_hash = None
        if parent_credential_id and parent_credential_id in self.credentials:
            parent_hash = self.credentials[parent_credential_id].credential_hash()

        credential = AgentCredential(
            issuer_did=self.did,
            subject_did=subject_did,
            credential_type=credential_type,
            claims=claims,
            disclosable_claims=disclosable_claims,
            expires_at=time.time() + ttl_seconds,
            parent_hash=parent_hash,
        )
        self.credentials[credential_id] = credential
        return credential

    def build_chain(self) -> dict:
        """Build a Merkle claim chain over all issued credentials.

        This anchors the credential history in a tamper-evident structure.
        Uses GreenHelix build_claim_chain to create the chain.
        """
        # Prepare claims from all credentials
        chain_claims = []
        for cred_id, cred in self.credentials.items():
            chain_claims.append({
                "credential_id": cred_id,
                "credential_hash": cred.credential_hash(),
                "subject": cred.subject_did,
                "type": cred.credential_type,
                "issued_at": cred.issued_at,
                "expires_at": cred.expires_at,
            })

        result = api_call("build_claim_chain", {
            "agent_id": self.agent_id,
            "claims": chain_claims,
            "chain_type": "credential_issuance",
        })
        if "chain_id" in result:
            self.chain_ids.append(result["chain_id"])
        return result

    def get_chains(self) -> dict:
        """Retrieve all claim chains for this agent."""
        return api_call("get_claim_chains", {
            "agent_id": self.agent_id,
        })

    def present_credential(
        self,
        credential_id: str,
        disclosed_claims: List[str],
    ) -> dict:
        """Create a selective disclosure presentation.

        Args:
            credential_id: The credential to present.
            disclosed_claims: Which claims to reveal.

        Returns:
            Presentation object with JWT payload and selected disclosures.
        """
        if credential_id not in self.credentials:
            raise KeyError(f"Credential {credential_id} not found in wallet")
        return self.credentials[credential_id].present(disclosed_claims)
```

### Registering and Creating a Wallet

```python
# Initialize the wallet for a procurement agent
wallet = CredentialWallet(
    agent_id="acme-procurement-01",
    display_name="Acme Procurement Agent #1",
    owner="alice@acme.com",
)

# Step 1: Register the agent identity
registration = wallet.register()
print(f"Agent registered: {wallet.did}")
# Output: Agent registered: did:key:acme-procurement-01

# Step 2: Create the credential wallet
wallet_result = wallet.create_wallet()
print(f"Wallet created: {wallet.wallet_id}")
# Output: Wallet created: wallet-acme-procurement-01
```

### Issuing Your First Credential

```python
# The organization (human principal) issues a delegation credential
# to the procurement agent
delegation_cred = wallet.issue_credential(
    credential_id="delegation-001",
    subject_did="did:key:acme-procurement-01",
    credential_type="https://greenhelix.net/credentials/agent-delegation/v1",
    claims={
        "delegated_by": "did:web:acme.com",
        "authorized_actions": ["purchase_compute", "purchase_storage"],
        "spending_limit": {"amount": "10000", "currency": "USD", "period": "day"},
        "merchant_categories": ["cloud_compute", "cloud_storage"],
        "principal_name": "Alice Chen",
        "principal_tax_id": "XX-XXXXXXX",
        "organization": "Acme Corp",
    },
    disclosable_claims=[
        "principal_name",
        "principal_tax_id",
        "spending_limit",
        "merchant_categories",
    ],
    ttl_seconds=28800,  # 8-hour session credential
)

print(f"Credential issued. Hash: {delegation_cred.credential_hash()[:16]}...")
print(f"SD digests: {len(delegation_cred.sd_digests())} disclosable claims")
```

### Anchoring Credentials in a Claim Chain

```python
# After issuing credentials, anchor them in a Merkle claim chain
chain_result = wallet.build_chain()
print(f"Chain built: {chain_result}")

# Verify chains are retrievable
chains = wallet.get_chains()
print(f"Active chains: {len(chains.get('chains', []))}")
```

---

## Chapter 4: Implementing Verifiable Intent

### What Verifiable Intent Means

Verifiable Intent (VI) is the Mastercard-originated specification that answers one question: "Did a human authorize this agent to perform this specific financial action?" It is not a general-purpose credential -- it is specifically designed for payment authorization in agentic commerce. The VI specification defines a layered issuance model where a human creates an intent declaration, the intent is bound to an agent's credential, and the credential is presented to a counterparty as proof of authorization.

The three components of Verifiable Intent:

1. **Intent Declaration**: A structured statement of what the human authorizes. "I authorize Agent acme-procurement-01 to purchase cloud compute services up to $5,000 per transaction from providers in the cloud_compute merchant category, valid for the next 8 hours."

2. **Intent Binding**: The intent declaration is cryptographically bound to the agent's credential using SD-JWT layered issuance. The intent becomes a claim in the agent's delegation credential.

3. **Intent Verification**: The counterparty agent verifies the delegation chain from the presenting agent back to the human principal's DID, checks that the intent constraints match the requested transaction, and confirms that the credential has not expired or been revoked.

### Session-Level Spending Limits

The most common VI use case is spending limits. A human authorizes an agent to spend up to X dollars within a session. The session has a start time and an end time. Every transaction the agent makes within that session must fit within the remaining budget.

```python
class VerifiableIntentManager:
    """Manages Verifiable Intent credentials for payment authorization.

    Implements the Mastercard VI specification with GreenHelix tools:
    intent declaration, binding, session limits, and chain verification.
    """

    def __init__(self, wallet: CredentialWallet):
        self.wallet = wallet
        self.active_intents: Dict[str, dict] = {}
        self.session_spent: Dict[str, float] = {}

    def declare_intent(
        self,
        intent_id: str,
        authorized_actions: List[str],
        spending_limit_usd: float,
        merchant_categories: List[str],
        session_hours: float = 8.0,
        additional_constraints: Optional[Dict] = None,
    ) -> AgentCredential:
        """Declare a Verifiable Intent and bind it to the agent's credential.

        This is called by (or on behalf of) the human principal to authorize
        the agent for specific financial actions within constraints.

        Args:
            intent_id: Unique identifier for this intent session.
            authorized_actions: Actions the agent may perform.
            spending_limit_usd: Maximum USD the agent can spend in this session.
            merchant_categories: Allowed merchant/service categories.
            session_hours: Session duration in hours.
            additional_constraints: Extra constraints (region, vendor whitelist, etc).

        Returns:
            The issued intent credential.
        """
        now = time.time()
        session_end = now + (session_hours * 3600)

        intent_claims = {
            "intent_type": "payment_authorization",
            "authorized_actions": authorized_actions,
            "spending_limit": {
                "amount": str(spending_limit_usd),
                "currency": "USD",
                "period": "session",
            },
            "merchant_categories": merchant_categories,
            "session_start": now,
            "session_end": session_end,
            "principal_did": f"did:web:{self.wallet.owner.split('@')[1]}",
            "principal_email": self.wallet.owner,
        }
        if additional_constraints:
            intent_claims["constraints"] = additional_constraints

        # Issue as SD-JWT-VC -- principal email is disclosable,
        # spending limit and actions are always visible to verifiers
        credential = self.wallet.issue_credential(
            credential_id=intent_id,
            subject_did=self.wallet.did,
            credential_type="https://greenhelix.net/credentials/verifiable-intent/v1",
            claims=intent_claims,
            disclosable_claims=["principal_email", "constraints"],
            ttl_seconds=int(session_hours * 3600),
        )

        self.active_intents[intent_id] = {
            "credential": credential,
            "spending_limit": spending_limit_usd,
            "session_end": session_end,
        }
        self.session_spent[intent_id] = 0.0

        return credential

    def check_intent_budget(self, intent_id: str, amount_usd: float) -> dict:
        """Check if a transaction fits within the intent's remaining budget.

        Returns:
            Dict with 'authorized' bool, 'remaining' float, and 'reason' if denied.
        """
        if intent_id not in self.active_intents:
            return {"authorized": False, "remaining": 0, "reason": "Intent not found"}

        intent = self.active_intents[intent_id]
        if time.time() > intent["session_end"]:
            return {"authorized": False, "remaining": 0, "reason": "Session expired"}

        spent = self.session_spent.get(intent_id, 0.0)
        remaining = intent["spending_limit"] - spent

        if amount_usd > remaining:
            return {
                "authorized": False,
                "remaining": remaining,
                "reason": f"Amount ${amount_usd} exceeds remaining budget ${remaining}",
            }

        return {"authorized": True, "remaining": remaining - amount_usd}

    def execute_authorized_payment(
        self,
        intent_id: str,
        vendor_agent_id: str,
        amount_usd: float,
        description: str,
    ) -> dict:
        """Execute a payment action under a Verifiable Intent session.

        Checks the budget, creates an intent via GreenHelix, and records the spend.
        """
        # Step 1: Check budget
        budget_check = self.check_intent_budget(intent_id, amount_usd)
        if not budget_check["authorized"]:
            return {"status": "denied", "reason": budget_check["reason"]}

        # Step 2: Create the payment intent via GreenHelix
        intent_result = api_call("create_intent", {
            "from_agent": self.wallet.agent_id,
            "to_agent": vendor_agent_id,
            "amount": str(amount_usd),
            "currency": "USD",
            "description": description,
            "metadata": {
                "vi_session": intent_id,
                "credential_hash": self.active_intents[intent_id][
                    "credential"
                ].credential_hash(),
            },
        })

        # Step 3: Record the spend against the session budget
        self.session_spent[intent_id] = (
            self.session_spent.get(intent_id, 0.0) + amount_usd
        )

        return {
            "status": "authorized",
            "intent_result": intent_result,
            "remaining_budget": budget_check["remaining"] - amount_usd,
        }
```

### Using Verifiable Intent

```python
# Create the wallet and intent manager
wallet = CredentialWallet(
    agent_id="acme-buyer-01",
    display_name="Acme Cloud Buyer",
    owner="alice@acme.com",
)
wallet.register()
wallet.create_wallet()

vi_manager = VerifiableIntentManager(wallet)

# Human declares intent: authorize the agent for cloud purchases
intent_cred = vi_manager.declare_intent(
    intent_id="session-2026-04-06-001",
    authorized_actions=["purchase_compute"],
    spending_limit_usd=5000.00,
    merchant_categories=["cloud_compute"],
    session_hours=8.0,
    additional_constraints={"region": "us-east", "max_per_tx": "2000"},
)
print(f"Intent declared. Expires: {intent_cred.expires_at}")

# Agent executes a purchase within the intent
payment = vi_manager.execute_authorized_payment(
    intent_id="session-2026-04-06-001",
    vendor_agent_id="cloudvendor-gpu-fleet",
    amount_usd=1500.00,
    description="8x A100 GPU instances, 4 hours",
)
print(f"Payment: {payment['status']}, remaining: ${payment['remaining_budg

…(truncated)
