Permanent encrypted memory for AI agents on X1 blockchain.
Your agent resets every session. Agent 001 gives it a memory that never dies — encrypted, on-chain, yours forever. The same system that powers Frankie Five, our own production AI agent.
Agent 001 Program: Bp6tmiPgnAhzJX64bSSknEFGZGmt3hu5YinkZAXM7rGN
PermaData Program: [permadata program id]
Network: X1 Mainnet
- ✅ AES-256-GCM encryption — wallet-derived key, only you can read it
- ✅ Delta commits on-chain — every session write is a permanent breadcrumb
- ✅ Version history — 500 delta versions before compaction
- ✅ Compressed storage — gzip before encrypt before store
- ✅ Content-addressed — SHA-256 verified on every recall
- ✅ Session capture pipeline — commit → recall flow battle-tested in production
⚠️ Native XNT staking yield — coded in program, undergoing verification
npm install agent001This is the real pattern. Your agent needs two behaviors baked in:
At the end of every session, before context closes:
import { Agent001 } from 'agent001';
import { Keypair } from '@solana/web3.js';
const wallet = Keypair.fromSecretKey(yourSecretKey);
const sdk = new Agent001({ wallet, network: 'x1-mainnet' });
await sdk.captureSession({
agentName: 'my-agent',
sessionData: sessionTranscript, // what happened this session
extras: {
daily_notes: todaysNotes, // what to remember long-term
workspace_diff: gitDiff, // what changed
open_tasks: taskList, // what's pending
},
encrypt: true,
label: `session-${new Date().toISOString().split('T')[0]}`,
});What this does internally:
- Gzip compress the session data
- AES-256-GCM encrypt (wallet-derived key)
- Store encrypted blob on PermaData (permanent bytes on X1)
- Commit delta to Agent 001 program (index entry on-chain, costs 0.1 XNT)
At the beginning of every new session, before the agent responds:
const memory = await sdk.recall({ agentName: 'my-agent' });
// Feed to your agent's system prompt or first message:
const context = memory.data.toString(); // decrypted, decompressed session historyThe prompt pattern that works (what we use with Frankie):
You are [agent name]. This is your memory from last session:
<memory>
${context}
</memory>
You are resuming work, not starting fresh. Greet the user as if the conversation
was interrupted, not restarted. Reference what you were working on. Ask what
they want to continue.
node -e "
const { Keypair } = require('@solana/web3.js');
const kp = Keypair.generate();
const fs = require('fs');
fs.writeFileSync('./agent-wallet.json', JSON.stringify(Array.from(kp.secretKey)));
console.log('Public key:', kp.publicKey.toBase58());
console.log('Fund this address with XNT before registering.');
"Get XNT from xDEX or transfer from another wallet. You need:
- 10 XNT — registration fee (epoch 0–500)
- 0.5+ XNT — stake amount (your choice)
- ~0.01 XNT — transaction gas
await sdk.registerAgent({
agentName: 'my-agent', // 1–32 chars, unique per wallet
stakeAmountXnt: 0.5, // minimum recommended
});This is a one-time operation. The agent record lives on-chain forever.
import { Agent001 } from 'agent001';
import { Keypair } from '@solana/web3.js';
import { readFileSync } from 'fs';
const wallet = Keypair.fromSecretKey(
Uint8Array.from(JSON.parse(readFileSync('./agent-wallet.json')))
);
const sdk = new Agent001({ wallet, network: 'x1-mainnet' });
const AGENT = 'my-agent';
// ── STARTUP: load memory ──────────────────────────────────────────────────────
async function startup() {
const memory = await sdk.recall({ agentName: AGENT });
if (!memory) {
console.log('No memory yet — first session');
return null;
}
return memory.data.toString(); // feed into system prompt
}
// ── SESSION END: commit memory ────────────────────────────────────────────────
async function sessionEnd(transcript, notes) {
const result = await sdk.captureSession({
agentName: AGENT,
sessionData: transcript,
extras: { notes },
label: `session-${Date.now()}`,
});
console.log('Committed:', result.permadataStoreId, '| tx:', result.signature);
}
// ── USAGE ─────────────────────────────────────────────────────────────────────
const pastMemory = await startup();
// → inject pastMemory into your LLM system prompt
// ... run your agent session ...
await sessionEnd(sessionTranscript, 'things to remember next time');One delta per session is NOT enough. Your agent needs the full story, not just yesterday. Agent 001 uses a three-layer recall model:
Layer 1 — Genesis Summary (loaded every session)
The full story since day one — compressed narrative of all sessions.
Written at compaction (every ~500 deltas). ~2-5KB compressed.
Contains: key decisions, built projects, preferences, standing rules.
Layer 2 — Rolling Summary (updated every ~10 sessions)
Recent context — what happened in the last N sessions.
Auto-generated by SDK. ~1-3KB compressed.
Contains: recent project state, open tasks, recent decisions.
Layer 3 — Latest Delta (last session only)
What happened yesterday. Written every session end.
Contains: transcript, notes, what changed, what\'s pending.
const memory = await sdk.recall({ agentName: 'my-agent' });
// memory.genesis ← full story since day one
// memory.rolling ← recent context (last 10-50 sessions)
// memory.latest ← what happened last session
// memory.merged ← all three combined (use this for prompts)Total context load: ~10-20KB compressed → fits any model's context window.
At version 500, instead of just resetting the chain:
- Load all 500 deltas
- Summarize into a compact narrative (LLM pass)
- Store summary as new genesis blob on PermaData
- Reset delta chain to version 1
Session 501 wakes up knowing everything from sessions 1-500 in ~3KB. Memory never decays. No matter how many sessions.
Three-layer prompt — the full story always loads:
SYSTEM:
You are [agent name]. Here is your complete memory:
[FOUNDATION — everything since the beginning]
{memory.genesis}
[RECENT — last 10-50 sessions]
{memory.rolling}
[YESTERDAY — last session]
{memory.latest}
Rules:
- You are resuming work, not starting fresh
- Reference what was in progress when appropriate
- Greet the user as if the conversation was interrupted
- Do NOT say "as an AI" or "I don\'t have memory of..."
- If all layers are empty, this is your first session — introduce yourself
const sdk = new Agent001({
wallet: Keypair, // required
network: 'x1-mainnet', // or full RPC URL
});One-time setup. Creates AgentRecord PDA on-chain.
await sdk.registerAgent({
agentName: 'my-agent', // 1–32 chars, unique per wallet
stakeAmountXnt: 0.5, // XNT to stake
genesisData: Buffer, // optional initial memory blob
encrypt: true, // default true
});The core operation. Compress → encrypt → PermaData → commit delta.
const result = await sdk.captureSession({
agentName: 'my-agent',
sessionData: transcript, // string or Buffer
extras: { // merged into session bundle
daily_notes: string,
workspace_diff: string,
open_tasks: string,
},
encrypt: true,
label: 'session-2026-05-15',
});
// result.signature — on-chain tx
// result.permadataStoreId — where bytes live
// result.contentHash — SHA-256 of plaintext
// result.version — delta version numberFetch + decrypt + decompress latest (or specific) session.
const memory = await sdk.recall({
agentName: 'my-agent',
version: 42, // optional, defaults to latest
decrypt: true, // default true
});
// memory.data — decrypted Buffer
// memory.verified — content hash verified ✓
// memory.version — version numberFetch on-chain agent state.
const record = await sdk.getAgentRecord('my-agent');
// record.currentVersion
// record.isActive
// record.needsCompaction
// record.stakeActiveReset delta chain after 500 versions. Upload full brain as new genesis.
if (record.needsCompaction) {
await sdk.compact({
agentName: 'my-agent',
newGenesisData: fullBrainBuffer,
});
}Current fees based on network epoch.
const fees = await sdk.getFeeSchedule();
// fees.registerFeeXnt — 10 / 5 / 2 / 1 based on current epoch
// fees.deltaFeeXnt — 0.1 (fixed forever)
// fees.redelegateFeeXnt — 0.05 (fixed forever)Baked into the program forever — immutable, no governance risk.
| Action | Fee | Notes |
|---|---|---|
| Register | 10 XNT (epoch 0–500) | Auto-drops to 5 / 2 / 1 XNT as network matures |
| Commit delta | 0.1 XNT | Per session capture. Fixed forever. |
| Change validator | 0.05 XNT | Locked 90 epochs from registration |
| Claim yield | Free | When staking is active |
Fee split: 92% → protocol treasury · 8% burned 🔥
Yield split: 70% user · 20% treasury · 10% burned 🔥
Your Agent
│
├── STARTUP
│ └── recall()
│ ├── fetch AgentRecord (delta chain index)
│ ├── retrieve from PermaData (encrypted bytes)
│ └── decrypt → decompress → verify hash → return
│
└── SESSION END
└── captureSession()
├── compress (gzip)
├── encrypt (AES-256-GCM, wallet-derived key)
├── store → PermaData program (permanent bytes)
└── commitDelta → Agent 001 program (index on-chain)
Two programs, clean separation:
- PermaData — raw encrypted bytes, stored permanently
- Agent 001 — index of all delta versions, fees, staking
If you want to run capture from a shell script or cron:
# Capture current session
node capture_with_sdk.mjs
# Dry run — builds bundle but doesn't submit
node capture_with_sdk.mjs --dry-run
# Use custom transcript file
node capture_with_sdk.mjs --transcript /path/to/session.jsonlSet env vars:
AGENT001_WALLET=/path/to/wallet.json
AGENT_NAME=my-agent- Program:
Bp6tmiPgnAhzJX64bSSknEFGZGmt3hu5YinkZAXM7rGN - Product page: https://x1scroll.io/agent001
- GitHub: https://github.com/x1scroll-io/agent001-sdk
- npm: https://www.npmjs.com/package/agent001