Verifiable credentials
Execution VCs with 3-tier hierarchy, offline verification, and VC chain export
Cryptographic proof of what each agent did, when, and with what inputs -- tamper-evident and offline-verifiable.
Every execution can produce a signed verifiable credential (VC) containing SHA-256 hashes of inputs and outputs, tied to the agent's DID. VCs form chains across workflows, enabling offline verification and tamper-evident audit trails for regulated environments.
from agentfield import Agent
app = Agent(
node_id="claims-processor",
version="1.0.0",
vc_enabled=True, # Every execution → signed VC with SHA-256 I/O hashes
)
@app.reasoner(vc_enabled=True)
async def process_claim(claim: dict) -> dict:
result = await app.ai(system="Assess this insurance claim.", user=str(claim))
# This execution is now signed — the VC proves:
# - WHO processed it (agent DID)
# - WHAT input was given (SHA-256 hash)
# - WHAT output was produced (SHA-256 hash)
# - WHEN it happened (timestamp)
return result
# Verify a VC from another agent's execution
result = app.vc_generator.verify_vc(vc_document)
# result["valid"] == True means the signature is valid
# Get the full VC chain for a workflow
chain = app.vc_generator.get_workflow_vc_chain(workflow_id)What just happened
The example walked from a single execution credential to a full workflow VC chain and then to verification endpoints. That is the production story this page should tell immediately: each run can produce a signed audit artifact you can inspect, store, and verify later without trusting application logs alone.
{
"execution_id": "exec_a1b2c3",
"workflow_id": "wf_d4e5f6",
"status": "succeeded",
"verification": "offline-capable"
}
What you get
- Execution VCs -- every execution produces a signed verifiable credential with hashed inputs and outputs
- 3-tier VC hierarchy -- platform, node, and function-level credentials for granular trust
- Workflow VC chains -- aggregate all execution VCs in a workflow into a verifiable chain
- Offline verification -- verify any credential without network access using
af vc verify - Non-repudiation -- Ed25519 signatures tied to DIDs prove which agent performed each operation
- Tamper detection -- SHA-256 hashes of inputs and outputs detect any modification after the fact
How VCs work
When an execution completes, the control plane generates a verifiable credential:
{
"@context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiableCredential", "AgentExecutionCredential"],
"issuer": "did:key:z6MkhaX...",
"issuanceDate": "2026-03-23T10:00:15Z",
"credentialSubject": {
"executionId": "exec_a1b2c3",
"workflowId": "wf_d4e5f6",
"sessionId": "sess_g7h8i9",
"targetDid": "did:key:z6MkjK2...",
"callerDid": "did:key:z6MknP3...",
"inputHash": "sha256:a1b2c3d4e5f6...",
"outputHash": "sha256:f6e5d4c3b2a1...",
"status": "succeeded",
"durationMs": 14200
},
"proof": {
"type": "Ed25519Signature2020",
"verificationMethod": "did:key:z6MkhaX...#key-1",
"proofPurpose": "assertionMethod",
"created": "2026-03-23T10:00:15Z",
"proofValue": "z58DAdF..."
}
}3-Tier Hierarchy
| Level | VC Type | Signed By | Purpose |
|---|---|---|---|
| Platform | Platform credential | Root DID | Certifies the control plane instance |
| Node | Agent tag credential | Root DID | Certifies the agent's identity and authorized tags |
| Function | Execution credential | Agent DID | Proves a specific execution with input/output hashes |
Input and Output Hashing
VCs include SHA-256 hashes of the execution's input and output:
input_hash = SHA-256(canonical_json(input))
output_hash = SHA-256(canonical_json(result))
This allows anyone to verify that a particular input produced a particular output without needing the actual data -- useful for privacy-sensitive workflows.
Configuration
Enable execution VCs in agentfield.yaml:
features:
did:
enabled: true
vc_requirements:
require_vc_execution: true
persist_execution_vc: true| Setting | Default | Description |
|---|---|---|
require_vc_execution | true | Generate VCs for every execution |
persist_execution_vc | true | Store VCs in the database (vs. generate on demand) |
Offline verification
Verify a VC without network access using the CLI:
# Verify a single VC
af vc verify audit.json
# Verify with explicit issuer public key
af vc verify audit.json --issuer-key issuer_pubkey.jwkThe verifier checks:
- Signature validity -- Ed25519 signature matches the VC content
- Issuer DID resolution -- the signing key belongs to the claimed issuer
- Credential integrity -- the VC document has not been modified
- Expiry -- the credential is still within its validity period
- Revocation status -- the credential has not been revoked (online check only)
Agent tag VCs
When agents register with tags, the control plane can issue a tag VC that cryptographically certifies the agent's authorized tags:
{
"@context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiableCredential", "AgentTagCredential"],
"issuer": "did:key:z6MkhaX...",
"credentialSubject": {
"agentDid": "did:key:z6MkjK2...",
"agentId": "auditor",
"tags": ["compliance", "financial", "auditor"],
"approvalStatus": "approved"
}
}Tag VCs are used by the access policy system to verify that an agent's tags are legitimate before evaluating policy rules.
Patterns
Audit Trail for Regulated Workflows
Build a complete, verifiable audit trail:
@app.reasoner()
async def regulated_process(document: str) -> dict:
# Each step produces a VC automatically
app.note("Starting regulated processing", ["audit", "compliance"])
analysis = await app.call(
"compliance-checker.analyze",
document=document,
)
review = await app.call(
"legal-reviewer.review",
analysis=analysis,
)
# After the workflow completes, export the VC chain:
# GET /api/ui/v1/workflows/{workflow_id}/vc-chain
# This provides cryptographic proof of every step
return {"analysis": analysis, "review": review}Verifying a VC Chain Programmatically
import requests
# Export the VC chain for a workflow
chain = requests.get(
"http://localhost:8080/api/ui/v1/workflows/wf_d4e5f6/vc-chain"
).json()
# Verify each VC in the chain
for vc in chain["chain"]:
result = requests.post(
"http://localhost:8080/api/ui/v1/vc/verify",
json=vc["vc_document"],
).json()
assert result["valid"], f"VC {vc['vc_id']} failed verification"
print(f"All {chain['vc_count']} VCs verified successfully")See Identity for how DIDs are generated and managed, and Audit for the broader observability picture.
API reference
Execution VC
GET /api/ui/v1/executions/{execution_id}/vc
Returns the verifiable credential for a specific execution.
Execution VC Status
GET /api/ui/v1/executions/{execution_id}/vc-status
Returns whether a VC exists and its verification status.
Verify Execution VC
POST /api/ui/v1/executions/{execution_id}/verify-vc
Performs comprehensive verification of the execution VC: signature validity, issuer DID resolution, credential expiry, and revocation status.
Workflow VC Chain
GET /api/ui/v1/workflows/{workflowId}/vc-chain
Returns the complete chain of VCs for a workflow -- every execution VC in topological order, plus the workflow-level VC.
Response:
{
"workflow_id": "wf_d4e5f6",
"vc_count": 5,
"verified_count": 5,
"failed_count": 0,
"chain": [
{
"execution_id": "exec_a1b2c3",
"vc_id": "vc_001",
"issuer_did": "did:key:z6Mk...",
"status": "verified",
"created_at": "2026-03-23T10:00:15Z"
}
]
}Verify Workflow VCs
POST /api/ui/v1/workflows/{workflowId}/verify-vc
Verifies all VCs in a workflow chain. Returns per-VC verification results.
Batch Workflow VC Status
POST /api/ui/v1/workflows/vc-status
Fetch VC status summaries for multiple workflows at once.
Download VC
GET /api/ui/v1/vc/{vcId}/download
Download a single VC as a JSON file for offline storage or verification.
Verify Arbitrary VC
POST /api/ui/v1/vc/verify
Submit any VC document for verification against the platform's DID registry.
Export All VCs
GET /api/ui/v1/did/export/vcs
Export all verifiable credentials for backup or external audit.