Examples
Three runnable programs in examples/ exercise the full protocol end to end — one traces the spec's own three-agent reference flow (§32), one shows the same authority chain enforced inside a LangChain tool-calling loop, and one governs a real deepagents agent graph.
Three-agent reference flow
examples/three_agent_demo.py runs Principal → Requester → Research Agent → Evaluator → Settlement Adapter, entirely with signed VACT-P objects — no network calls, no mocked cryptography.
make demo| # | Phase | What happens |
|---|---|---|
1 | Authority | Principal signs a Mandate authorizing the Requester to purchase one research report, capped at USD 250. |
2 | Authority | Requester issues a Delegation to the Researcher — read access to three documents, a USD 220 ceiling, no training use, 24h retention. |
3 | Authority | Chain is verified; effective authority is the intersection — USD 220 budget, delegation depth 1. |
4 | Market | Researcher publishes a signed Offer for research.report, priced fixed at USD 200, verified by an evaluator. |
5 | Market | Researcher issues a Quote binding the Offer to the three delegated documents and a USD 200 ceiling. |
6 | Market | Requester and Researcher co-sign the identical Task Contract — it only activates once both signatures are present. |
7 | Execution | Researcher evaluates the authorization decision, records a Policy Decision Receipt. |
8 | Execution | Task advances through five signed transitions: PROPOSED → OFFERED → ACCEPTED → AUTHORIZED → QUEUED → RUNNING. |
9 | Execution | Researcher completes the report and emits an Execution Receipt, hash-linked to the Policy Decision Receipt. |
10 | Verification | An independent Evaluator agent scores the output 0.94, issues an Evaluation Receipt hash-linked to the Execution Receipt. |
11 | Settlement | Requester authorizes capture; USD 200.00 settles through a mock escrow adapter with a hash-linked Settlement Receipt. |
Audit reconstruction
At the end, the Principal reconstructs the full chain without ever seeing the raw source documents or private model reasoning:
Mandate
→ Delegation
→ Offer and Quote
→ Task Contract
→ Policy Decision
→ Execution Receipt
→ Evaluation Receipt
→ Settlement ReceiptThe demo then asserts the receipt hash-chain is intact — execution_receipt.prev_receipt_digest == digest(policy_receipt), and so on through settlement. Tamper with a single byte of any object and verification fails closed.
LangChain "Deep Agent" integration
examples/langchain_deep_agent.py wraps two LangChain tools — read_secure_vaultand publish_summary_report — with VACT-P authority checks. Each tool call carries the signed envelope and is validated before it runs:
@tool
def read_secure_vault(document_id: str, envelope_json: str) -> str:
"""Reads a document from the secure vault. Requires a valid VACT-P authority chain."""
envelope = json.loads(envelope_json)
chain = envelope.get("authority_chain", [])
effective = verify_chain(chain, RESOLVER)
decision = authorize(effective, action="document.read", resource=document_id)
decision.enforce() # raises + fails closed if not allowed
return vault_data.get(document_id, "ERROR: Document not found.")The demo then drives an agent through three calls:
- Reads
urn:doc:financial-secrets— allowed, in scope of the Delegation. - Publishes a summary report — allowed, in scope of the Delegation.
- Attempts to read
urn:doc:hr-secrets— denied, outside the delegated resource set, fails closed withPERMISSION DENIED.
Run it (falls back to a self-contained simulation mode if langchain-core isn't installed):
make demo-langchainThe agent's LLM never decides what it's allowed to do — the tool itself reconstructs effective authority from the signed chain and enforces it before touching data. A jailbroken prompt cannot talk its way past a Delegation it wasn't issued.
Governing a real deepagents agent
examples/deepagents_governed_agent.py goes one step further: it builds an actualdeepagentscreate_deep_agent() graph — planning via a todo list, a mock filesystem, sub-agent spawning — the same LangGraph-based shape of agent that coding assistants are built on, and governs its tools with VACT-P instead of hand-rolling the tool-calling loop.
Effective authority is resolved once, out-of-band, from a signed Mandate → Delegation chain, then bound to the run through a contextvar. The model's tool schema only ever exposes ordinary arguments like document_id and report_id — it has no channel through which to see, present, or forge authority material:
def vact_governed(action: str, resource_param: str):
"""Enforce a VACT-P authorization decision before the tool body runs."""
def decorator(func):
@wraps(func)
def guarded(**kwargs):
authority = _authority.get() # bound out-of-band, not by the model
resource = kwargs.get(resource_param, "*")
decision = authorize(authority, action=action, resource=resource)
if not decision.allowed:
return f"PERMISSION DENIED [{decision.reason_code}]: {decision.detail}"
return func(**kwargs)
return guarded
return decorator
@vact_governed("document.read", resource_param="document_id")
def read_secure_vault(document_id: str) -> str:
"""Read a document from the secure vault by its resource identifier."""
return VAULT.get(document_id, "ERROR: document not found.")
agent = create_deep_agent(tools=[read_secure_vault, publish_summary_report], ...)Run it against a real model, or let it fall back to a self-contained governance simulation:
pip install deepagents langchain-anthropic
export ANTHROPIC_API_KEY=sk-...
make demo-deepagentsGovernance lives entirely outside the model's context window. Whether the deep agent is reasoning live with Claude or being driven deterministically in simulation, the same authorize()call enforces the same signed chain — the enforcement boundary doesn't move when the model does.