Golem docs

Guides

How do I prove what an AI agent did, for an incident or an auditor?

What evidence an investigator or auditor needs about an agent's actions, how to keep chain of custody, and a worked offline check of a Golem evidence export with verify.py.

"The agent did it" is a claim. Evidence is a record that answers who, what and when, and that someone who does not trust you can check was not changed afterward. The same standard applies whether the reader is your incident team, an auditor, or a lawyer.

What the evidence has to show#

  • Who: which agent, on which machine, acting for which person, under which credentials.
  • What: each tool call, its arguments and result, and what the agent was asked to do.
  • When, and in what order.
  • Under which rules: what was allowed, refused or approved, and by whom.
  • That it is complete and unchanged: nothing removed, nothing added later, nothing edited.

Doing it without special tooling#

  1. Preserve early. Copy the agent's own transcripts (for Claude Code, the JSONL files under ~/.claude/projects/) before cleanup removes them, along with shell history, git history and any telemetry already collected.
  2. Hash what you collect with SHA-256 at the moment you collect it, and write down who collected what, from where, and when. That record is your chain of custody.
  3. Store the copies read-only, somewhere the people involved cannot reach.
  4. Corroborate. Line the transcript up against git commits, CI runs, cloud audit logs and the model provider's usage records. Independent sources that agree are stronger than any one.

This is sound practice, and it is what most teams can do today. Its weakness is the source. The transcript was written by the agent's own process on the machine under investigation. Your hashes prove that nothing changed after you collected it, not before. If the session was hijacked, or someone edited the file, the copy you preserved is the edited one.

Where Golem fits#

Golem's record is written by something other than the actor. The Golem agent on each machine signs an entry for every call before anything leaves the machine, chains each session's entries, and sends the raw payload to your storage with only its hash in the record. Golem's service also signs every triage decision, case event and export into a workspace evidence chain, so a person's decisions sit in the same record as the calls they were about. Every 15 minutes, when anything has changed, a Merkle root is taken over the tip of every chain, which bounds when entries existed. See The signed record.

An evidence export#

On a case, Export evidence downloads a signed zip of everything the case rests on: the case and its timeline, every session chain it cites in full with the machines' public keys, the evidence chain and the entry recording this export, every flag in scope with totals that must reconcile, the rules and settings in force, a Merkle proof, a readable summary, and the verifier, verify.py. Tick Include payload bodies to add the stored payloads. See Evidence export.

Checking it offline#

The person checking needs Python 3 and two libraries, not a Golem account or network access:

pip install cbor2 cryptography
python3 verify.py golem-evidence-....zip

It prints one line per check and ends with VERIFIED or FAILED (n problems), exiting 0 only when everything verifies. In order, it checks that every file matches the signed manifest; the manifest's signature; that the evidence chain links and each entry's signature verifies; that the export's own entry commits to this manifest; that each session chain links and verifies against the machines' keys; that each included payload hashes to what its entry signed; that the flags reconcile; and that the Merkle proof covers the evidence chain's tip. Lines marked note are not failures: a chain segment that starts partway through, or payloads left out.

An auditor who does not want to trust the copy inside the zip can download verify.py separately and compare, and can read the record format to write their own.

Identity, stated carefully#

Every entry names the machine, proven by its key, and the agent client the call came through. The console separates a verified agent (one that presented a Golem-issued token, signed into the entry), an observed identity (read from an OAuth token an MCP server received, not verified by Golem), and an accountable owner (a person your administrators assigned, never signed, so a correction does not leave a wrong name sealed). See Which agent did it.

What it does not prove#

  • Tamper-evident, not tamper-proof. A passing check means nothing changed after signing by anyone without the signing keys. On macOS and Windows the machine's identity key is a software key file; on Linux it is generated in a TPM 2.0 when one is usable. See Hardware-backed keys.
  • Only what passed through Golem. Commands you type yourself, AI tools Golem is not wired into, and Claude Code's prompts without OpenTelemetry are not in the record. See Coverage.
  • Not a compliance verdict. The SOC 2 and ISO 27001 reports Golem builds for your workspace mark each control as evidence provided or needing attention, never as satisfied. That judgement is your auditor's.
  • Limits per export: at most 500 sessions, 200,000 entries, 2,000 payloads and 64 MB. Exporting a period rather than a case is available through the API only.

To keep a case, its flags and its conversations from being deleted by retention while an investigation runs, place a legal hold. Payloads in your own storage follow your own retention settings.

Updated 2026-10-15 · This page as Markdown