Memory that outlives the process
Akashik fields now survive restarts. v0.3 reaches full Level 1 conformance without breaking a published contract from v0.2.
An agent that forgets everything when its process exits is not remembering. It is caching.
That was the honest limit of Akashik v0.2. The protocol had the right shape — shared memory with mandatory intent, relevance decided by the protocol, disagreement surfaced rather than resolved — but it held everything in one process's heap. Restart the process and the field was gone.
For a system where agents run for minutes, that is fine. For agents coordinating over days, across serverless invocations, across machines, it is the whole problem.
v0.3 ships today on npm as @akashikprotocol/core. It reaches full Level 1 conformance against the Akashik Protocol Specification.
The protocol decides what is relevant and detects disagreement; the agent decides resolution.
That thesis has not changed. What changed is how long it holds.
The one-line difference
Here is a field that forgets:
import { createField } from "@akashikprotocol/core";
const field = createField();
Here is the same field, durable:
import { createField } from "@akashikprotocol/core";
import { createFileAdapter } from "@akashikprotocol/core/file";
const adapter = createFileAdapter({ path: "./field.jsonl" });
await adapter.init();
const field = createField({ adapter });
Every other line of application code is identical. Write, attune, reckon, draft, retract, supersede — all unchanged. The only difference is where the field keeps its memory.
That is the point of the adapter design. Persistence is a deployment decision, not an architectural one.
Three adapters ship in v0.3:
- Memory — the default. Fast, ephemeral, good for tests and single-run coordination.
- File — a local JSONL log. Good for development, single-machine services, CLI tools, embedded use.
- Postgres — production, serverless, multiple machines, real concurrency.
All three satisfy one interface and pass the same conformance suite. A custom adapter satisfying that interface works everywhere the built-in ones do.
What durability makes possible
The obvious gain is surviving a restart. The less obvious ones matter more.
Agents across processes now share a field correctly. v0.2 ordered entries with a monotonic counter, which works only when one process owns the counter. v0.3 replaces it with Lamport logical clocks, so two serverless invocations writing without having seen each other still produce an ordering every reader computes identically. Concurrent writes are ordered by (lamport, agent, event id) — deterministic, no shared clock, no dependence on wall time.
In a single process, that reduces exactly to the old counter. Existing behaviour is unchanged. The new machinery only engages where the old approach had no answer.
History became walkable. Akashik is event-sourced now: an append-only log is the source of truth, and current state is a projection derived from it. That made replay() nearly free, because the log was already there.
Replay matters because intent is mandatory on every write. Walking a field's history does not give you a list of values that changed. It gives you the ordered sequence of why.
initial pricing observation from the g2 listing page
correcting after verifying the vendor pricing page directly
updating again after the vendor announced a price drop
Three entries in a supersession chain. attune shows only the last one, which is correct — that is the current state. replay({ entry_id }) follows the chain in both directions and returns all three, each with the intent that motivated it. An agent deciding whether to trust the current price can read how it got there.
Agents can express calibrated uncertainty. A write may now carry an optional confidence: a score from 0 to 1 and, encouraged but not required, the reasoning behind it.
The protocol carries confidence. It does not act on it. Confidence never changes relevance ranking, never suppresses a conflict, never picks a winner. That restraint is deliberate: a high-confidence wrong observation and a low-confidence correct one is exactly the case where the agent, holding domain knowledge the protocol cannot have, must decide. A protocol that quietly down-ranked the uncertain entry could bury the right answer.
Subscription works without a transport. attune({ since_epoch }) returns only what arrived after a watermark the caller tracks. No streaming layer, no callbacks, no transport binding — just polling, which is enough for most coordination and costs nothing to adopt.
Fields advertise what they are. Registration now returns real capabilities: the conformance levels the field satisfies, plus durable when the adapter provides it. An agent that needs its work to survive a restart can check, and decide for itself whether to proceed. The field informs; it does not gatekeep.
The part that mattered most
Adding persistence to a protocol is not hard. Adding it without breaking what people already depend on is the whole job.
v0.3 did not bolt storage onto v0.2's in-memory field. It rewrote the field entirely. State moved out of the closure and into an event log; the field became a coordinator over a storage adapter; the in-memory path became just another adapter implementation rather than a special case.
That is a foundation replacement, touching every code path the existing test suite exercises.
I set one gate before that work started: all 280 tests from v0.2 pass unchanged. Not adjusted. Not updated. Not "passing after minor tweaks." Unchanged, or the rewrite is wrong.
They passed. Two assertions in the whole suite changed across the entire release, both for stated reasons: the message envelope now stamps the specification's operation name DETECT where it previously used the SDK's local RECKON, and registration now returns real capabilities where v0.2 documented an empty placeholder. Everything else held exactly as written.
This is what the conformance ratchet is for. Once a level is claimed, its requirements are permanent. v0.2 claimed Level 0; v0.3 claims Level 0 and Level 1. Level 0 did not get renegotiated along the way, and it cannot be. Anyone building against v0.2 can upgrade and change nothing until they want persistence, at which point they change one line.
The package still has one runtime dependency. The Postgres driver is an optional peer dependency reached through a separate entry point, so anyone using the in-memory or file adapter never installs it.
What v0.3 does not do
The protocol is layered into four conformance levels, and v0.3 reaches the second of them fully. Stating what is missing is part of the discipline.
- No semantic relevance. Scoring is feature-weighted — topic, role, recency, intent quality. Vector embeddings and semantic ranking arrive at Level 2 in v0.4.
- No semantic conflict detection. Two entries disagreeing on a shared primitive value produce a conflict. Two entries disagreeing in meaning while differing in wording do not. Also Level 2.
- No MERGE, SUBSCRIBE, or COMPACT. Level 2.
- No transport bindings and no authentication. The message envelope is constructed and validated but does not yet cross a wire. Level 3, in v0.5.
Each absence maps to a level with its own release. The roadmap is published, and the order is the commitment — not the dates.
Try it
npm install @akashikprotocol/core
For a field that survives a restart, add an adapter. For Postgres, install pg alongside it.
The README has a quick start. ADAPTERS covers choosing between the three and writing your own. REPLAY covers reasoning chains. The specification is canonical; this SDK is one implementation of it, and anyone can build another in any language at any conformance level.
v0.4 begins Level 2: embeddings, semantic relevance, semantic conflict detection.
Tell me what breaks. I will read every issue.
Sahil David maintains @akashikprotocol/core and authors the Akashik Protocol Specification. The project is governed under GOVERNANCE.md, with design discipline in PRINCIPLES.md.
