Skip to main content

Capture verifiable, replayable records of your AI agent's decisions — the Python SDK for the Verifiable Decision Record standard.

Project description

Determs Python SDK

Verifiable Decision Records for AI agents — Python client.

Capture each LLM call as a structured, verifiable record. Persist records wherever you want. Verify and replay them later with the determs CLI.

This SDK is the open-core reference client for the Verifiable Decision Record specification.

Install

pip install determs

# With optional client SDKs:
pip install "determs[anthropic,openai]"

(Until the first public release, install from the built wheel in dist/: pip install dist/determs-0.1.0-py3-none-any.whl.)

Quick start — Anthropic

import anthropic
from determs.anthropic import wrap as wrap_anthropic
from determs.storage import FileStorage

client = wrap_anthropic(
    anthropic.Anthropic(),
    agent_id="support-triage",
    storage=FileStorage("./determs_records"),
)

response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=512,
    messages=[{"role": "user", "content": "Hi"}],
)
# A record file landed under ./determs_records/{action_id}.json.

Quick start — OpenAI

from openai import OpenAI
from determs.openai import wrap as wrap_openai
from determs.storage import FileStorage

client = wrap_openai(
    OpenAI(),
    agent_id="support-triage",
    storage=FileStorage("./determs_records"),
)

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Hi"}],
)

Storage backends

from determs.storage import FileStorage, StdoutStorage, CallbackStorage

# Write each record as <dir>/<action_id>.json
FileStorage("./records")

# Print each record as one JSON line on stdout — pipeable.
StdoutStorage()

# Hand the record dict to your own callback — for queues, custom sinks, tests.
CallbackStorage(callback=lambda record: print(record["agent_id"]))

Or pick a backend from environment variables:

from determs.storage import storage_from_env
storage = storage_from_env()   # honours DETERMS_STORAGE and DETERMS_DIR

Manual records

If you don't use the Anthropic or OpenAI SDKs directly (e.g. you call an inference service through your own HTTP client), build records explicitly:

from determs import build_record
from determs.storage import FileStorage

storage = FileStorage("./records")
record = build_record(
    agent_id="my-agent",
    model={"provider": "anthropic", "name": "claude-3-5"},
    params={"temperature": 0.0},
    input={"messages": [{"role": "user", "content": "Hi"}]},
    output={"content": "Hello.", "finish_reason": "stop"},
    context={"trace_id": "trace-001"},
)
storage.put(record)

Verify and replay

The determs binary is the verification surface. The SDK emits the record JSON; the CLI handles capture, replay, and verify.

# Bundle the action into a full record (input + execution + receipt):
determs capture --input ./records/act-xxx.json --output ./full.record.json

# Replay it later: returns 0 if bit-exact.
determs replay --record ./full.record.json

# Verify: returns 0 if no tampering, 1 if any digest mismatches.
determs verify --record ./full.record.json

Async clients

import anthropic
from determs.anthropic import wrap_async as wrap_anthropic_async

aclient = wrap_anthropic_async(
    anthropic.AsyncAnthropic(),
    agent_id="support-triage",
    storage=FileStorage("./records"),
)

response = await aclient.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=512,
    messages=[{"role": "user", "content": "Hi"}],
)

determs.openai.wrap_async(...) works the same way for AsyncOpenAI.

Streaming

stream = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=512,
    messages=[{"role": "user", "content": "Hi"}],
    stream=True,
)
for event in stream:
    handle(event)
# A record is emitted only when the stream completes naturally.
# If the caller stops iterating before the end, no record is written.

Async streaming uses async for after await client.messages.create(stream=True, ...).

What this SDK does and does not do

Does:

  • intercept messages.create (Anthropic, sync + async, streaming + non-streaming)
  • intercept chat.completions.create (OpenAI, sync + async, streaming + non-streaming)
  • accumulate streamed text, tool_use blocks, and tool_calls into a final record
  • emit records only on complete streams; abandoned streams produce nothing
  • build a well-formed action record consumable by the Determs CLI
  • persist records via a swappable storage backend
  • never let recording failures break the upstream LLM call

Does not yet:

  • support Anthropic's messages.stream(...) context manager (use messages.create(stream=True) instead)
  • support the OpenAI Responses API (use chat.completions instead)
  • talk to a Determs Cloud endpoint (phase 3)
  • ship a replay UI

Tests

cd sdk/python
pip install -e ".[dev]"
pytest tests/

The end-to-end tests in test_cli_compatibility.py require the determs binary built from the workspace root (cargo build or cargo build --release).

Build the wheel

cd sdk/python
pip install build
python -m build
# Produces dist/determs-0.1.0-py3-none-any.whl and dist/determs-0.1.0.tar.gz

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

determs-0.1.0.tar.gz (32.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

determs-0.1.0-py3-none-any.whl (25.7 kB view details)

Uploaded Python 3

File details

Details for the file determs-0.1.0.tar.gz.

File metadata

  • Download URL: determs-0.1.0.tar.gz
  • Upload date:
  • Size: 32.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for determs-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4a79c8a65b06217d9b4b03d09a8b01ef4ed66b0f6d911fe747a7f26e5105ce26
MD5 0fa78b3a1242bfb3bde9740922ddcbb7
BLAKE2b-256 30d55965cf947c51cff41ccc409761801a3557fa0cbad9a7a4eeda2839aac442

See more details on using hashes here.

File details

Details for the file determs-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: determs-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for determs-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e1141c1a4a612d076f5871d2eed98ef499a9e37780b50a45506d49fafbef6669
MD5 384f58bf85b26eda7e858dbc2bb86cbb
BLAKE2b-256 f115a7daf26f28710c89fb6d392a7a5f7ee91a7ccb3b9f92466a05c9c76ec5da

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page