Automations & Auto-replies (auto-respond to messages)
The two ways Omniscio acts automatically: Auto-replies fire one action when a session's finished output matches a rule, while Automations run a pipeline of up to ten actions over incoming channel messages, with scoping, backtesting and AI reply review.
What it is
(formerly called "Away Mode". Its sidebar entry in the Automation group is now labeled "Auto-Reply & Triage" — renamed 2026-08-10 so it no longer collides with the scheduled "Automations" family (Automation Builder / My Automations / Cron Jobs); same feature, display-name only.)
Omniscio has two distinct ways to act automatically, and the one you want depends on how much logic you need (and on what triggers it — Auto-replies watch a session's own output, Claude or a non-Claude engine like Codex / Gemini / OpenCode; Automations watch incoming channel messages). Auto-replies is the lightweight one: simple rules (keyword / project / tag / time-of-day) match text in a session's finished output — for any engine — and fire one action. Historically that action was always a reply; now each rule picks one of six — reply (inject a message / snippet, the default), rename the session, archive the session, start a new session (spawns a fresh Claude — billable per fire), add an inbox note to yourself, or organize the session (set its title, a library tag, and an inbox color together). A rule can also carry an optional project scope so it only fires for sessions in one project ("this text in this repo"). See Auto-reply actions below. Automations is the heavy one: a full pipeline engine where rules can use AND/OR conditions (with contains, matches_regex, matches_glob, equals operators) or delegate to AI classification, and each rule runs an ordered chain of up to 10 actions — reply, label, archive, summarize with AI, forward, forward to email (Gmail only, max 20/hour), notify, spawn a CLI session (with template-interpolated prompt + optional fuzzy project routing — see Spawning a CLI session from a message below), send a message to an existing session, archive a Claude session (see Archiving a Claude session below), run a recipe (triggers a full recipe orchestration run with approval gates and cost caps), send an outbound HTTP request (with an optional stored credential — see below), or whitelist. Both auto-respond to Gmail/SMS/Slack/Telegram traffic and both share the same template vars ({{sender}}, {{body}}, {{channel}}, {{subject}}). Most users start with Auto-replies and graduate to Automations only when they need multi-step workflows.
Automations support four trigger types:
on_message— fires when an incoming/outgoing message arrives on a channel (the original behavior described above).manual— never fires automatically; you run it on demand from the UI button. (Cron-like timing in Omniscio is the separate Cron Jobs feature, not an automation trigger.)on_session_state— fires when a condition about Claude Code session statuses becomes true. Concrete example: "once every session in project X isended, send a follow-up prompt to project Y." You pick a scope (one project / all projects / a hand-picked subset of sessions / a single session), the statuses that count as "matched" (e.g.ended,error,archived), a firing mode (one_shotself-disables after firing,recurringre-arms every time the condition flips back), and a cooldown (60s minimum in the UI). The watcher polls every 30 seconds — there can be up to a 30-second delay between the condition becoming true and the action chain firing.on_pm_event— fires when a PM board event occurs (item created, status changed, assigned, overdue, column changed). You pick an event type, a board scope (allboards or aspecificboard+column), and the rule fires through the normal channel automation dispatcher. The PM event channel bridge receives events from the sync pipeline (fire-and-forget), matches them againston_pm_eventrules, and dispatches with a 5-second per-rule cooldown. Three PM-specific v2 actions are available:pm.update-linked-status(update a column on the triggering item),pm.add-comment(add a comment to the triggering item), andpm.create-item(create a new item on any board). Gated on BOTHautomationsEnabledANDpmAutomationsEnabled. Four preset templates ship: Overdue Task Nudge, Status Change Update, Comment on New Items, Assignment Notification. In-development (samepm-automationsfeature gate). See mission-control.md — PM event channel bridge.
Where to find it
How to use it
- Decide which you need. If the goal is "send a canned reply when a message mentions X" — Auto-replies. If the goal is "auto-archive newsletters, forward client mail to Slack, and AI-summarize everything else" — Automations.
- Open the Automations virtual project. Click Automations in the left sidebar's Integrations group — it lives next to Quick Replies. The sub-sidebar uses the same layout as a regular project: two collapsible sections at the top — RULES (N) and AUTO-REPLIES (N) with chevron + uppercase label headers — followed by the standard SESSIONS / SNOOZED / ARCHIVED sections beneath. The two collapsibles default to expanded; each lists the matching rules as standard sidebar rows (the same shared interactive row style used elsewhere, e.g. the Quick Replies sidebar) you can click to jump to that category's list view. Clicking a section header toggles its expansion AND switches the main panel to that list. The Auto-replies list view also has a sticky filter input at the top (case-insensitive substring match against trigger keyword + reply text + snippet label); when active, the sidebar header shows the match count as
Auto-replies (5 of 22)so you can tell at a glance how many rules survived the filter. The standard SESSIONS section shows your AI edit sessions as normal session rows with full snooze + archive support. Each rule list is a single wide column where every row collapses to a header (rule name + condition meta + last-fired/run-count); clicking a row's header toggles an inline editor underneath (accordion behavior — opening row B collapses row A). The list header carries a + New rule button that opens the editor in a centered modal for creating fresh rules. - Configure an Auto-replies rule. Open the AUTO-REPLIES sidebar section (or click any auto-reply row) to switch the main panel to the Auto-replies list, then click + New rule in the list header. Pick condition type (keyword / project / tag / time), enter the match value (for keyword / tag, the value is matched as one whole phrase — a case-insensitive substring of the agent's output (text the agent places inside a fenced code block, inline code, or a
>blockquote is ignored, so a session that merely quotes your trigger — discussing it, pasting a log, echoing a header — won't fire the rule) — not a comma-separated list of alternatives), then choose what happens when it matches from the action dropdown — Reply (free-text message or a snippet from your Quick Replies library), Rename the session, Archive the session, Start a new session (a prompt + optional target project — billable), Add an inbox note (title + optional body), or Organize the session (any combination of a title, a library tag, and an inbox color). Each action reveals only its own fields. Optionally fill Only in project to scope the rule to one project. Save. The first matching rule for a finishing session wins. There is no global on/off master toggle — auto-replies fire whenever an enabled rule matches; toggle individual rules off in their list row to silence them. Non-reply rows show a small action badge (rename/archive/start session/inbox note/organize) so you can tell them apart at a glance. - Configure an Automation. Open the RULES sidebar section (or click any rule row) to switch the main panel to the Rules list, then click + New rule in the list header. Pick the trigger type (message / manual / session state / PM board event) → fill the rest of the form: name, scope, condition (for message triggers), actions. Expand the Actions accordion to chain up to 10 in order. Rules fire in list order until one matches (unless the action is
pass, which lets the next rule run too). Rules created in the virtual project land asapprovedimmediately; rules created via the CLI server (by an outside AI) land aspendingand show an amber left-border badge until you approve them. - For session-state triggers, the form swaps the channel/condition cards for two new ones: Scope (radio: this project / all projects / pick sessions / single session) and Conditions (checkbox grid for
running/needs_you/ended/error/archived/paused/etc., plus theone_shotvsrecurringmode toggle and cooldown spinner). Action choices are filtered — message-only actions (auto_respond,label,archive,summarize,forward,forward_email) are hidden because there's no incoming message to act on; session/notification actions stay visible, including the Send to CLI Session action that pushes a templated prompt into a specific existing session and the Archive Session action — which on a session-state trigger can archive exactly the sessions the rule matched (see Archiving a Claude session). - Spawn an AI edit session. Click the standard + launch button next to the SESSIONS header in the sidebar — the same button regular projects use. Omniscio starts a Claude session pre-seeded with this page, your current rule inventory as JSON, a REST cheatsheet for
/automation/*, and a short-lived in-app token. Writes authorized with that token skip the CLI approval inbox and land as approved immediately — so "add a rule that archives newsletters from substack.com" turns into a live rule in seconds. The session shows up as a normal row under SESSIONS with full snooze + archive support; click it to focus the SessionPanel, click the standard close button to return to the rule lists. - Test before letting it run. Each rule has a small preview that echoes what it would have done against the most recent message matching the condition. Use this to catch regex mistakes before a real message arrives. Session-state triggers don't have a preview — set them to
recurringfirst, watch the trigger count, and switch toone_shotonce you trust them. - Watch the analytics. Both surfaces show trigger counts so you can tell if a rule is mis-firing (e.g., catching too much) or dead (matched zero times in a week).
Configure via CLI
Agents can create, update, and test automation rules via the CLI server at 127.0.0.1:19519/automation/* (see the omniscio-control skill). Rules created via CLI require one-tap approval in the Omniscio inbox before they fire — that's the user-in-the-loop guarantee. The skill documents all 13 endpoints, the rule schema, the idempotency key convention, and worked curl examples.
How it behaves
Auto-reply actions (beyond a plain reply)
An auto-reply rule matches text in a session's finished output — Claude or a non-Claude engine (Codex, Gemini, OpenCode, …) — and fires exactly one action. Pick it from the editor's When it matches dropdown:
| Action | What it does | Still pings you afterward? |
|---|---|---|
| Reply (default) | Sends a message back into the session — free text or a Quick Reply snippet. This is the legacy behavior; every pre-existing rule is a reply. | No (the turn is handled) |
| Rename the session | Renames the session to a title you set (exactly like renaming it by hand). | Yes |
| Archive the session | Stops the session's process and archives it. The archive chip reads "Auto-reply rule (auto-archive)." | No (it's gone) |
| Start a new session | Spawns a fresh Claude session with a prompt you set, in the matched session's project (or one you pick). Billable — it starts a real session each time it fires. | Yes |
| Add an inbox note | Drops a dismissible note (title + optional body) in your inbox. Repeats from the same rule+session coalesce into one note. | Yes |
| Organize the session | Tidies the session in one shot — sets any combination of a new title, a library tag, and an inbox color (the colored bar that shows on the session in the inbox and sidebar). Fill in just the parts you want; at least one is required. Each part is applied independently and best-effort, so if (say) a tag was deleted the title and color still get set. | Yes |
Every rule may also set an Only in project scope so it fires only for sessions in that one project.
Loop-safety for the billable actions: the two actions that spend money or re-drive the agent are loop-guarded. "Start a new session" is guarded three ways — a session that an auto-reply rule itself spawned can never trigger another spawn (so a spawned session echoing the trigger word won't cascade); the same rule can't fire twice for the same session within a short window (so a duplicated turn-completion can't double-spawn); and each rule can spawn at most 50 sessions per day, past which it pauses until local midnight and drops a deduped inbox card — a backstop against a mis-scoped rule that spawns across a whole fleet. "Reply" is guarded too — it spends a billable Claude turn every time it fires: (1) a rule only matches the turn that just finished (session.turnOutputBuffer), never a keyword that already scrolled out of an earlier turn; and (2) consecutive replies to turns that make no progress — a "nothing to do" / status-only reply, via detectBackgroundAck — are capped at MAX_CONSECUTIVE_NO_PROGRESS_AUTO_REPLIES (3), after which the reply is skipped and the session surfaces to you with a kinded auto-reply-loop-capped breadcrumb. A substantive turn — the agent doing real work — resets that counter, so a productive hands-free autonomous run never trips it; the cap is shared by Claude and non-Claude sessions. Unlike a spawn, a reply is NOT subject to the per-rule daily cap — those reply-loop-safety-bounded guards plus your budget/spend caps bound it, so a legitimate high-volume rule (e.g. a dev-pipeline gate auto-approver that replies once per run) is never paused for the day. See away-mode-rich-actions-contract.md reply-loop-safety-bounded. The other four actions (rename / archive / inbox note / organize) are cheap and don't re-drive the agent, so they need no cap.
Giving a session a color
You can paint any session a color of your choosing. The color shows up as a thin colored bar at the left edge of that session's row — everywhere the session appears: the inbox feed, the desktop sidebar, and the mobile list. The bar sits next to the usual status dot (green = running, amber = needs you, red = error); it never replaces it, so you still see at a glance whether the session needs attention. Use it to flag a few sessions visually — "these three are the client work", "this one is the experiment I keep losing".
There are two ways to set a color:
- By hand — right-click any session and pick Set color, then choose a swatch from the color picker. To remove a color again, open the same picker and click No color (the bar disappears and the session goes back to inheriting its normal status color). Setting or clearing a color is undoable.
- Automatically — the Organize the session auto-reply action (above) can set a color whenever a rule matches, on its own or together with a new title and a tag.
A color you set sticks with the session until you change or clear it, and it updates live in every open window the moment it changes.
Spawning a CLI session from a message (cli_session action)
The cli_session action spawns a fresh Claude Code session in an Omniscio project when a rule's condition matches — the canonical use case is "GitHub Actions failure email arrives → spawn a Claude session in the matching project to investigate and fix it." Two fields control how the session opens:
prompt— the initial message the session receives. Supports the same template vars asnotify/forward_email/auto_respond:{{body}},{{subject}},{{sender}},{{channel}}. Substitution happens at fire time, so the agent gets the verbatim email body / SMS text / Slack message instead of a generic placeholder.projectResolution—'static'(default — the session opens in the project named by the action'sprojectIdfield; existing automations are unchanged) or'auto'. With'auto', Omniscio scans the message body for a GitHub URL (github.com/<owner>/<repo>/...), strips a trailing.git, normalizes the repo name (lowercased; dashes, underscores, spaces, dots removed), and fuzzy-matches against your registered projects in two passes — first an exact normalized match against project names AND folder names (last path segment), then a substring match. So a message body containinghttps://github.com/me/reddit-scout/actions/runs/123resolves to the project namedReddit Scout(or the folderreddit_scout/). If no GitHub URL is present or no project matches, the executor logs a warning and falls back to the configuredprojectIdso the rule still fires — auto-resolution is best-effort, never a blocker.
Together these turn "GitHub Actions Failure Auto-Fix" into a single rule: condition matches the GitHub email, action cli_session with projectResolution: 'auto' and a templated prompt like Investigate the failed CI run mentioned in this email:\n\n{{body}} opens a session in the right repo's project with the failure email injected as context. Backtest (next section) renders both the resolved projectId and the rendered prompt in its dry-run preview, so you can verify the routing and substitution before any real session spawns. The implementation lives at /src/main/services/automation/legacy/automation-action-executor.ts — renderTemplate(config.prompt, msg, triggerContext) for substitution and resolveProjectFromMessage(body) for fuzzy lookup.
Archiving a Claude session (cli_archive_session action)
The cli_archive_session action archives a Claude Code session — the same archive the sidebar performs: it kills the session's running process, flips its status to archived, and stamps the archive-attribution chip as "Automation rule (auto-archive)" so a glance at the archive tells you why the session was put away. Use it for housekeeping — keeping the sidebar clear of sessions that have served their purpose. It's available on every trigger type (message / manual / session-state / PM board event).
A single target selector decides which session is archived:
- The sessions this rule matched (
target: 'matched') — only meaningful on anon_session_statetrigger. When the rule fires because every scoped session reached one of its matched statuses, this archives exactly those sessions. This is the canonical "auto-archive finished sessions" rule: scope = a single session or a hand-picked set, conditions =ended(optionally +error), one action = Archive Session targeting the matched sessions. The radio is hidden on message / schedule triggers because there are no matched sessions to act on, so the action uses the specific-session target there. - A specific session (
target: 'specific', the default) — you pick one session from a dropdown when building the rule, and it's archived whenever the rule fires. Works on any trigger. Because sessions are ephemeral, a hard-coded target ages out over time — the durable, set-and-forget case is matched sessions on a session-state trigger.
The action is idempotent and safe: a target that's already archived, deleted, paused, or missing is skipped with a note (never an error) and simply doesn't count toward the archived total — exactly like the Send-to-CLI-Session action, so a stale rule never breaks the chain. Backtest renders the action in its dry-run preview without archiving anything real. Implementation: the cli_archive_session arm in /src/main/services/automation/legacy/automation-action-executor.ts resolves the target ids (from the trigger's matched sessions or the configured sessionId) and calls the canonical archiveSessionService(id, 'automation-rule') from /src/main/services/session/session-lifecycle-service.ts — the same path the sidebar archive uses.
Sending an outbound HTTP request (http.request action)
The http.request action makes Omniscio call a web address for you when a rule matches —
the action to reach when the thing that needs to happen next lives in some other service rather
than in Omniscio. Typical uses: ping a webhook, post a note into a system that only accepts HTTP,
or kick off a job somewhere else.
Type http.request in the action's type field, then fill in:
- Method —
GET,POST,PUT,PATCHorDELETE. - URL — the address to call. It must be
http://orhttps://; anything else is refused rather than attempted. The URL and the other text fields accept the same template variables as every other action ({{sender}},{{body}},{{channel}},{{subject}}), so you can put something from the message into the address. - Headers (optional) — one
Name: valueper line. - Body (optional) — sent as the request body, as plain text or a JSON string.
- Auth credential (optional) — pick a stored credential instead of pasting a token into the headers. This is the part worth using: the credential is kept in the same encrypted store as your other automation credentials and referenced by id, so the secret never appears in the rule itself. Three schemes are supported — bearer (a token), basic (username + password), and header (your own header name + value). Leaving the credential out is a normal, valid choice: plenty of public endpoints need none. See Automation credentials.
Four things about this action are worth knowing before you rely on it:
- It will not call your own machine or your private network. Addresses that point at the local machine, a private network, or a cloud metadata endpoint are refused before the request is made — a stored rule must not become a way to reach services that are not otherwise reachable. The same check is re-applied to every redirect, so a public address cannot bounce the request inward. A request to such an address fails with "Refused to fetch private or internal network address".
- It is never retried automatically. Every other outbound action can be retried by the engine; this one deliberately is not, because the address is arbitrary and repeating a request that may have already taken effect is worse than reporting the failure once.
- A slow endpoint gives up after about 25 seconds, and only the first part of the reply body is kept — enough to see what came back, not to move a large payload through a rule.
- The stored credential is masked in previews. A backtest shows
***in place of the authorization header, so a preview you screenshot or paste into a log cannot leak it.
The request is sent as the automation fires. Backtest renders this action like any other, so you can see the resolved URL and body before anything real is sent.
This action is currently reachable by authoring the action type directly; it is not one of the types offered in the UI's action picker.
Preview AI replies before they send
An Automation's reply action can write its reply with AI (useAi). Because that text is
generated from the incoming message, a hostile inbound message could try to steer the model into
replying with a scam link or a request for private info — which would then go out under your
identity. To close that, Omniscio has a default-on setting, Review AI replies before sending
(autoRespondPreviewBeforeSend), in the Automation settings (Settings search: "preview before send").
- On (default): an AI-written auto-reply is not sent — it lands in your inbox as an approve/reject card showing the exact reply text and the destination conversation. Approve sends it; Reject drops it. Approving is reachable from your phone too.
- Off: AI replies send immediately (the earlier behavior).
- Only genuine AI replies are held. A plain template reply (including the fallback used when the automation AI daily-spend cap is reached) always sends immediately.
- The reply you approve is exactly what will send, and the destination is read from the saved card — never from the click — so nothing can be tricked into redirecting or rewriting a queued reply. On approve the reply sends then the card clears; if the channel is offline the card stays so you can retry or reject.
- This is Layer 1. A link-allowlist and output-side exfiltration detection are deliberately deferred follow-up layers. Full invariants: auto-reply-preview-before-send-contract.md.
Backtest a rule against the last 24 hours
Open the Automations virtual project → click any rule row to expand its inline editor → expand the Backtest (last 24 hours) card → click Run Backtest. Omniscio replays every message that arrived on the rule's channels in the last 24 hours (capped at 100 most-recent messages) against your in-progress draft and shows two things per match: the rule's confidence (for AI conditions in Phase B) and the rendered preview of every action in the chain — the literal email subject and body a forward_email would send, the templated reply text an auto_respond would post, the label name an archive would apply, etc. No real side effects fire. Backtest runs through the same executor as live automations but with a dryRun gate that short-circuits each action arm before it touches the network or the database.
The list also flags any match whose message historically triggered the live rule with an "Already triggered" badge — useful for distinguishing "this rule worked" from "this rule would also have caught these other messages I missed." Cancelling a long scan is one click; the backend stops between messages and reports how many were evaluated before the cancel.
Phase A scope (current):
- Window: last 24 hours, max 100 messages, on-message rules only
- Channels: SMS, Slack, Telegram. Gmail is unsupported because the inbound tracking table doesn't store message bodies (only metadata)
- Conditions: rule-method only. AI-method conditions return an error ("AI conditions require Phase B") because re-classifying 100 messages against a draft is expensive and needs a cache
- Approval status is ignored — backtest runs whether the rule is pending, approved, or rejected. It's a design tool, not an execution
- Single-rule only —
stopOnMatchinteractions across multiple rules are not simulated - Attachments are not matched — body, sender, subject, channel only
How it works: /src/main/services/automation/legacy/automation-backtest-service.ts pulls recent messages via getRecentSmsMessages / getRecentSlackMessages / getRecentTelegramMessages from their per-channel query modules (queries-sms/messages.ts / queries-slack.ts / queries-telegram.ts), evaluates each through the standard pattern matcher, then invokes /src/main/services/automation/legacy/automation-action-executor.ts with dryRun: true. The dryRun branch in every action arm renders the action body (template substitution, recipient resolution) but returns before the side effect. UI lives in /src/renderer/src/features/settings/BacktestPanel.tsx and is mounted lazy-loaded inside /src/renderer/src/features/automations/components/AutomationRuleEditor.tsx Card 6 (gated behind triggerType === 'on_message').
Which senders can trigger an automation from email
An email's sender is a From: line, and a From: line is something anyone can write — so
an email-triggered automation only spends money for a sender the mail system has actually
vouched for.
- The sender is matched by address, not by name. A rule like
sender contains someone@acme.commatches that exact address. It no longer matches a message whose display name happens to contain that text, and it no longer matches a lookalike domain such assomeone@acme.com.example.net. - A paid action needs an authenticated sender. Before an email can start a session,
reply to the sender, or run a paid recipe, the receiving mail host has to confirm the
message really came from the domain in its
From:line (DMARC aligned with the From domain). If it cannot, the message still arrives and free actions — archiving, labelling, notifying, summarizing — still run, but the money-spending actions are held back and you get one inbox notice naming the channel. - This only applies to email. Text-message senders keep matching the way they always have, including a contact name.
If an automation you rely on stops firing, the most likely cause is the third point: the sending domain publishes no mail-authentication record, so its mail can never be confirmed. The notice in your inbox names it.
When an action permanently fails (the automation dead-letter queue)
An action that talks to the outside world — posting a Slack message, calling a webhook, sending mail — can fail for a reason that is worth retrying: a timeout, a 503, a dropped connection. Those are retried a bounded number of times. If every retry fails, the action is neither dropped silently nor retried forever: it is written to a durable automation dead-letter queue, and the rest of the rule's action chain still runs. This is the one place you can learn that a message never went out or a webhook never landed.
Two things happen when something is set aside:
- An inbox alert. "Some automation actions could not be completed" carries the running count and climbs as more accumulate. It is deduped (one row, updated) and clears itself when the queue empties.
- A 30-day retention window. Set-aside actions are purged on the same 30-day maintenance cadence as the rest of the automation history, so the queue cannot grow without bound.
The honest limit: there is no per-item screen for this queue today. It is durable and counted, but nothing in the app or over the CLI lists an individual set-aside action — the count in that alert is the whole of what you can see. If an action you care about was set aside, the alert is your signal, re-running the rule is the fix, and the raw cause is in the app log.
Naming caution. "Dead letter" names three other queues in Omniscio — Team Chat's failed scheduled messages, undelivered agent-to-agent messages, and PM webhooks. This is the automation one. If you searched the term and landed on one of those, that is why.
Related
- dev-pipeline-panel.md — the Dev Pipeline can seed a starter set of workflow auto-replies for you (the opt-in "Add the workflow auto-replies" companion under Settings → Features → Enable Dev Pipeline skill); it skips any trigger you already have and, turned off, removes only the ones it added. The matcher's quote/code-strip behavior above is locked by away-mode-rich-actions-contract.md
matcher-ignores-code-and-quoted-spans. - automation-credentials.md — where v2 actions (Slack, GitHub, SMTP, etc.) load their secrets from; actions reference a credential by id rather than embedding the secret in the action config
- quick-replies.md — the paired virtual project for authoring the snippet library that Auto-replies rules and
auto_respondactions cite - use-quick-responses.md — composer-side UX for using snippets (Alt+S picker, AI chips, Zap button)
- daily-digest.md — the digest summarizes what your automations did yesterday
- Automations & Auto-replies (part 2) — the rest of this page: the auto-response badge taxonomy that names which automated path produced a system message, the per-step activity-log breakdown for v2 runs, and the implementation map of the engines, stores, watchers and IPC channels behind both kinds of rule.
Last verified 2026-09-28