> ## Documentation Index
> Fetch the complete documentation index at: https://docs.auto.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Routing

> Production rules for spawn, deliver, and bind — pairing triggers, suppressing loops, and choosing onUnmatched.

Routing decides which session receives an event. The conceptual overview lives in [triggers and events](/concepts/triggers-and-events); this page collects the production rules that keep routing predictable once a factory grows past its first agent.

| Kind      | Sends the event to                                                                                                                  | Use when                                                             |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| `spawn`   | a fresh session                                                                                                                     | each event is a self-contained job                                   |
| `deliver` | existing session(s) — the agent's concurrency-slot member, or `routeBy: { kind: attributedSessions }` / `{ kind: allLiveSessions }` | the follow-up belongs to a session that already has the context      |
| `bind`    | the one session bound to the event's artifact (`target: github.pull_request`, `slack.thread`, `linear.issue`, …)                    | an artifact should have exactly one owning session over its lifetime |

Rules of thumb, all enforced or exercised in this repo's config:

* **Bind when the artifact is the unit of work.** This repo's PR reviewer binds every PR lifecycle trigger to `github.pull_request` with `onUnmatched: spawn`, so one reviewer session owns a PR across heads and re-reviews fold forward on push instead of spawning a fresh review per push.
* **Only some events can `bind`.** An event routes to a binding only if its payload carries a routing target (a PR, issue, or thread). `github.push` and `github.workflow_run.completed` carry none — a `bind` route can never match them; use `spawn` or `deliver`.
* **Suppress your own echoes.** Chat deliver triggers routed by `attributedSessions` must filter `"$.auto.authored": false` — validation rejects the trigger otherwise, because an agent that hears its own messages loops.
* **Make spawn/deliver pairs mutually exclusive.** When the same event should spawn on first contact and deliver on follow-ups, split it on `$.auto.attributions: { exists: false }` (spawn) versus `{ exists: true }` (deliver). Validation enforces this partition; the [chat assistant](/examples/chat-assistant) example is the canonical demonstration.
* **Choose `onUnmatched` deliberately.** `drop` (the default) is right for optional signals like reactions; `warn` leaves an audit trail; `error` records the unmatched event as a failure; `spawn` guarantees the event is handled even when no session matches. Reserve `spawn` for events that must never be lost.

See the [triggers reference](/reference/triggers) for the complete routing schema and the [event catalog](/reference/events/github) for which events carry which bind targets.
