Verdra Record · SDK

Add Verdra to one agent action in under 10 lines.

Wrap any agent action with @record.capture(...). The SDK seals a four-strata Evidence Package before the action returns, signs it with your key, and writes it to your storage. Nothing leaves your environment.

Inspect a packet A signed sample Evidence Package, ready for your editor.

V0.1 schema, four strata (transaction, configuration, behavior, mandate), customer-held key, deferred RFC 3161 timestamp. Drop the file into your editor to see exactly what an Evidence Package looks like before you wire one up.

1. Install

Python · verdra-recordfrom source · works today
# requires Python 3.11+
# clone the verdra repo, then:
pip install -e ./sdk/python/verdra-record
Python · verdra-recorddirect from git
# with repo credentials configured:
# repository URL provided per engagement
pip install verdra-record
Python · verdra-recordafter PyPI release
# PyPI release follows V0.1 schema freeze:
pip install verdra-record
TypeScript · @verdra/recordroadmap
// the TypeScript package tracks the Python schema; ETA Q3 2026
npm install @verdra/record
// or: pnpm add @verdra/record · bun add @verdra/record

2. Quickstart, Python

Wrap any agent action with @record.capture(...). The SDK reads the runtime configuration at the call site, runs the four-strata capture, signs the package with your customer-held key, and writes it to your storage.

Python · LangGraph runtimequickstart.py
from verdra_record import Record
from langgraph.graph import StateGraph

# customer-held signing key + customer-controlled storage
record = Record(
    principal="Orion Treasury Corp.",
    storage="s3://orion-evidence/verdra/",
    signing_key="./orion.ed25519.priv",   # or raw 32-byte seed
    schema_version="verdra/v0.1",
)
# Production engagements wire signing through KMS (AWS KMS, GCP KMS,
# Azure Key Vault, or HSM); see /security for the integration pattern.

@record.capture(
    strata=["a", "b", "c", "d"],
    configuration={"model": "claude-sonnet-4-5", "tools": ["pay"], "spend_cap": "5000 USDC/day"},
    mandate={"delegation": "dlg_4b2e", "scope": ["pay", "ship"], "expires": "2026-12-31"},
)
def issue_payment(graph: StateGraph, mandate: dict) -> dict:
    # your existing agent logic, unchanged
    return graph.invoke(mandate)

# every call produces a signed Evidence Package in your bucket
result = issue_payment(graph, mandate={"to": "vendr-fulfill-2", "amount": "1847.20 USDC"})
# result["_verdra_package_id"] => "EP-..."  (also retrievable via the SDK return)
V0.1 → V1.0 Today (V0.1): the Python SDK ships per engagement against your runtime, signs with a customer-held Ed25519 key, persists to file:// or s3:// storage, and verifies offline. The schema is frozen in the public Rules; the integration surface is what we tailor per engagement. V1.0 schema freeze makes the framework adapters generic. LangGraph, LangChain, AutoGen, Semantic Kernel, OpenAI Agents stop being engagement-specific and ship behind a stable schema. RFC 3161 timestamping closes alongside the freeze, disclosed in each package as a forward commitment under Rules P.5.

3. Quickstart, TypeScript

TypeScript · OpenAI Agents SDKquickstart.ts
import { Record } from "@verdra/record";
import { Agent, tool } from "@openai/agents";

const record = new Record({
  principal: "Orion Treasury Corp.",
  storage: "s3://orion-evidence/verdra/",
  schemaVersion: "v0.1",
});

const issuePayment = record.capture(async (mandate) => {
  const agent = new Agent({ name: "orion-procure-7" });
  return await agent.run(mandate);
});

// every call produces a signed Evidence Package in your bucket
await issuePayment({ to: "vendr-fulfill-2", amount: "1847.20 USDC" });

4. Runtime adapters

The base @record.capture(...) decorator works against any callable today. The framework adapters below wrap idiomatic hook points in each runtime so you don’t have to thread the strata through manually; they ship behind the V0.1 schema freeze on the cadence noted in each card. Until then, use the base decorator with explicit configuration={...} and mandate={...}; see §2 above.

Base decoratorPY
@record.capture() The canonical V0.1 surface. Hand the four strata in via configuration={...} and mandate={...}; the SDK signs, persists, and verifies. Works against any callable, including in-house runtimes. Today
LangGraphPY · TS
verdra-record-langgraph Wraps the graph node executor. Captures S(b) from the compiled graph spec; one EP per node invocation. V1.0 roadmap
LangChainPY · TS
verdra-record-langchain Decorates Tool / StructuredTool. Captures S(a) at tool dispatch and S(c) over the chain trace. V1.0 roadmap
AutoGenPY
verdra_record.autogen Conversable-agent message hook. Captures multi-agent handoffs as a linked EP chain (one per assistant action). V1.0 roadmap
CrewAIPY
verdra_record.crewai Task-execution callback. Captures crew composition and role config in S(b); one EP per Task.execute(). V1.0 roadmap
Semantic Kernel.NET · PY
Verdra.Record.SemanticKernel Kernel function-invocation filter. Captures plugin manifest in S(b); planner output in S(c). V1.0 roadmap
OpenAI AgentsTS · PY
@verdra/record-openai-agents Wraps Agent.run(). Captures tool inventory and instructions hash; native streaming preserved. V1.0 roadmap
Anthropic ToolsTS · PY
@verdra/record-anthropic Intercepts tool_use blocks in messages.create. Captures system prompt hash and tool schemas in S(b). V1.0 roadmap
Google ADKPY
verdra_record.google_adk Agent-Development-Kit before/after-tool hook. Captures Vertex model and ADK runtime config in S(b). V1.0 roadmap

5. Evidence Package shape

Every captured action produces an Evidence Package conforming to the public Verdra Rules schema. Top-level fields:

FieldTypeDescription
idstringContent address: EP- + first 32 hex chars (128 bits) of BLAKE3-256 over the canonical body, excluding id and signature.
schemastringSchema version pin, e.g. verdra/v0.1.
principalstringCustomer-supplied principal identifier; informational, not validated by the schema.
captured_atstringISO 8601 / RFC 3339 UTC timestamp at millisecond precision.
strata.aobjectTransaction stratum: counterparty, payload, rail, reference, timestamp.
strata.bobjectConfiguration stratum: prompt hash, tool inventory, model + version, spend caps at dispatch.
strata.cobjectBehavior stratum: counterfactual decision trace, tool calls, latencies.
strata.dobjectMandate stratum: principal-signed delegation, scope, limits, expiry.
signed_withobjectAlgorithm + public key, bound into the signed canonical body. Tampering with either changes the recomputed id and breaks the signature. {algorithm: "ed25519", public_key: "ed25519:<hex>"}.
timestampobjectRFC 3161 timestamp token from an external authority. V0.1 records {mode: "deferred"} as a forward commitment per Rules P.5.
storageobjectCustomer-controlled storage URI. Verdra has no write path.
signatureobjectCustomer Ed25519 signature over the canonical body. {value: "<128-hex>"}; algorithm and pubkey live in signed_with so they are part of the signed bytes.

6. Verifying a package

Python · from your shellCLI verify
# anyone with the public key can verify, offline:
verdra-record verify ./EP-ed594af8f57ff7c6a5a290ea78b4ffc1.ep.json \
    --pubkey ./orion.ed25519.pub
# [OK] EP-...  schema=verdra/v0.1
#   signature_valid:        True
#   content_address_matches:True
#   timestamp_valid:        False  (RFC 3161 deferred, forward commitment per Rules P.5)
Python · verifying programmaticallyverify.py
from verdra_record import verify_package

# adjudicators, counsel, auditors, or counterparties can verify offline
# using only the public schema and the customer's pubkey.
result = verify_package(
    "./EP-ed594af8f57ff7c6a5a290ea78b4ffc1.ep.json",
    pubkey="./orion.ed25519.pub",    # raw 32 bytes, or "ed25519:<hex>" text form
)

assert result.signature_valid
assert result.content_address_matches
# result.timestamp_valid is False in V0.1 (TSA deferred); see notes:
for note in result.notes:
    print(note)

7. What the SDK does not do