Signed audit chain for any workflow
Every step of a multi-agent workflow becomes a signed Verifiable Credential. Pull the whole chain in topological order with one request.
A regulated workflow runs across five agents. Each step produces a signed credential. Query the workflow ID and you get the whole chain in topological order — auditor-ready.
from agentfield import Agent
app = Agent(
node_id="claims-pipeline",
enable_did=True,
vc_enabled=True,
)
@app.reasoner()
async def regulated_claim(claim: dict) -> dict:
# Each cross-agent call becomes a signed VC node in the workflow chain
validated = await app.call("validator.check_claim", claim=claim)
if not validated.get("valid"):
return {"status": "rejected", "reason": validated["reason"]}
risk = await app.call("risk-engine.assess", claim=claim)
decision = await app.call("adjudicator.decide", claim=claim, risk=risk)
return {"decision": decision, "workflow_id": app.note("decided", ["audit"])}
app.run()import { Agent } from '@agentfield/sdk';
const agent = new Agent({
nodeId: 'claims-pipeline',
didEnabled: true, // VCs require DID
});
agent.reasoner('regulatedClaim', async (ctx) => {
const claim = ctx.input.claim;
// Each cross-agent call becomes a signed VC node in the workflow chain
const validated = await ctx.call('validator.check_claim', { claim });
if (!validated.valid) {
return { status: 'rejected', reason: validated.reason };
}
const risk = await ctx.call('risk-engine.assess', { claim });
const decision = await ctx.call('adjudicator.decide', { claim, risk });
ctx.note('decided', ['audit']);
return { decision, workflowId: ctx.workflowId };
});
agent.serve();package main
import (
"context"
"log"
"github.com/Agent-Field/agentfield/sdk/go/agent"
)
func main() {
a, err := agent.New(agent.Config{
NodeID: "claims-pipeline",
Version: "1.0.0",
EnableDID: true,
VCEnabled: true,
})
if err != nil {
log.Fatal(err)
}
a.RegisterReasoner("regulated_claim", func(ctx context.Context, input map[string]any) (any, error) {
claim := input["claim"]
// Each cross-agent call becomes a signed VC node in the workflow chain
validated, err := a.Call(ctx, "validator.check_claim", map[string]any{"claim": claim})
if err != nil {
return nil, err
}
if valid, _ := validated["valid"].(bool); !valid {
return map[string]any{"status": "rejected", "reason": validated["reason"]}, nil
}
risk, err := a.Call(ctx, "risk-engine.assess", map[string]any{"claim": claim})
if err != nil {
return nil, err
}
decision, err := a.Call(ctx, "adjudicator.decide", map[string]any{"claim": claim, "risk": risk})
if err != nil {
return nil, err
}
a.Note(ctx, "decided", "audit")
return map[string]any{"decision": decision}, nil
})
a.Serve(context.Background())
}Pull the full audit chain when an auditor asks:
# Every step in this workflow, signed and topologically ordered
curl http://localhost:8080/api/ui/v1/workflows/<workflow_id>/vc-chain
# Verify all of them in one request
curl -X POST http://localhost:8080/api/ui/v1/workflows/<workflow_id>/verify-vc
# Or download a single VC for offline verification
curl http://localhost:8080/api/ui/v1/vc/<vc_id>/download > step.json
af vc verify step.jsonFrom any run page, the Export provenance menu surfaces the VC chain — preview JSON, download for af verify, or jump to the offline audit tool:
Drop the downloaded JSON into the Provenance page to audit offline — bundled DID data, no network round-trip:
The chain response tells you exactly how many steps signed cleanly:
{
"workflow_id": "wf_d4e5f6",
"vc_count": 5,
"verified_count": 5,
"failed_count": 0,
"chain": [
{ "execution_id": "exec_1", "vc_id": "vc_001", "issuer_did": "did:key:...", "status": "verified" }
]
}What this gives you
- One request returns every signed step of a workflow, in order.
- Verification is a single POST — no per-step round-tripping.
- Each VC contains SHA-256 hashes of input and output, so you can verify a step without exposing its data.
Next
Cryptographic receipts for every AI decision
Every reasoner execution produces a signed, offline-verifiable W3C Verifiable Credential with SHA-256 hashes of input and output.
Multimodal agents — vision, image, and audio in one pipeline
One agent that takes images and audio in, and emits images, audio, or video out. Same SDK, same call surface.