Integrating Anthropic Claude
This is the canonical integration. The Verdifax SDK ships a one-call helper that takes a Claude prompt and response and returns a sealed manifest hash you can store alongside the model output.
Install
pip install verdifax anthropic
Two-call pattern
The simplest pattern: call Claude, then attest the result.
import anthropic
import verdifax
claude = anthropic.Anthropic() # picks up ANTHROPIC_API_KEY
resp = claude.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Summarize this document..."}],
)
output = resp.content[0].text
receipt = verdifax.attest_claude_response(
prompt="Summarize this document...",
response=output,
program_id="a" * 64, # your registered program id
route_id="claude-summarize-v1",
registry_record_hash="b" * 64, # your registry record hash
govern=True, # route the output through AIVP-T4 review
)
print(f"Claude said: {output}")
print(f"Verdifax seal: {receipt.manifest_hash}")
receipt.manifest_hash is the artifact you keep. It names this one run: every call seals its own admission clock and per-run nonce, so attesting the same prompt and response again produces a new run with a different hash. What holds every time is that the run's sealed record still recomputes to the hashes it recorded.
What govern=True does, and why you want it
Without it, the attest call seals exactly what your code submitted,
which proves submission, not that the model produced it or that the
answer should have gone out. With govern=True (SDK 0.5.0+), the
orchestrator routes the response text through the AIVP-T4 review
stage: an independent reviewer model examines it and can refuse it,
which halts the run before the execution record. The refusal is itself
sealed and anchored on the public log as an AivpT4HaltReceipt; when
the reviewer releases the output, the review outcome plus the
governed-output hash become part of the sealed record. A governed
run can therefore fail where an ungoverned one would quietly seal a
bad answer; that is the point.
Two honest notes. Governance adds the review outcome and the governed-output hash to the sealed record, which changes what each run's manifest covers, so it is opt-in; treat turning it on as a format change. And the reviewer is a second model, not an oracle: its verdict is sealed evidence of an independent check, not a guarantee the answer is right, see What the Manifest Hash proves.
Payload canonicalization: helper-specific prefix
Important: The Claude helper uses a helper-specific canonicalization format. This is NOT the canonical format for raw verdifax.attest() calls.
Inside the helper, Verdifax canonicalizes the prompt + response with a Claude-specific prefix, joining the five parts with the ASCII record separator (\x1e); the blocks below show one part per line:
verdifax.helper.claude.v1
verdifax.helper.prompt.v1
<prompt>
verdifax.helper.response.v1
<response>
Example: If you call:
verdifax.attest_claude_response(
prompt="What is 2+2?",
response="4",
...
)
The payload the helper sends (parts joined by \x1e, shown one per line) is:
verdifax.helper.claude.v1
verdifax.helper.prompt.v1
What is 2+2?
verdifax.helper.response.v1
4
This means an identical prompt + response pair sent through attest_openai_response() produces a different manifest hash than through attest_claude_response(). That's intentional, the same text under different providers is meaningfully different evidence.
Without the helper
If you want to attest Claude calls without the helper's prefix, build the payload yourself:
payload = f"prompt:{prompt}\nresponse:{response}"
receipt = verdifax.attest(
payload=payload,
program_id="...",
...
)
This will hash the raw payload without any provider-specific prefix. You lose the provider separation but gain full control over what bytes are sealed.
Reusing a connection pool
For high-throughput servers, share one VerdifaxClient:
from verdifax import VerdifaxClient
import anthropic
claude = anthropic.Anthropic()
verdifax_client = VerdifaxClient()
def attest_one(prompt: str) -> str:
resp = claude.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
)
output = resp.content[0].text
receipt = verdifax.attest_claude_response(
prompt=prompt,
response=output,
program_id="a" * 64,
route_id="claude-summarize-v1",
registry_record_hash="b" * 64,
client=verdifax_client,
)
return receipt.manifest_hash
Async (FastAPI / async workers)
from verdifax import AsyncVerdifaxClient
import anthropic
claude = anthropic.AsyncAnthropic()
async def attest_async(prompt: str):
resp = await claude.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
)
output = resp.content[0].text
async with AsyncVerdifaxClient() as v:
receipt = await v.attest(
payload=f"prompt:{prompt}\nresponse:{output}",
program_id="a" * 64,
route_id="claude-summarize-v1",
registry_record_hash="b" * 64,
)
return receipt.manifest_hash
What gets sealed
The helper sends Verdifax exactly two pieces of data: the prompt text and the response text. It does not send your Anthropic API key, conversation metadata, or system prompts. If you need those sealed too, build the payload yourself and call verdifax.attest() directly.
