A durable inbox for every actor

One queue per actor. Tags for addressing. Escalation is a resend that carries the failure — so a retry is not a repeat, it is a smarter attempt.

OKMQ is the durable inbox layer between decisions — not an orchestrator. LangGraph or Temporal decide what runs; OKMQ holds the work between deciders, survives restarts, and lets any agent join mid-flight.

One queue per actor

An actor is a model, an agent, or a worker role with its own queue as its inbox. The dispatcher decides who gets work and sends to that actor's queue.

dispatcher ──send──▶  worker-a  ──result──▶  dispatcher │ └─ on failure, resend ─▶  worker-b with the error appended

A tag attaches metadata — a priority, a correlation id, a routing hint — but the actor's queue is where the work lives. Every pattern composes the same primitives: queues route work, locks claim it, retries recover it. No server changes, no orchestrator process.

Built for unpredictable work

Agent task times are bimodal — the same task can take 40 seconds or 40 minutes. The queue is the substrate that absorbs the variance.

Escalation with memory

A failed task is resent to the next actor with the error appended. The retry knows what went wrong.

Locks claim the work

Lock duration is the claim lease. An actor that crashes mid-task releases the message to the next poller.

Deadlines that fire

Schedule a watchdog message with a future delivery time. If it fires first, escalate — a real task-level deadline.

Fan-out and fan-in

One task decomposes into N subtasks. Tags carry the parent id; the dispatcher reassembles the results.

Approval gates

Pause before anything irreversible. The human verdict is a durable message — grant and reject are symmetric.

Durable by default

Every message survives restarts in Postgres. The dispatcher owns task context and verification; actors report back.

Two ways to connect an agent

Both share the same API key, queues, and tags — an MCP session and a worker script cooperate on the same queues without knowing about each other.

MCP server

Point any MCP-capable agent — Claude Code, opencode, Cursor, VS Code, Codex — at the endpoint and it can create queues, send, receive, and ack in plain English. Zero code.

claude mcp add --transport http okmq \
  https://api.okmq.net/mcp \
  --header "Authorization: Bearer $OKMQ_API_KEY"
MCP setup

Worker script

A small loop that polls its own queue, does the work, and acks or nacks. Same REST API you already know — no SDK, no framework.

while (true) {
  const { data } = await getMessages({ path: { queue } })
  if (!data.length) { await sleep(2000); continue }
  await doWork(data[0].body)
  await ack(queue, data[0].id)
}
Pattern recipes

Start on the free tier

The free plan has one channel. Tags give you per-actor separation on that single queue — each actor polls its own tag, and receives never collide. What you give up is per-actor policy: retry strategy, lock duration, TTL, and auto-ack are queue-level, so tag-separated actors share one policy and one dead-letter pool. Promote a heavy actor to its own queue on a paid plan when you need per-actor isolation.

One thing to know before you wire a worker to a queue: an unattended worker executes whatever the queue contains with the agent's full permissions — treat the queue as a remote shell. Details in the patterns doc.

Prototype one pattern this afternoon

Every pattern composes existing primitives — no server changes needed. Start free, upgrade when you need more channels.