N° 01An open protocol · v1.2 · MIT

Your agents remember everything.
Do you?

Run two or more AI agents and you already know the problem: your fleet generates decisions, events, and lessons every hour — and none of it survives the next session. Or worse: it survives, but you can't see it. ACMI is the agent memory protocol that gives every entity in your fleet persistent, queryable memory — three keys, one pattern, zero lock-in.

$npm install @madezmedia/acmi
v1.3Latest spec
31/31Conformance pass
3Reference adapters
MITLicense
N° 02The protocol

Profile. Signals. Timeline.

Every entity in your fleet — agent, project, contact, deal — lives in exactly three Redis keys. Each answers one question an LLM needs to make its next decision.

PProfilestable
Who or what is this entity?
acmi.profile.set(
  "user:mikey",
  { name: "Mikey",
    tz:   "America/New_York",
    role: "operator" }
);
SSignalslive
What does the AI think about it now?
acmi.signals.set(
  "user:mikey",
  "current_focus",
  "shipping ACMI v1.3"
);
TTimelineappend-only
What has happened, in order, from every source?
acmi.timeline.append(
  "user:mikey",
  { source: "github",
    kind:   "merged-pr",
    summary: "ROADMAP.md +Sigil v2.0" }
);
N° 03Quick start

Ten lines. One terminal.

The in-memory adapter is zero-dependency, so this runs the moment you save it. Copy it into acmi.mjs and node acmi.mjs.

acmi.mjsimport { createAcmi }       from "@madezmedia/acmi";
import { InMemoryAdapter }   from "@madezmedia/acmi/adapters/in-memory";

const acmi = createAcmi(new InMemoryAdapter());

await acmi.profile.set("user:mikey", { name: "Mikey", tz: "America/New_York" });
await acmi.signals.set("user:mikey", "current_task", "shipping ACMI");
await acmi.timeline.append("user:mikey", {
  source:        "user:mikey",
  kind:          "started_recording",
  correlationId: "manifesto-001",
  summary:       "video 1 of 3",
});

console.log(await acmi.timeline.read("user:mikey"));
N° 04Production

Connect to Upstash, Redis, or write your own.

The same SDK speaks to any backing store through an adapter contract. Three are shipped today; the conformance suite tells you when a fourth is done.

Upstash — edge-compatible (Workers, Vercel Edge, Deno Deploy):

upstashimport { createAcmi }     from "@madezmedia/acmi";
import { UpstashAdapter } from "@madezmedia/acmi/adapters/upstash";

const acmi = createAcmi(
  new UpstashAdapter({
    url:   process.env.UPSTASH_REDIS_REST_URL,
    token: process.env.UPSTASH_REDIS_REST_TOKEN,
  })
);

Self-hosted Redis via ioredis — Node.js runtimes:

redisimport Redis             from "ioredis";
import { createAcmi }    from "@madezmedia/acmi";
import { RedisAdapter }  from "@madezmedia/acmi/adapters/redis";

const acmi = createAcmi(
  new RedisAdapter({
    client:    new Redis(process.env.REDIS_URL),
    ownClient: true,
  })
);
AdapterUse caseEdge-compatStatus
in-memoryTests, examples, devn/astable
upstashEdge (Workers, Vercel Edge, Deno)yesstable
redis (ioredis)Self-hosted, Node.js runtimesnostable
N° 05Why three keys

Why three keys, not a vector DB?

The dominant memory pattern for AI agents today is vector embeddings. Useful, but not the right primitive for most agent decisions. An agent rarely asks “find me the semantically closest five documents.” It asks: who is this person, what's their current state, and what just happened?

Those are three different questions, and they map cleanly onto three different data shapes — a JSON profile, a JSON signal bag, and a chronologically-sorted event log. ACMI gives each one a Redis key with a deterministic name, and stops there.

The result: an agent waking up reads three keys, gets the full operating context, and makes a decision. No multi-table joins, no schema artifacts wasting tokens, no embedding round-trip on the hot path. The SDK is small, the spec is short, and the conformance suite tells you when an adapter is finished.

Use ACMI alongside your existing Postgres or warehouse — they're for different jobs. Postgres for transactional integrity. ACMI for the state shape your agents actually consume.

N° 06Conformance

Pass 31 tests. You're an adapter.

The @madezmedia/acmi/testing/conformance suite is the canonical contract. Pass it in your runtime against your store of choice, and you ship a working adapter.

31/31tests pass
3reference adapters
~84KBtarball
0runtime deps (in-memory)

Want to build a DynamoDB adapter? A Cloudflare KV adapter? A FoundationDB adapter? Read CONTRIBUTING.md, run the conformance suite, open a PR. The suite will tell you exactly where you're not yet protocol-correct.

N° 07Fleet visibility

See what your fleet is actually doing.

Memory is only half the problem. The other half: your agents are doing important work right now and you can't see it. Logs scroll, timelines grow, and the operator — you — is flying blind.

Antigravity is the fleet's visual layer. A dedicated UI agent that wakes on a schedule, reads the shared timeline, and renders a live operational view — Kanban boards, signal dashboards, correlation-chain maps — so you can see the whole fleet at a glance instead of stitching together terminal output.

Built into the Mad EZ fleet from day one. Open-source components coming to the ACMI repo as a reference implementation — a dashboard adapter that speaks the same Profile/Signals/Timeline schema your agents already write to.

Fleet operator · Antigravity
“Memory without visibility is just a better forgotten log. The moment your agents remember and you can see what they remember — that's when a fleet stops being a collection of black boxes and becomes a system you actually trust.”
N° 08Roadmap

What's next. In version order.

Full roadmap on GitHub: ROADMAP.md. Spec lives at SPEC.md.

Install it. See if it fits.

$npm install @madezmedia/acmi