Repository navigation
Concepts Storage and Performance
The signer sits in the path of every tool call, so it has to be fast, and its log has to survive crashes without losing what it acknowledged or hiding what it lost. This page explains how records are written and stored, what each durability mode guarantees, and what the signer costs per call.
Every record goes through one writer thread. It takes up to 512 queued requests at a time and, for each one inside an
undo log, assigns sequence numbers, computes hashes, signs, and appends the records and their Merkle leaves to storage
in one batch. A refused request leaves no partial state behind. If storage fails mid-batch (a disk error, a full disk),
the whole batch rolls back and callers get unavailable; when storage recovers, the signer writes a signed
signer_unavailable gap. One writer is what lets the signer, not the agent, decide the order of everything.
| Backend | Layout | Single writer enforced by |
|---|---|---|
| File store |
records.jsonl, the registry, checkpoints, Merkle tiles and periodic snapshots in the signer's data directory |
A lock file |
| Postgres (14 or newer) | Tables for records, registry, notes, tiles and snapshots, written by a role that can only insert | A session advisory lock; each batch is one transaction |
Network filesystems (NFS, SMB, FUSE and the like) aren't supported for the data directory, because file locking and
fsync can't be trusted there; tracekit doctor flags one (D-DATA-FS).
| Mode | A call returns after | Risk |
|---|---|---|
ack-on-write (default) |
The record is written; the file store syncs within a few milliseconds, Postgres commits asynchronously | A power loss can lose the last acknowledged records |
ack-on-fsync |
The record is synced to disk (or the WAL is flushed) | Slower per call |
tracekit doctor warns when a production signer uses ack-on-write.
tracekit signer fsck checks every line, hash, both chains, every signature, the registry, checkpoints and tiles. The
signer also runs it in the background once a day; a problem it finds becomes a signed trace.tamper{edited}, and client
writes stop until a restart. Every time the store is opened, the last 1,024 signatures are re-verified.
| Experiment | Result |
|---|---|
kill -9 of the signer, 30 rounds under 8 concurrent clients (E15) |
No acknowledged record lost in either mode; every unacknowledged call either reached the store or is covered by a signed gap. Power loss isn't tested: kill -9 keeps the operating system's cache |
| Signer down, closed tool class (E14) | 20 of 20 calls blocked |
| Signer down, open tool class (E14) | 20 calls ran, then one signed gap covering them |
| Network partition to an HTTPS signer (E14) | Each call waits the client timeout (one second), then follows its fail mode; afterwards latency returns to normal |
| Disk full (E14) | 41 calls acknowledged, none lost, one signer_unavailable gap |
| Witness down (E14) | Signed gaps while it's down; checkpoints cosigned after it recovers |
| Measurement | Result |
|---|---|
| v2 signer, file storage, one client calling decide and complete | 0.45 ms median, 0.91 ms p99 per call |
| v2 signer, file storage, throughput with 4 clients | 5,356 events a second |
| v2 signer, Postgres | 0.59 ms median, 5.17 ms p99 per call |
v2 signer, file storage, ack-on-fsync
|
about 7 ms median, 10 ms p99 per call |
| v1 coding-agent hooks | about 70 ms per hook on Linux, mostly starting Python |
| A real agent app with Tracekit added | 1.6% more wall time |
The signer figures are a short run on one macOS machine and are informational. The design's targets (p99 at most 5 ms per call, at least 1,000 events a second) are enforced on Linux in CI; on that run Postgres's p99 is just over the target. Full tables: evaluation and the technical report.
Default quotas per caller identity: 200 events a second (bursts of 400), 100 open runs, 100 pending approvals, 8
approval waits at once, and 64 event streams per run. Calls a gateway makes for its clients count per gateway and
client, so one agent behind a shared gateway can't use up every other agent's budget. A refusal is
quota_exceeded with a retry time, and the refusals of a window are folded into one signed refusal.summary.
Deployment: storage and durability · doctor · the writer:
tracekit/signer/pipeline.py · storage: tracekit/storage/
Previous: Deployment and isolation · All concepts · Next: Integrations
Generated from docs/ at v1.4.1. Edit the docs in the repository, not here.
Get started
- Quickstart: the v2 signer
- Quickstarts
- Quickstart: Claude Agent SDK
- Quickstart: a custom agent
- Quickstart: LangChain and LangGraph
- Quickstart: MCP client
- Quickstart: OpenAI Agents SDK
- Coding agents other than Claude Code
- tracekit doctor
- Walkthrough: Tracekit end to end
How it works
- How Tracekit works
- Overview
- The life of a tool call
- The evidence format
- Verification and assurance
- Witnesses and monitoring
- Policy
- Approvals
- Detection and containment
- Capture and completeness
- Custody
- Provenance and tracekit why
- Deployment and isolation
- Storage, durability and performance
- Integrations
- Security model
- Architecture
- tracekit why: architecture
Integrations
- Integrations
- Adapters
- OpenTelemetry
- Remote clients
- Kubernetes agent-sandbox
- agentgateway
- agentsh and Tracekit
- Browser Use
- Claude Agent SDK
- Claude Code's sandbox
- Codex's sandbox
- CrewAI
- Docker MCP Gateway
- E2B
- Falco
- Gemini CLI's sandbox
- Google ADK
- Haystack
- LangChain v1
- LiteLLM
- LlamaIndex
- MCP client
- microsandbox
- Microsoft Agent Framework
- OpenAI Agents SDK
- NVIDIA OpenShell
- Pydantic AI
- sandbox-runtime's proxy on its own
- Strands Agents
- Tetragon
- Vercel AI SDK
- Wassette
Policy and approvals
- Policy reference
- Approvals
- Findings
- Reading the model's reasoning
- Incidents and containment
- Webhooks
Deploy and operate
- Deploying the signer
- The signer as a container
- The signer on Kubernetes
- The compose stack
- Identity
- Tool executor
- MCP gateway
- LLM gateway
- Egress observation
- Witnesses
- Log monitor
- Record-key issuer
- Signer observability
- Viewer
- tracekit why: causal investigation and replay
- Migrating
- Platforms
Verify the evidence
- Reading a v2 verify report
- Evidence format v2
- Auditor guide
- Sample evidence bundle
- Signing
- What Tracekit guarantees
Security and privacy
- Threat model: the v2 signer
- Threat model: the v1 laptop signer
- HTTP security checklist
- Threat-model review packet
- Privacy
- Known limits and trade-offs
- What's stable
Compliance
- Compliance mapping
- EU AI Act
- ISO/IEC 42001
- NIST AI RMF and the Generative AI Profile
- OWASP Top 10 lists for LLM and agentic applications
Evaluation
Demos
- Demos
- Agent approvers within bounds
- Completeness and tamper evidence
- Detection and containment
- Network coverage: an egress observer
- Guardrails: allow, deny, or ask a person
- MCP tools, gated and recorded
- Prompt injection held by provenance
- Why: which input caused the action
Help