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.
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 appendedA 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.
Agent task times are bimodal — the same task can take 40 seconds or 40 minutes. The queue is the substrate that absorbs the variance.
A failed task is resent to the next actor with the error appended. The retry knows what went wrong.
Lock duration is the claim lease. An actor that crashes mid-task releases the message to the next poller.
Schedule a watchdog message with a future delivery time. If it fires first, escalate — a real task-level deadline.
One task decomposes into N subtasks. Tags carry the parent id; the dispatcher reassembles the results.
Pause before anything irreversible. The human verdict is a durable message — grant and reject are symmetric.
Every message survives restarts in Postgres. The dispatcher owns task context and verification; actors report back.
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.
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 setupA 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 recipesThe 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.
Every pattern composes existing primitives — no server changes needed. Start free, upgrade when you need more channels.