AI agents · background jobs · durable workflows

You write the agent. Mikku keeps it running.

Durable execution for AI agents and background jobs, self-hosted on your own Postgres. Every LLM call is a checkpoint, rate limits get waited out, and your prompts never leave your servers.

recent deliveries
POST /webhooks/order-paiddelivered
POST /sync/inventorydelivering
POST /emails/receiptdelivered
POST /notify/slackfailed
POST /reports/dailyscheduled

AI agents

Agent loops that survive anything

Wrap each LLM call and tool call in a step and your agent becomes a durable run. Mikku checkpoints every step in your Postgres and replays the log on resume, so a crash, redeploy, or week-long wait never loses work. Prompts, keys, and outputs stay on your servers.

app.mikku.dev/workflows/wf_3fa8d1c2

Agent run

research-agent v1 · wf_3fa8d1c2

waiting
Draft ready, parked on approval
Steps
  1. llm-0done
  2. search-docsdone
  3. llm-1done
  4. approvalwaiting for signal…
  5. publishpending

LLM calls run exactly once

step.ai memoizes each call. A crash mid-run never re-bills a completed call on resume.

Rate limits, waited out

A 429 retries with backoff floored at the provider's Retry-After, so you wait instead of hammering.

Humans in the loop

Park the run until someone approves the action. It costs nothing while it waits, for days if needed.

Publish

Publish in one line

Install the SDK, set your keys once, and hand Mikku the request. The rest is the queue's problem. Typed end to end, from publish to delivery.

publish.ts
import { MikkuClient } from "@mikku.dev/sdk"; const mikku = new MikkuClient(); const msg = await mikku.publish({  url: "https://api.example.com/order-paid",  body: { orderId: "ord_123" },  headers: { "x-tenant": "acme" },  delaySeconds: 30,  maxAttempts: 5,  idempotencyKey: "ord_123:paid",}); // 202 Accepted  { id: "msg_9f2c4a1b", status: "queued" }

Schedule and cap

Delay delivery or cap the attempt budget from the same publish call.

Idempotency keys

Publish the same message twice and Mikku delivers it exactly once.

Any language

Not on TypeScript? Generate a client from the OpenAPI spec.

Fan out

One publish, every endpoint

Group your destinations into a fanout and publish once. Mikku delivers an independent message to each endpoint, so a single dead consumer dead-letters on its own without holding up the rest.

app.mikku.dev/fanouts/order-events
publishorder-events6 endpoints
Endpoint
https://warehouse.acme.com/inventorydelivering
https://analytics.acme.com/trackdelivered
https://crm.acme.com/contact-syncdelivered
https://search.acme.com/reindexdelivered
https://email.acme.com/order-confirmdelivered
https://billing.acme.com/usagefailed

Publish to a name

Reference a fanout by name and Mikku delivers to every endpoint in it.

Independent retries

Each endpoint gets its own attempts, backoff, and dead-letter queue.

Edit without redeploying

Add or remove endpoints from the dashboard or API; new publishes pick them up.

Workflows

Jobs that sleep for a week and resume intact

Write a function that runs a step, sleeps until a future date, or waits for an external signal. Mikku checkpoints every step and replays the rest, so a run survives crashes and redeploys and picks up with its state intact. Your code stays on your servers.

app.mikku.dev/workflows/wf_7c1a2f9e

Workflow run

order-flow v3 · wf_7c1a2f9e

waiting
Parked on event review
Steps
  1. chargedone
  2. cooldowndone
  3. reviewwaiting for signal…
  4. notify · shippending
  5. receiptpending

Steps run exactly once

Each step memoizes its result, so a completed step never runs again across resumes.

Durable sleep and signals

Park a run until a future date or an external event, for days or weeks, at no cost while it waits.

Parallel steps and children

Run independent steps concurrently, or start a child workflow and await its result.

Monitor

Filter the firehose, watch it land

Every message your account publishes, in one table. Filter by status or destination and the list keeps itself current as deliveries land, no refresh button to hit.

app.mikku.dev/messages
Filter by destination URL…
All statuses
StatusDestination
deliveringPOST /sync/inventory
deliveredPOST /emails/receipt
failedPOST /notify/slack
deliveredPOST /webhooks/order-paid
pendingPOST /reports/daily
deliveredPOST /agents/research-run
deliveringPOST /search/reindex

Status and search filters

Narrow to just failures, or search by destination. The counts follow your filter.

Live by default

The table polls quietly in the background and pauses while the tab is hidden.

Open for the full story

Click any row for its payload, headers, retry policy, and every attempt.

Observability

See every attempt, not just the last error

Open any message for its whole history: each attempt, the response code, how long it took, and the worker that handled it.

app.mikku.dev/messages/msg_b3f0a91c

Message details

msg_b3f0a91c · POST /webhooks/order-paid

delivered
Delivery attempts
  1. attempt 11.21s500
    Internal Server Error
  2. attempt 20.84s503
    Service Unavailable
  3. attempt 30.12s429
    Too Many Requests
  4. attempt 40.31s200

Three failures, then a 200 on the fourth. Backoff spaced out the retries.

Response capture

The response body is saved with every attempt, truncated to 4KB.

Flexible backoff

Exponential, linear, or fixed retry spacing, with jitter applied.

Cancel in flight

Stop any message that hasn't been delivered yet.

Recovery

Recover failures without leaving the page

Messages that exhaust their retries land in the dead-letter queue. Select a batch and retry, or resend one as a fresh copy. You never touch the database.

app.mikku.dev/dlq
10 failedRetry allDelete all
Destination
POST /notify/slack
POST /webhooks/refund
POST /sync/crm
POST /emails/receipt
POST /agents/summarize
POST /billing/charge
POST /search/reindex
POST /webhooks/shipped
POST /crm/contact-sync
POST /analytics/track

Bulk retry

Send a batch back to pending with a fresh attempt budget.

Resend

Clone a delivered or failed message into a brand new one.

Scoped and safe

Every action is scoped to your account. You never touch the database.

Scheduling

Schedules without a cron server

Write a cron expression and Mikku turns each tick into a message, with the same signing and retries as everything else. Pause or edit from the dashboard.

app.mikku.dev/schedules
NameStatusNext run
Hourly digestonin 38s
Nightly cleanuponin 6h
Weekly reportonin 3d
Cache warmonin 9m
Token refreshonin 2h
Metrics rolluponin 4m
Invoice remindersonin 18h
Stale sweeppausedpaused

Standard cron

Standard 5-field cron expressions, evaluated in UTC.

Inspectable runs

Each tick is a normal message you can open and inspect.

One-off sends

Build and send a single message from a form, no cron needed.

Stop hand-rolling retry logic.

Create an API key and run your first background job or durable agent in two minutes. No queue to stand up, no cron server to babysit.