Pragmatic

How it works.

Pragmatic sits between your agent and the models and tools it uses, and writes down each request and answer before the agent sees it. If the agent crashes, it picks up from that record without repeating finished work. You can replay the run from the record without calling the model, and with 0.6, in preview, an auditor can check it without trusting you.

In your code

One wrapper, no new framework.

Keep your agent as it is. Wrap the Anthropic or OpenAI client you already use, and hand tool calls to ctx.run_tools. Model calls through the wrapped client, and tool calls through ctx.run_tools, are now on the record.

Crash halfway through, and resume reads every finished call back from the journal instead of paying for it again.

research_agent.py

import anthropic, pragmatic

rt = pragmatic.Runtime("./journals")

def research(ctx):
    client = ctx.wrap(anthropic.Anthropic())        # wrap the client you already use
    messages = [{"role": "user", "content": "Find papers on durable execution."}]
    while True:
        msg = client.messages.create(model="claude-sonnet-5-5", max_tokens=1024,
                                     tools=TOOLS, messages=messages)
        messages.append({"role": "assistant", "content": msg.content})
        if msg.stop_reason != "tool_use":
            return msg.content[0].text
        messages += ctx.run_tools(msg, {"search": search})   # tools, on the record

rt.run("research-42", research)       # record
rt.resume("research-42", research)    # finished calls are not repeated
rt.replay("research-42", research)    # audit: the model is never called
rt.verify("research-42")              # the hash chain is intact

Python and Rust today, with C++, Java, Go and Node bindings over one C interface. Version 0.5 is not yet a packaged release; install it from source.

A record, not a trace. A trace helps you watch a run. A record lets someone else check it, months later, without taking your word for it.

The record

What happens on every call.

The journal · in 0.5

Append-only and hash-chained.

Each entry carries a SHA-256 fingerprint that covers every entry before it. Change anything in the past and every later fingerprint stops matching, starting at the entry that was changed. A journal can also be keyed with a secret, so someone without the key cannot rebuild the chain to hide an edit.

Capture · in 0.5

Through the official SDKs.

ctx.wrap hands back your Anthropic or OpenAI client, used exactly as before, with its model calls going through the journal; other methods on the client pass through unrecorded. Each response is written down before your agent can read it and comes back as the same SDK type on replay. In 0.5, streaming and .parse() are refused inside a run rather than quietly bypassing the journal. In 0.6, capture moves down to the HTTP layer, so streaming and agent frameworks can be recorded too.

Replay · in 0.5

The model, switched off.

Replay runs your agent against the journal with a stand-in model that refuses to answer, so the model is never called. Mark the agent with @pragmatic.durable and its source fingerprint is recorded too, so replay refuses a changed agent before it starts. Without it, replay stops with an error at the first step that differs from the record. Either way, it does not report a run that never happened.

Crash recovery · in 0.5

Resume without repeating work.

Resume reads the journal back into your agent. Model responses come from the record, finished tool calls are not run again, and recording continues from where the run stopped. A call cut off mid-flight runs again: a model call still waiting for its reply is sent again, and a tool call runs again by default. Pass a recover policy to mark a tool call done instead.

Branches · 0.6 preview

Parallel work, replayed in order.

Work an agent does in parallel is recorded on separate branches, so replay gives each branch its own results no matter which one finished first. Random draws join model calls, tool calls, inputs and clock reads on the record.

Pragmatic Server · design-partner preview

The record, shared and witnessed.

Shared store

One home for every run.

Agents write to the server instead of local files. A lease lets one process write a run at a time, so a crashed run can resume on another machine without two writers colliding. You run the server in your own environment, and the data stays wherever you put it.

Independent anchoring

Fingerprints, countersigned outside.

On a regular schedule, the server folds the latest fingerprint of every run into one log and sends that log’s fingerprint to independent timestamp authorities, and optionally to a witness. From then on, rewriting that part of the history would be detected, even if the person rewriting it runs the server, as long as the auditor checks against a witness they trust. Only fingerprints leave the server, never content.

Retention and erasure

Keep what you must, erase what you must.

Retention rules keep each kind of run for at least as long as you set, then erase its content or delete it. Legal holds pause both. Erasure removes chosen pieces of content, or every piece that contains a given text such as an email address, and records who did it and why. Every fingerprint stays, so the rest of the run still verifies.

Roles and access log

Who could see what, and did.

Tokens carry a role (agent, auditor or admin) and the runs they may touch. Auditors see redacted content unless they are allowed raw access. Every request, refused ones included, goes into an access log that is itself a journal, anchored like any run.

Evidence and console

One file per run, and a place to look.

An evidence bundle holds a run’s journal, its anchors and the witnesses’ signatures in one file, with content redacted if you choose. The console shows each run’s timeline and its verification and anchoring status, and lets admins manage holds, erasure and tokens.

How an auditor checks a run · 0.6 preview

The auditor needs the evidence file, the open-source pragmatic command-line tool, the root certificates of the timestamp authorities they trust, and OpenSSL, which most systems already have. No account with us, and no access to your systems.

the auditor’s terminal

pragmatic verify-evidence research-42.evidence.json \
    --tsa-roots digicert-root.pem \
    --tsa-roots sectigo-root.pem

The verifier rebuilds every fingerprint in the journal, checks that each erased piece of content has a matching erasure record, checks each anchor against the countersigned checkpoint, and checks each timestamp against the roots the auditor supplied. Nothing in the file is treated as a source of trust. It ends with one of four answers:

  • VERIFIED: the whole run is anchored by at least two independent operators.
  • VERIFIED (PARTIAL): an earlier part of the run is anchored, and the report says how many later entries are not.
  • UNANCHORED: the journal is intact, but no anchor has enough independent witnesses.
  • FAILED: something does not match, and the report says what.

What a verified anchor proves: the first entries of the run, with that exact fingerprint, existed no later than the stamped time. It does not prove that what was recorded was true, that nothing happened outside Pragmatic’s interfaces, or anything about a run before its first anchor.

Next In practice