MCP gateway you deploy: a Tracekit signer decides and signs each call; agents send each run's token.
Tracekit checks every tool call your agent makes before it runs, signs each call and decision into a hash chain,
and gives you one .tkb file per run that anyone can verify offline.
8 of 8tamper attacks caught480 trials, with a witness (E1) |
500 of 500harmful calls stopped11 classes, 1 false alarm in 692 (E17) |
< 1 msadded per tool call0.91 ms at p99, signer round trip (E9) |
8 of 8insider attacks caughta merge gate on every PR (E8) |
Built like Certificate Transparency: signed records in an append-only log that independent witnesses cosign
Open file format · verifiers in Python and TypeScript · MIT · runs on your own machines
Try it · Add it to your agent · What it proves · What's in it · Proof · How it works · Pilot it · Contribute · Docs
When an agent does something it shouldn't, you ask three things: what did it do, was it allowed, and can you trust the record? The agent's own log can't answer the third, because the agent can edit it. Here is one run, recorded both ways:
The same run, recorded: the database, the signer, the viewer and both edits are real; the model is scripted. Watch it with sound (1:47)
In this demo the signer ran as the agent's own user (dev mode), so an agent that knew how could have read the key and re-signed the log. Run the signer where the agent can't reach it, with a witness, and it can't.
uvx --from tracekit-ai tracekit demo --server
No API key, and nothing to install with uv. From an empty cache on a Mac it took 5
seconds (10 with pip install tracekit-ai in a fresh venv). The package is tracekit-ai: tracekit on PyPI is an
unrelated project. A scripted agent makes three calls, and you should see:
== agent run (SCRIPTED: fixed tool calls, not a model)
Bash 'ls': allow
Bash 'sudo rm -rf /': deny TK-D001 TK-D004 TK-F003
Bash 'echo "unterminated': ask TK-SHELL-PARSE
...
Integrity: VERIFIED.
== tamper test: rewrite the denied call as allowed in a copy, then verify again
[FAIL] signatures — 11 record(s), keys valid at their position
seq 4: hash does not match the event
Integrity: FAILED.
The delete was denied before it ran, the held call ran after an approval, and the run verified. Then the demo rewrote the denial as allowed in a copy, and verification failed at the record it changed.
Three lines:
pip install tracekit-ai
import tracekit; tracekit.instrument() # the first line of your agent; then run it as usual
tracekit last # Integrity: VERIFIED. / Assurance: dev; ...
tracekit.instrument() starts a dev signer (or reuses the running one) and gates and records every tool and model call
of the frameworks it finds. tracekit last exports your latest run, verifies it and says where it is.
tracekit view --dev shows every run. On a clean machine the LangGraph example (a mock model, no API key) installed,
ran and verified in 27 seconds: examples/v2/clean-machine.sh langchain.
Stable: Claude Code, the OpenAI Agents SDK, LangChain / LangGraph, the Claude Agent SDK and MCP. Experimental: Codex CLI, Cursor, Gemini CLI, CrewAI, Browser Use, Pydantic AI, Google ADK, Haystack, LlamaIndex, Microsoft Agent Framework, Strands Agents and the TypeScript SDK. Setup: coding agents · OpenAI Agents SDK · Claude Agent SDK · LangChain / LangGraph · MCP · CrewAI · Browser Use · Pydantic AI · Google ADK · Haystack · LlamaIndex · Microsoft Agent Framework · Strands Agents · TypeScript · Vercel AI SDK · OpenTelemetry · any other agent
Coding agents: tracekit init --dev --v2 wires Claude Code's hooks to a dev signer; add --agent codex, cursor or
gemini for the others (experimental). Without uv: pip install tracekit-ai, then tracekit demo --server. --why
(experimental) shows a held
email whose cause is found by replay and cited by its signed record:
tracekit demo --server # exit 0
tracekit demo --why # exit 0
tracekit init --dev --v2
From a checkout, the shipped sample bundles (v1) check with the verifier alone (pip install --no-deps tracekit-ai is
enough), and python examples/v2/langchain/agent.py --scripted runs a LangGraph agent with a mock model:
tracekit verify docs/sample/demo-run.tkb --key docs/sample/signer.pub # exit 0
tracekit verify docs/sample/demo-run-tampered.tkb --key docs/sample/signer.pub # exit 1
TypeScript needs Node 18 or newer: npm install @cygnuxlabs/tracekit, and npx @cygnuxlabs/tracekit up starts a dev
signer without Python on Apple Silicon Macs, Linux and Windows (TypeScript SDK). Python 3.9 to
3.13; the framework integrations need 3.10 or newer.
Three guarantees. They're related, but one doesn't give you the others, and each needs something different.
| Guarantee | What you get | What it needs |
|---|---|---|
| Evidence integrity | A record that was edited, deleted, swapped or inserted fails verification at that record | Only the signed log. Cutting off the end of the log, or re-signing it with a stolen key, takes a witness to catch |
| Execution control | Each call is checked before it runs. A denied call is blocked; a held call runs only after a yes, with exactly the arguments that were approved | The call goes through Tracekit: an SDK, a hook or a gateway. Code that skips it isn't stopped |
| Independent assurance | An operator who rewrites or forks its own log is caught | A witness the operator doesn't control, and a monitor. Both are experimental, and no public witness is running yet |
isolation: same-user
(FAQ).What each deployment guarantees, from dev mode to a signer the agent can't reach: guarantees. Every limit, with what to do about it: limits.
One signer. The core is stable and is hardened first. The rest ships in the same package as experimental: it works and is tested, but may change between releases (what's stable).
| Core | What it does | Measured |
|---|---|---|
| Record | Every tool call, decision and result in one signed hash chain per run. A lost event becomes a signed gap, never silence | 6 of 8 tamper attacks caught by the log alone (E1) |
| Decide | Allow, deny, or hold each call for a person, before it runs. Packs for shell, files, SQL, HTTP, cloud CLIs, browsers, email, messaging, payments, secrets and MCP | 500 of 500 harmful calls stopped, 1 false alarm in 692 (E17) |
| Approve | A held call runs only after a yes from the command line, bound to its exact arguments and used once (approvals) | Edited arguments, a replayed snapshot or another run's approval: refused, in the contract tests every stable framework integration runs |
| Prove | tracekit verify checks a run's file offline against keys you pinned | 8 of 8 insider attacks caught (E8) |
| Watch | tracekit view: every run verified, blocked and held calls, approvals, gaps, replay and a run review (viewer) | Not measured |
| Experimental | What it does | Measured |
|---|---|---|
| Witness | Independent witnesses cosign each checkpoint; a monitor watches the log for rewrites and forks | 8 of 8 tamper attacks caught with a witness (E1) |
| Cross-check | The signer compares the calls the model asked for, as an LLM gateway or the session transcript saw them, with the calls the agent reported. A skipped hook or a made-up call is flagged | 12 of 12 seeded discrepancies flagged, 0 false (E10) |
| Contain | Signed incidents hold or quarantine a run. Tools run on credentials the agent never holds (executor, MCP gateway). An egress observer flags traffic no call explains | 8 of 8 containment and 10 of 10 detection checks (E17) |
| Explain | Where each argument came from, and tracekit why: which input caused an action, found by replaying the run without it | 6 of 6 true causes named, 0 false blames, one 7B model, small sample |
| More approvers | A web page with passkeys, Slack, or a reviewer agent that approves within bounds | 7 of 7 abuse cases against agent approvers caught (E18) |
Our own experiments: small, synthetic and written by us. Nothing rounded up. The misses stay in.
| Experiment | Setup | Result |
|---|---|---|
| E1 tamper detection | 120-record signed logs, 8 attacks, 60 trials each, re-run on 1.2 | 6 of 8 caught by the log alone, 8 of 8 with a witness |
| E8 insider attacks | Real unprivileged users against a Linux system-mode signer: a decoy signer, a stopped signer, a swapped policy, fabricated runs | 8 of 8 caught, a merge gate on every pull request |
| E17 policy packs | 500 harmful and 692 benign tool calls in 11 classes, decided by both regex engines | 500 of 500 stopped; 1 false alarm, a draft email held for a person |
| E10 reconciliation | 30 runs, 12 with a seeded discrepancy: a missing hook, a fabricated call, changed arguments | 12 of 12 flagged, 0 false positives |
| E9 overhead | Signer round trip over a Unix socket, file storage, macOS quick run | 0.45 ms p50, 0.91 ms p99 per call; 5,356 events/s |
| E3 the v1 regex gate, on a rougher set | 16 harmful and 20 benign calls written after the rules | 12 of 16 caught, 1 false alarm. Rules are tripwires, not a sandbox |
The two E1 misses are the design: a log can't see its own tail cut off, and whoever holds the key can re-sign it. Only
a copy of the head held elsewhere, a witness, catches those, so an unwitnessed run verifies as dev. The test sets
were written by us, and no one outside has reviewed the threat models yet. Every experiment, and what isn't
measured: evaluation ·
technical report.
TRACEKIT_SIGNER points it at the signer.| Where the signer runs | Who can reach the keys and log | Recorded isolation |
|---|---|---|
| Laptop dev | the agent's own user | same-user |
| Laptop system mode (Linux; macOS experimental) | root and the signer's OS user | separate-user |
| Container or Kubernetes sidecar | the signer's uid and the node's administrator | separate-user |
| Central signer over HTTPS (or Docker Compose) | the signer host's administrators | remote |
The operator who runs the signer could still rewrite its log with its own key; an independent witness and a monitor make that visible. Each mode end to end: deployment. The full model: architecture, laptop and server threat models.
| Use Tracekit when | A plain tracer is enough when |
|---|---|
| Your agent acts on real systems: a shell, files, databases, email, payments, the cloud | It only reads, or runs in a throwaway sandbox |
| Some calls must be stopped or held for a person before they run | Seeing what happened afterwards is enough |
| Someone outside the team has to trust the record: a customer, an auditor, an incident review | Only your team reads the logs, to debug |
For debugging a prototype, a tracer such as OpenTelemetry, Langfuse or LangSmith is the right tool. Tracekit doesn't replace one; it's the record you can hand to someone who doesn't trust the agent. How it compares with tracers, guardrail libraries and other tamper-evident logs, and when it's the wrong choice: comparisons.
Running an agent that acts on real systems, with someone who has to sign off on it: a customer, an auditor, an insurer? We'll set up Tracekit with you for two weeks, free: one agent, on your machines. At the end you have a verified evidence file for every run and a written review of what the agent did that you didn't expect. Email info@cygnuxlabs.com or open a pilot request.
tracekit demo --server # allow, deny, approve, then a tampered copy fails verification
tracekit up # start the dev signer, or find the running one
tracekit last # export your latest run, pin the dev key, verify it
tracekit view --dev # every run, verified: calls, decisions, gaps, replay, why
tracekit approvals list # calls held for a person; tracekit approvals approve ID
tracekit export --v2 --run ID -o run.tkb # one run as one .tkb file
tracekit verify run.tkb --trust trust.json # check it offline, against the keys and witnesses you pinned
tracekit policy lint policy.yaml # check a policy before the signer loads it
tracekit doctor # check this setup
tracekit init --dev --v2 # wire Claude Code's hooks; add --agent codex, cursor or gemini
.tkb file is a zip of records, inclusion proofs, checkpoints and the policy snapshots that
decided the calls. It holds no verification code.UNVERIFIABLE (needs tracekit >= x), never FAILED.Verify a v1 bundle in GitHub Actions with uses: Cygnux-Labs/Tracekit@main (bundle: and key: or witness:).
require-anchor defaults to true, so an unanchored bundle fails the step; set require-anchor: "false" to only
report it.
Each of these is useful on its own, and none needs to know the whole codebase:
tests/data/policy/deny/ with a rule
that catches it; E17 runs every case.To start: make install, then make check
(contributing). Smaller tasks are labelled
good first issue. Everyone taking part follows
the code of conduct.
| To | Start here |
|---|---|
| See every step on a clean install | walkthrough · recorded demos · viewer tour |
| Wire up an agent | v2 quickstart · coding agents · TypeScript SDK |
| Put the signer out of reach | deployment · compose · container · Kubernetes · doctor |
| Decide calls | policy reference · approvals · incidents · webhooks |
| Check evidence | reading a verify report · auditor guide · witnesses · monitor |
| Ask why an action happened | tracekit why · its architecture |
| Understand the design | architecture · evaluation · technical report · case study |
| Know what's stable | support · limits · FAQ · security checklist · changelog |
| Run the v1 laptop signer | coding agents · signing · v1 integrations |
MIT, Copyright Cygnux Labs. This is 1.3.0, and 1.x is the supported line. Report vulnerabilities privately as SECURITY.md describes.
@software{tracekit2026,
author = {{Cygnux Labs}},
title = {Tracekit: the tamper-evident flight recorder for AI agents},
year = {2026},
url = {https://github.com/Cygnux-Labs/Tracekit}
}
Agents can edit logs. They can't hide the edit. A star costs nothing and helps other teams find Tracekit.
Website · Evaluation · Limits · Contributing · IssuesThis listing does not have a supported local package template. Use the maintainer’s documentation for its hosted endpoint, authentication, and client-specific setup. No install command has been inferred.