Build persistent agent memory with signed receipts
By the end of this tutorial you'll have stored multiple memories for an agent, retrieved them semantically across sessions, walked the receipt chain to prove tamper-evidence, and exported the full chain for regulator audit. The memory layer that makes your agents auditable in production.
$DCS_API_KEY and $DCS_AGENT_ID set in your shell.
Step 01 Store multiple related memories
Store three memories that an agent might accumulate during a real conversation:
# Memory 1 — user preferences curl -X POST https://api.dcslabs.ai/v1/memory/store \ -H "Authorization: Bearer $DCS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "0348", "content": "User prefers vegetarian food, allergic to peanuts", "tags": ["preferences", "diet"] }' # Memory 2 — context about the user curl -X POST https://api.dcslabs.ai/v1/memory/store \ -H "Authorization: Bearer $DCS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "0348", "content": "User lives in Mumbai, prefers dark mode in apps", "tags": ["preferences", "location"] }' # Memory 3 — a recent decision curl -X POST https://api.dcslabs.ai/v1/memory/store \ -H "Authorization: Bearer $DCS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "0348", "content": "Agreed to a weekly meal-prep schedule, Sundays at 6pm", "tags": ["decisions", "schedule"] }'
Each call returns a memory_id and receipt_id. Each receipt_id is an R+2 signed receipt linking to the previous receipt in your agent's chain.
Step 02 Semantic search — query with different words
Now ask your agent something related to the stored memories but in different words:
curl -X POST https://api.dcslabs.ai/v1/memory/search \ -H "Authorization: Bearer $DCS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "0348", "query": "what should I cook for this user?", "top_k": 3 }'
Expected response:
{
"results": [
{
"memory_id": "mem_a83f12cd",
"content": "User prefers vegetarian food, allergic to peanuts",
"cosine_similarity": 0.612,
"receipt_id": "r2_a83f12cd"
},
{
"memory_id": "mem_b91d34ef",
"content": "Agreed to a weekly meal-prep schedule, Sundays at 6pm",
"cosine_similarity": 0.487,
"receipt_id": "r2_b91d34ef"
},
{
"memory_id": "mem_c47a89bd",
"content": "User lives in Mumbai, prefers dark mode in apps",
"cosine_similarity": 0.212,
"receipt_id": "r2_c47a89bd"
}
]
}
The agent found the diet preference and the meal-prep decision (both relevant), and ranked the unrelated "dark mode" memory third. Semantic search means your agent finds the right memory even when the query uses different words from what was stored.
Step 03 Walk the receipt chain
Every memory write linked to the previous one cryptographically. Walk the chain to see this:
curl "https://api.dcslabs.ai/v1/receipts/chain?agent_id=0348&limit=10" \ -H "Authorization: Bearer $DCS_API_KEY"
You'll see your three receipts in order, each with a prev_receipt_cid pointing to the previous one. The first receipt has prev_receipt_cid: null — it's the genesis of your agent's chain.
Any of these can be cryptographically verified independently — without trusting our server. Pipe one through r2-verify:
curl "https://api.dcslabs.ai/v1/receipts/r2_a83f12cd" | \ npx @trdnetwork/r2-verify --pubkey $(# your pubkey from /agents/0348)
Step 04 Test cross-session persistence
The point of persistent memory is that it survives restarts. Test it:
- Close your terminal completely.
- Open a fresh terminal — no environment variables set.
- Set them again from scratch:
export DCS_API_KEY="dcs_sk_live_..." export DCS_AGENT_ID="0348"
Now query memory — it's still all there:
curl -X POST https://api.dcslabs.ai/v1/memory/search \ -H "Authorization: Bearer $DCS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "0348", "query": "diet preferences" }'
Step 05 Export the full memory chain
For regulator audit or for migrating to a different DCS deployment, export everything:
curl "https://api.dcslabs.ai/v1/memory/export?agent_id=0348&format=json" \ -H "Authorization: Bearer $DCS_API_KEY" \ > agent-0348-memory-export.json
You get back a single JSON file containing:
- All memory writes for the agent
- The complete R+2 receipt chain (every receipt, with chain pointers)
- The chain head CID for the export timestamp
- Metadata: total count, export time
This export is what you hand to a regulator if they ask "what does this agent know and when did it learn it?". Every entry is independently verifiable.
Step 06 Logical delete (right to be forgotten)
Under GDPR / DPDP / CCPA, users have the right to have their data deleted. R+2 receipts are immutable by design (that's the security property), but the content they reference can be purged:
curl -X DELETE https://api.dcslabs.ai/v1/memory/mem_a83f12cd \
-H "Authorization: Bearer $DCS_API_KEY"
Response:
{
"ok": true,
"memory_id": "mem_a83f12cd",
"deleted_at": "2026-05-21T15:50:22Z"
}
What this does:
- The memory's content is purged from the database.
- The memory is marked
deleted: trueand excluded from future searches. - The R+2 receipt remains in the chain (with the content hash, not the content), maintaining the integrity of every receipt that came after it.
- A new R+2 receipt is produced for the delete action itself, creating an audit trail of the deletion.
Architecture under the hood
What you just used:
- Storage: Postgres + pgvector. Memory writes stored as 1536-dim vectors via OpenAI's
text-embedding-3-large. - Search: HNSW index over the cosine distance metric. P50 query latency: 47ms against a 100K-entry corpus.
- Receipts: Every memory operation generates an R+2 signed receipt using your agent's Ed25519 keypair (derived from your SBT identity).
- Chain integrity: Each receipt's
prev_receipt_cidcontains the SHA-256 hash of the previous receipt's canonical JSON form. Tampering breaks the chain instantly. - Durability: Cross-region replication between us-east-1 and eu-west-1. Single-AZ failure won't lose memory.
Pricing on free tier
The free tier covers:
- 1,000 memory writes per month per Agent SBT
- 10,000 memory queries per month per Agent SBT
- Unlimited exports and deletes
If you hit the cap, the API returns 429. Builder tier ($29/mo) bumps you to 50K writes / 500K queries. Sovereign tier is custom.
What's next
- Tutorial 04 — Agent-to-agent negotiation — connect two agents, settle a USDC transaction.
- Tutorial 05 — Verify R+2 receipts independently — go deeper on the cryptography.
- Tutorial 06 — Produce a regulator-ready audit export — the R+3 export format.