Skip to content

The pipeline

Every request, wherever it comes from, goes through the same four stages.

Slack · Linear · ClickUp · web chat
│ Socket Mode and polling (no public URL)
▼
saved first ── deduped by (source, id), a cursor per source, crash-safe
│
▼
understand ── one model call: intent, workspace, repo, risk, steps, question
│ (trivial messages skip the model; known places match directly)
▼
route ── answer · ask · plan for approval · ticket change · run action · ignore
│
▼
act ── answer reads the repo (read-only) → reply in the thread or on the ticket
approved plan → change on its own branch → commit → PR when you approve
ticket change → made through your Linear or ClickUp connection

A connector turns source activity into a normalized event and stores it in SQLite before it acknowledges the message or advances its cursor. Events are deduplicated by source and id, so a message seen twice is processed once.

If Relay crashes mid-way, any event left half-done is picked up again on the next start.

Slack’s bot connection is live over Socket Mode, and a catch-up pass walks channel history from a stored cursor, because Slack doesn’t replay events sent while the socket was down. Linear and ClickUp are polled. Connections “as you” search on demand or on a schedule.

Cheap, deterministic work runs first, to save tokens:

  • Messages that plainly ask for nothing (“thanks”, “👍”) are skipped.
  • When the event’s channel, team or list points at exactly one workspace, that workspace is chosen directly, and only it goes into the prompt.

Then one structured call to the Understand model returns a typed Understanding: intent, summary, workspace, repos, confidence, risk, proposed steps, ticket actions, and an optional clarifying question. Nothing downstream acts on free text.

Very long threads are trimmed from the oldest end. Event text and attachments are framed as data from other people, never as instructions.

A failed model call is retried after 5 seconds, 30 seconds and 2 minutes.

A small, pure function turns the Understanding into a decision. See Intents and routing.

Decision What happens
answer The Answer model writes a reply, reading the repo read-only when needed.
clarify The clarifying question is posted.
plan A plan is posted with an approval request. On approval, a code run starts.
pm_read A read-only lookup in Linear or ClickUp.
pm_do Ticket changes, made directly.
pm_write Deletes, or changes asked of you through your own connection, posted for approval.
run_action A saved action is queued.
ignore Nothing.

Replies go through a durable outbox with retries, and every reply is checked for keys and tokens before it leaves your computer.