Strategy memory
Memory is what makes Sworn an agent rather than a stateless oracle — but only durable, normalized memory is worth a public commitment. Sworn distills, encrypts, commits, and reconciles.
#Durable facts
A StrategyFact is a normalized, dedup-keyed record: a kind (risk tolerance, preferred/avoided chain, preferred asset, constraint, intent breadcrumb), a canonical key, a human-readable value, a confidence, and a version that bumps when the value changes. What Sworn keeps is stable; what it drops is everything one-off, time-bound, or speculative.
#Consolidation
Consolidation distills a noisy turn into the smallest set of facts worth committing, and commits nothing when nothing changed. Confidence rises with recurrence, up to a hard cap.
const CONFIDENCE_CAP = 0.98; // once a fact reaches it, identical repeats produce no delta
const RECURRENCE_STEP = 0.08; // how much a repeated observation nudges confidence up
function reconcileFact(prev, cand, now): StrategyFact | null {
if (prev.value !== cand.value) // value changed → version bump
return { ...prev, value: cand.value, version: prev.version + 1, confidence: cand.confidence, updatedAt: now };
const bumped = Math.min(CONFIDENCE_CAP, prev.confidence + RECURRENCE_STEP);
if (bumped > prev.confidence) return { ...prev, confidence: bumped, updatedAt: now };
return null; // no material change → out of the delta
}An identical memory produces an identical root hash, which is a wasted write of gas and time. So dedup happens upstream of encryption: consolidate returns an empty delta when nothing durable changed, and the commit path short-circuits — surfacing the last real commitment rather than sealing and uploading unchanged bytes.
#Encrypt-to-self
A user’s strategy is private; only the commitment to it is public. Every memory object is sealed with a key derived from the agent wallet secret (AES-256-GCM) before it touches the public network. The root hash is a public fingerprint; the bytes behind it are an opaque, authenticated ciphertext only the agent can open.
// Envelope: MAGIC(4) | version(1) | iv(12) | tag(16) | ciphertext (AES-256-GCM)
export function encryptToSelf(plaintext: Uint8Array, secret: string): Uint8Array {
const iv = randomBytes(IV_LEN);
const cipher = createCipheriv(ALGO, deriveKey(secret), iv);
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
const tag = cipher.getAuthTag();
return Buffer.concat([MAGIC, Buffer.from([VERSION]), iv, tag, ciphertext]);
}The IV is random, so identical memory yields different ciphertext — deliberately, so encrypted bytes are never a dedup signal. Determinism lives one layer down, in canonical (sorted-key) JSON, which makes the plaintext reproducible for the integrity check.
#Reconciliation
A commitment is born pending. The background reconcile job confirms each one truly landed — and verification is stronger than “the network has a record.” It downloads the bytes and runs them back through openMemory, which fails on bad magic, wrong version, or a broken auth tag. So On the record means: downloadable and decrypts to a memory we recognize.
The API runs one reconcile pass every 30 seconds; a commit that exhausts its retry budget is honestly marked failed rather than left to spin. The browser polls every 15 seconds while anything is still Filing and flips the chip in place — so the memory goes on the record live, without the page ever blocking.