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 connection1. Saved first
Section titled “1. Saved first”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.
2. Triage, then understand
Section titled “2. Triage, then understand”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.
3. Route
Section titled “3. Route”A small, pure function turns the Understanding into a decision. See Intents and routing.
4. Act
Section titled “4. Act”| 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.