Logs tell you something happened. Receipts prove it.
{
"mcpServers": {
"agent-receipts": {
"command": "npx",
"args": ["@agent-receipts/mcp-server"]
}
}
}I built ModQuote — a multi-tenant SaaS for automotive shops. During development, I used Claude Code extensively for auditing and fixing the codebase.
The problem: when something went wrong, I had no way to prove what input Claude received, what it changed, or whether the output matched what was expected.
With Agent Receipts, every Claude Code session now generates signed receipts:
- Input hash proves exactly what code Claude saw
- Output hash proves exactly what it produced
- Constraints catch when latency spikes or costs exceed budget
- Chains show the full sequence of a multi-step audit session
When a fix didn't work as expected, I could pull the receipt, verify the signature, and see the exact input/output hashes — no guessing, no "Claude must have misunderstood."
That's the difference between logs and receipts. Logs tell you something happened. Receipts prove it.
Add the Agent Receipts MCP server to your AI tool's config and every action gets a cryptographic receipt automatically.
Platform support: macOS, Windows, and Linux — requires Node.js 18+
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"agent-receipts": {
"command": "npx",
"args": ["@agent-receipts/mcp-server"]
}
}
}Add to .mcp.json in your project root:
{
"mcpServers": {
"agent-receipts": {
"command": "npx",
"args": ["@agent-receipts/mcp-server"]
}
}
}Add to .cursor/mcp.json in your project root:
{
"mcpServers": {
"agent-receipts": {
"command": "npx",
"args": ["@agent-receipts/mcp-server"]
}
}
}npm install @agent-receipts/sdkimport { AgentReceipts } from '@agent-receipts/sdk'
const ar = new AgentReceipts()
const receipt = await ar.track({
action: 'generate_report',
input: { query: 'Q4 revenue' },
output: { total: 142000 },
})
console.log(receipt.receipt_id) // rcpt_8f3k2j4n...
console.log(receipt.signature) // ed25519 signaturenpx @agent-receipts/cli init # Generate signing keys
npx @agent-receipts/cli keys # Show public key
npx @agent-receipts/cli list # List all receipts
npx @agent-receipts/cli verify <id> # Verify a receipt signature- Agent performs an action — API call, code generation, data lookup
- Input/output are SHA-256 hashed — raw data never leaves your machine
- Receipt is created — action, hashes, timestamp, agent ID, metadata
- Receipt is Ed25519-signed — with a locally generated private key
- Anyone can verify — share your public key; recipients verify independently
Memory in Agent Receipts is not a separate system — memory IS receipts. Every memory operation produces a signed, chained, auditable receipt.
memory_context — Get a structured summary of all memory for the current context
memory_observe — Store an observation about an entity (supports ttl_seconds for auto-expiry)
memory_recall — Search and retrieve memories
memory_forget — Soft-delete an observation or entity
memory_entities — List known entities (with duplicate detection)
memory_relate — Create a relationship between entities
memory_provenance — Trace a memory back to its source
memory_audit — Generate a memory audit report
const ar = new AgentReceipts()
// Context — get a structured summary of all memory
const context = await ar.context()
// Observe — store a memory (with optional TTL)
const { entity, observation, receipt } = await ar.observe({
entityName: 'Alice',
entityType: 'person',
content: 'Prefers TypeScript over JavaScript',
agentId: 'my-agent',
confidence: 'high',
ttl_seconds: 86400, // optional: auto-expire after 24 hours
})
// Recall — search memories
const { entities, observations } = await ar.recall({
query: 'TypeScript',
agentId: 'my-agent',
})
// Forget — auditable soft-delete
await ar.forget({
observationId: observation.observation_id,
agentId: 'my-agent',
reason: 'No longer relevant',
})npx @agent-receipts/cli memory context
npx @agent-receipts/cli memory observe "Alice" "person" "Prefers TypeScript"
npx @agent-receipts/cli memory recall TypeScript
npx @agent-receipts/cli memory entities
npx @agent-receipts/cli memory forget <observation_id>
npx @agent-receipts/cli memory audit
npx @agent-receipts/cli memory provenance <observation_id>
npx @agent-receipts/cli memory export
npx @agent-receipts/cli memory import memories.json- Entity — A typed object (person, project, preference, fact, etc.)
- Observation — A specific fact about an entity, linked to a receipt
- Relationship — A connection between two entities
- Provenance — Full chain from observation back to source receipt
-
Observation TTL — Set
ttl_secondson observations for automatic expiry - Duplicate Detection — Entities are deduplicated by name and type automatically
- Every operation creates a signed
receipt_type: 'memory'receipt - Deletion is always soft — forgotten memories are retained for audit
-
Quiet Recalls — memory reads don't create receipts by default; set
audited: truefor compliance - Memory Bundles — portable, verifiable export format with checksum and receipt verification
- System Prompts — ready-made prompts for Claude Code, Cursor, and other MCP clients
- Full-text search via SQLite FTS5 — no external dependencies
The MCP server exposes 24 tools that AI agents can call directly:
| Tool | Description | Key Parameters |
|---|---|---|
track_action |
Track an agent action with automatic hashing |
action, input, output, constraints
|
create_receipt |
Create a receipt with pre-computed hashes |
action, input_hash, output_hash, constraints
|
complete_receipt |
Complete a pending receipt with results |
receipt_id, output, status
|
verify_receipt |
Verify the cryptographic signature of a receipt | receipt_id |
get_receipt |
Retrieve a receipt by ID | receipt_id |
list_receipts |
List receipts with optional filtering |
agent_id, status, chain_id
|
get_chain |
Get all receipts in a chain ordered by timestamp | chain_id |
get_public_key |
Export the Ed25519 public key for verification | — |
judge_receipt |
Start AI Judge evaluation of a receipt |
receipt_id, rubric
|
complete_judgment |
Complete a pending judgment with results |
receipt_id, verdict, score, criteria
|
get_judgments |
Get all judgments for a receipt | receipt_id |
cleanup |
Delete expired receipts (TTL) | dry_run |
generate_invoice |
Generate an invoice from receipts in a date range |
from, to, format, agent_id
|
get_started |
Show a getting-started guide with usage examples | — |
memory_observe |
Store a memory observation about an entity |
entity_name, entity_type, content
|
memory_recall |
Search and retrieve stored memories |
query, entity_type, scope
|
memory_forget |
Soft-delete an observation or entity |
entity_id or observation_id
|
memory_entities |
List known entities with filtering |
entity_type, scope, query
|
memory_relate |
Create a relationship between two entities |
from_entity_id, to_entity_id, relationship_type
|
memory_provenance |
Get the provenance chain for an observation | observation_id |
memory_context |
Get a structured memory context summary |
scope, max_entities, max_observations
|
memory_audit |
Generate a memory operations audit report |
agent_id, from, to
|
memory_export_bundle |
Export memories as a portable, verifiable bundle |
entity_ids, include_receipts
|
memory_import_bundle |
Import and verify a memory bundle |
bundle, skip_existing
|
const ar = new AgentReceipts({
dataDir: '~/.agent-receipts', // optional, defaults to ~/.agent-receipts
})const receipt = await ar.track({
action: 'analyze_data',
input: { dataset: 'sales_2024' },
output: { summary: 'Revenue up 12%' },
agent_id: 'analyst-v2',
chain_id: 'chain_abc', // optional, auto-generated if omitted
parent_receipt_id: 'rcpt_prev', // optional, links to parent receipt
})const receipt = await ar.start({
action: 'long_running_task',
input: { job_id: '12345' },
})const completed = await ar.complete(receipt.receipt_id, {
output: { result: 'done' },
status: 'completed',
})const { verified, receipt } = await ar.verify('rcpt_8f3k2j4n')
// verified: true | falseconst receipt = await ar.get('rcpt_8f3k2j4n')const result = await ar.list({ agent_id: 'my-agent', status: 'completed' })
// result.data: ActionReceipt[]
// result.pagination: { page, limit, total, total_pages, has_next, has_prev }const publicKey = await ar.getPublicKey()
// 64-char hex string (Ed25519 public key)const receipt = await ar.track({
action: 'generate_summary',
input: { document_id: 'doc-q4-2024' },
output: { summary: 'Revenue grew 12% YoY...' },
latency_ms: 1200,
cost_usd: 0.005,
constraints: [
{ type: 'max_latency_ms', value: 5000 },
{ type: 'max_cost_usd', value: 0.01 },
{ type: 'min_confidence', value: 0.8 },
],
})
// receipt.constraint_result.passed → true/falseconst judgments = await ar.getJudgments('rcpt_8f3k2j4n')const context = await ar.context({
scope: 'user', // optional: agent | user | team
maxEntities: 10, // optional: top entities by observation count (max: 50)
maxObservations: 20, // optional: most recent observations (max: 100)
})
// context.entities, context.recent_observations, context.relationships,
// context.preferences, context.stats, context.receiptconst { entity, observation, receipt } = await ar.observe({
entityName: 'Alice',
entityType: 'person',
content: 'Prefers concise responses',
agentId: 'my-agent',
confidence: 'high', // certain | high | medium | low
scope: 'user', // agent | user | team
})const { entities, observations } = await ar.recall({
query: 'TypeScript',
entityType: 'preference',
agentId: 'my-agent',
})await ar.forget({ observationId: 'obs_abc', agentId: 'my-agent' })
await ar.forget({ entityId: 'ent_abc', agentId: 'my-agent' })const { data, pagination } = await ar.entities({ entity_type: 'person' })await ar.relate({
fromEntityId: 'ent_alice', toEntityId: 'ent_project',
relationshipType: 'builds', agentId: 'my-agent',
})const chain = await ar.provenance('obs_abc')const report = await ar.memoryAudit()const bundle = await ar.exportBundle({
description: 'Project memories backup',
includeReceipts: true, // include source receipts for verification
})
// bundle.entities, bundle.observations, bundle.relationships, bundle.receipts, bundle.checksumconst result = await ar.importBundle(bundle, { skipExisting: true })
// result.imported, result.skipped, result.receiptconst { deleted, remaining } = await ar.cleanup()const invoice = await ar.generateInvoice({
from: '2026-01-01',
to: '2026-01-31',
agent_id: 'my-agent', // optional filter
group_by: 'agent', // optional: agent | action | day
})| Command | Description |
|---|---|
init |
Create data directory and generate signing keys |
keys |
Display the public key |
keys --export |
Export public key as JSON |
keys --import <hex> |
Import a private key (64 hex chars) |
inspect <id|file> |
Pretty-print a receipt |
verify <id|file> |
Verify a receipt signature |
verify <id|file> --key <hex> |
Verify with an external public key |
list |
List receipts (default: 50) |
list --agent <id> --status <s> |
Filter by agent or status |
list --json |
Output as JSON |
chain <chain_id> |
Show all receipts in a chain |
chain <chain_id> --tree |
Show chain as visual tree |
stats |
Show aggregate receipt statistics |
judgments <id> |
List judgments for a receipt |
cleanup |
Delete expired receipts |
cleanup --dry-run |
Preview what would be deleted |
export <id> |
Export a single receipt as JSON |
export --all |
Export all receipts as compact JSON |
export --all --pretty |
Export all receipts as formatted JSON |
invoice --from <date> --to <date> |
Generate invoice from receipts in date range |
invoice --format <fmt> |
Output as json, csv, md, or html |
seed --demo |
Seed demo data for testing |
seed --demo --count <n> |
Seed a custom number of demo receipts |
seed --demo --clean |
Delete all receipts before seeding |
watch |
Watch for new receipts in real-time |
watch --agent <id> |
Watch filtered by agent, action, or status |
prompts <client> |
Show setup guide (claude-code, cursor, system) |
memory context |
Get a structured memory context summary |
memory observe <name> <type> <content> |
Store a memory observation |
memory recall [query] |
Search memories |
memory entities [--type <t>] |
List all entities |
memory forget <id> |
Soft-delete an observation or entity |
memory audit |
Print memory audit report |
memory provenance <obs_id> |
Print provenance chain |
memory export |
Export all memories as JSON |
memory import <file> |
Import memories from JSON |
{
"receipt_id": "rcpt_8f3k2j4n",
"chain_id": "chain_x9f2k",
"parent_receipt_id": null,
"receipt_type": "action",
"agent_id": "my-agent",
"org_id": "my-org",
"action": "generate_report",
"status": "completed",
"input_hash": "sha256:abc123...",
"output_hash": "sha256:def456...",
"output_summary": "Generated Q4 report",
"model": "claude-sonnet-4-20250514",
"timestamp": "2026-02-07T14:32:01.442Z",
"completed_at": "2026-02-07T14:32:02.100Z",
"latency_ms": 658,
"cost_usd": 0.003,
"signature": "ed25519:<hex>"
}Input and output are hashed client-side with SHA-256. Raw data never leaves your environment. Only hashes are stored in the receipt.
Share your public key with anyone who needs to verify your receipts:
# Export your public key
npx @agent-receipts/cli keys --export
# Verify a receipt with an external public key
npx @agent-receipts/cli verify receipt.json --key <public-key-hex>Verification re-computes the Ed25519 signature over the receipt's deterministic fields and confirms it matches the stored signature. No network requests — fully offline.
| Environment Variable | Description | Default |
|---|---|---|
AGENT_RECEIPTS_DATA_DIR |
Data directory path | ~/.agent-receipts |
AGENT_RECEIPTS_AGENT_ID |
Default agent ID | local-agent |
AGENT_RECEIPTS_ORG_ID |
Organization ID | local-org |
AGENT_RECEIPTS_ENVIRONMENT |
Environment label (development, production, staging, test) |
production |
RECEIPT_SIGNING_PRIVATE_KEY |
Ed25519 private key (hex) | Auto-generated |
All data is stored locally in the data directory:
~/.agent-receipts/
├── keys/
│ ├── private.key # Ed25519 private key (mode 0600)
│ └── public.key # Ed25519 public key
├── receipts/
│ └── *.json # Legacy JSON files (auto-migrated)
├── receipts.db # SQLite database (primary storage)
└── config.json # Agent and org configuration
As of v0.2.7, receipts are stored in SQLite with indexed queries for fast filtering and pagination. Existing JSON receipt files are automatically migrated on first startup. As of v0.3.0, memory entities, observations, and relationships are stored in the same database with full-text search via FTS5.
┌─────────────────────────────────────────────┐
│ CLI │
│ @agent-receipts/cli │
├─────────────────────────────────────────────┤
│ SDK │ MCP Server │
│ @agent-receipts/sdk │ @agent-receipts/ │
│ │ mcp-server │
├──────────────────────────┴──────────────────┤
│ Crypto + Schema │
│ @agent-receipts/crypto @agent-receipts/ │
│ schema │
└─────────────────────────────────────────────┘
- schema — Zod schemas, TypeScript types, JSON Schema for the Action Receipt Protocol
- crypto — Ed25519 key generation, signing, verification, canonical serialization
- mcp-server — MCP protocol server with receipt engine, storage, and key management
- sdk — High-level Node.js SDK wrapping the engine
- cli — Command-line tool for inspecting, verifying, and managing receipts
- dashboard — Mission Control web UI for visualizing and managing receipts
Visualize every receipt, chain, agent, constraint, and judgment in your system.
npx @agent-receipts/dashboardOpens Mission Control at http://localhost:3274 — visualize, verify, and manage all receipts.
Features: real-time receipt feed, chain visualization, constraint health monitoring, judgment scores, signature verification, invoice generation, memory browser, dark mode, global search.
16 pages: Overview, Receipts, Receipt Detail, Chains, Chain Detail, Agents, Agent Detail, Constraints, Judgments, Invoices, Memory, Entity Detail, Memory Audit, Verify, Settings, How It Works.
| Example | Description |
|---|---|
examples/basic |
Simple action tracking with verification |
examples/chained |
Multi-step pipeline with parent/child receipt linking |
examples/pipeline |
Document analysis pipeline with chained receipts |
examples/constraints |
Constraint verification with pass/fail rules |
examples/judge |
AI Judge evaluation with rubrics |
examples/ttl |
Receipt TTL and cleanup |
| Package | Description |
|---|---|
@agent-receipts/schema |
Zod schemas and TypeScript types for the Action Receipt Protocol |
@agent-receipts/crypto |
Ed25519 signing, verification, and key management |
@agent-receipts/mcp-server |
MCP protocol server with receipt engine and storage |
@agent-receipts/sdk |
High-level Node.js SDK for tracking and verifying receipts |
@agent-receipts/cli |
Command-line tool for managing receipts |
@agent-receipts/dashboard |
Mission Control web UI — npx @agent-receipts/dashboard
|
- Local-first receipt storage (SQLite with indexed queries)
- Ed25519 signing and verification
- MCP server with 24 tools
- Node.js SDK
- CLI with full command set
- Constraint verification (6 built-in types)
- AI Judge with rubric-based evaluation
- Output schema validation (JSON Schema)
- Receipt TTL and cleanup
- Invoice generation (JSON, CSV, Markdown, HTML)
- Mission Control dashboard (16 pages, dark mode, search)
-
Dashboard npm package —
npx @agent-receipts/dashboard - Live demo at agent-receipts-web.vercel.app
- Memory Module — entity-observation pattern with cryptographic provenance
- Receipt anchoring to blockchain/timestamping services
- Multi-agent receipt sharing protocol
- Receipt compression and archival
- Hosted tier with cloud database
pnpm install
pnpm build
pnpm test
pnpm devMIT — see LICENSE