sark

Welcome

Mention a bot in Slack; it forks a cloud sandbox for that thread and runs a coding agent inside it.

sark is a single Cloudflare Worker that turns a Slack thread into a sandboxed agent session. Mention the bot, and it forks a cloud sandbox on ascii.dev Box for that thread. A coding agent runs inside it and talks back through an MCP server hosted by the same Worker, using a token that can only ever address the one thread it was minted for.

It's named after Tron's Slack Agent Runtime Kernel — the Master Control Program's lieutenant, who commands Programs on the Grid.

Why

Running a coding agent from chat is easy to demo and hard to make safe. The moment more than one person can mention the bot, you need answers to:

  • where does the agent's code actually run, and what else can it touch?
  • how do two threads avoid trampling each other's files?
  • what stops a public channel from spinning up unbounded sandboxes?
  • what happens when the agent finishes but never says anything?
  • when five people talk at once, who does the agent think it's answering?

Every one of those is a design decision in this repo, and each has a page here.

At a glance

One sandbox per threadEach Slack thread forks its own Box. Conversation and filesystem stay in sync; threads never contend.
Thread-scoped MCP tokensStateless HMAC naming one thread and one box generation, with an enforced issue time. A leaked token addresses nothing else.
Fail-closed allowlistEmpty ALLOWED_CHANNELS/ALLOWED_USERS refuses every mention. You opt channels in, never out.
WatchdogA Durable Object alarm polls the run; if the agent finishes silently, the reply is recovered from the box event log and posted anyway.
Batched turnsMessages arriving mid-run queue and drain into one turn, each as its own <message> block with its own sender.
Prompt-injection hardeningMessage bodies, display names, and metadata are untrusted; block delimiters are neutralized inside them.
Idle lifecycleBoxes archive (snapshot) after IDLE_STOP_SECONDS and resume onto the same filesystem on the next message.
Slack-free testingMemoryTransport records everything the agent "says", so the whole pipeline is scriptable with no Slack app at all.
One Worker, no infraHono on Cloudflare Workers plus a Durable Object per thread. No database, no queue, no server.

Where to go next

Not in scope

sark is deliberately small. It does not try to be:

  • an agent runtime; the agent is whatever BOX_PROVIDER points at, and this just gives it a thread to live in
  • a multi-tenant SaaS; one Worker, one Box account, one workspace's allowlist
  • a general Slack framework; five tools, two event types, one dropdown, no slash commands
  • a job queue; one run per thread, a bounded backlog, no cross-thread scheduling
  • a bridge to other chat platforms, though Transport is the seam where one would go

On this page