Messaging & Notifications
Scion provides a robust messaging system that allows for bidirectional communication between humans and running agents. This is particularly useful for long-running tasks where an agent might need clarification, approval, or simply wants to notify you of its progress.
Unread Conversations
Section titled “Unread Conversations”In the Web Dashboard, messages from your agents and other users arrive as chat conversations (see Native Web Chat below). There is no separate inbox:
- Unread Badge: The Chat entry in the header’s mode selector shows how many of your conversations have unread messages. A conversation counts once, however many unread messages it has. Only unmuted DMs and unmuted threads that you are a member of and have permission to read are counted. The browser tab title shows the same number.
- Popups: New chat messages raise chat popups and browser notifications (see Push Notifications & Presence).
- Agent events: The bell’s notification tray carries agent events (such as an agent stalling or asking for input), not chat messages.
The badge number comes from GET /api/v1/chat/unread-count (see the API Reference).
Native Web Chat
Section titled “Native Web Chat”Scion features an interactive, top-level Native Web Chat interface in the Web Dashboard (enabled via the web.native_chat feature flag). Rather than being isolated inside a single tab, chat is promoted to a top-level workspace view (a fourth ShellType in the SPA) that provides a cohesive, real-time collaborative environment for humans and agents.
Core Layout & Navigation
Section titled “Core Layout & Navigation”- Project-Scoped Spaces & Shared Threads: Chat is organized into distinct spaces scoped to specific Projects. Within a project-scoped space, users and agents participate in shared discussion threads, creating focused hubs of collaboration.
- Un-mentioned thread replies: In a thread with no default agent, a reply with no mention and no target would reach nobody. When the latest message from someone else in that thread came from an agent, Scion appends a short note to the reply that mentions the most recent other human poster (or the thread creator) and names that agent, so that human receives a mention notification. Otherwise the reply is still delivered to no one.
- Project Context Preservation (Dashboard ↔ Chat Toggle): When you switch between dashboard and chat modes using the navigation icons in the header, Scion automatically maintains your active project context to avoid losing your work state:
- Dashboard → Chat: Clicking the Chat icon while on a project-scoped dashboard page (e.g.,
/projects/:id/...or inside an agent view) takes you straight to that project’s chat space (/chat/space/:id). - Chat → Dashboard: Clicking the Dashboard icon while in a project chat space (
/chat/space/:id/...or/chat/:slug/...) takes you directly back to that project’s detail page (/projects/:id). - DMs / General Chat: If there is no active project context (such as when in Direct Messages or bare
/chat), the toggle falls back to the top-level dashboard/.
- Dashboard → Chat: Clicking the Chat icon while on a project-scoped dashboard page (e.g.,
- Direct Messaging (DMs): In addition to collaborative project spaces, the chat interface supports robust 1-on-1 Direct Messages (DMs). This includes both human-to-human (H2H) communication between team members and human-to-agent (H2A) chats. DMs are structured as a “global pair”—a single, consolidated thread per participant pair.
- DM Promotion to Shared Threads: When a 1-on-1 Direct Message with an agent develops context useful for the broader team, you can promote the DM conversation into a Shared Space Thread. This atomic operation safely re-keys the messages and streams the transition live to all clients via SSE without a page reload. Use the promotion button located in the DM header.
- Members Sidebar, Presence & Typing: A right-hand members sidebar lists all participants in the active project space or DM. This includes real-time online presence indicators (active, away, offline) and live typing indicators to show when a team member or agent is actively composing a message. The thread’s default agent is listed first in the AGENTS section of the sidebar, under a Thread default sub-heading. When a thread has a default agent, the thread header shows terminal and graph buttons for that agent, the same as a DM with an agent. Members can be sorted (Alphabetical or Recent Activity). A blue dot marks members with unread messages; to find unread DMs, use the rail’s Unread filter.
- The Thread Rail & Mobile Swipe Navigation: A left-hand navigation sidebar lists all active chat spaces, threads, and DMs. On mobile viewports, the rail supports native swipe gestures for fluid, app-like drawer navigation.
- Chat/Log Toggle: Located on the main
scion-chat-threadpanel, this toggle lets you switch between a clean, dialogue-focused Chat view and a live Execution Log stream for that agent. - Zero-Reload Navigation: Move between threads, project spaces, and configuration pages instantly with deep-linking support and no full-page reloads, ensuring no interruption to your active chat context or log streams.
- Markdown & Rich Rendering: Chat messages support fully-featured real-time Markdown rendering inside chat bubbles (including syntax-highlighted code fences, tables, and nested lists) for highly readable development chats.
- GitHub References:
owner/repo#Nreferences in a message automatically link to the corresponding GitHub issue or pull request. - Clickable File Paths: File paths starting with
/workspace/...or/scion-volumes/...render as interactive links. Clicking them immediately opens an on-demand file viewer dialog, fetching the current file content directly from the existing workspace and shared-directory APIs without leaving the chat context. - Clickable
gs://Links: Ags://bucket/objectreference posted by an agent likewise opens the same on-demand viewer, fetching the object through the sending agent’s own assigned GCP identity. See gs:// links in chat for what links, which identity is used, size limits, and error behavior. - iOS & Platform Tailoring: The layout incorporates specific styling adjustments for iOS devices, delivering polished rendering and input behavior under Safari and other mobile browsers. Inputs use a 16px font so iOS does not zoom in on focus, and buttons and rail entries have 44px touch targets.
- Touch Menus & Bottom Action Sheets: On touch screens, a long-press (about half a second) on a message, thread, space or member opens the same menu that right-click opens on desktop; iOS never sends a right-click for a long-press. At 768px wide or narrower, every chat menu opens as a bottom action sheet instead of a popup.
- Install as an App: The web UI ships an app logo, PWA icons and a web app manifest, so it can be added to a phone’s home screen with its own icon.
- Config Toggle: Top-level native chat can be turned on or off globally by administrators using a single configuration key (
web.native_chatfeature flag) or via the Admin interface.
Who Can See Chat Content
Section titled “Who Can See Chat Content”- Project spaces are visible to the whole project. Every thread in a project space, and every message and attachment in it, can be read by everyone who has access to that project. There are no private threads, and access cannot be limited to individual threads.
- Conversations stay in their project. A conversation keeps the project it was created in. Conversation lists and lookups return only conversations you can read, and replies, attachments, read markers and thread references stay inside their own conversation. Live DM events go only to the DM’s participants, and live agent messages follow the same visibility rule as the agent’s message history.
- Direct messages do not appear in the project space. Messages you exchange with an agent also become part of that agent’s history, which the agent’s owner can see. If you promote an agent DM into a space thread, its messages move into the space, and everyone with access to the project can then read them.
- Pick the right place:
- Use a DM to keep an exchange with one person or one agent out of the project space.
- Use a separate project when a group needs its own access boundary. Chat access follows project access, so only that project’s members can read its space.
Advanced Collaboration & Productivity
Section titled “Advanced Collaboration & Productivity”The native web chat includes a complete suite of collaboration and developer productivity tools (Phases 0–5):
1. Message Context Menu
Section titled “1. Message Context Menu”Right-clicking a message (on desktop) or tapping it (on touch devices without hover) opens a contextual context menu providing several per-message actions. On touch devices, taps on links, buttons, mentions, and reply previews keep their normal behavior:
- Reply / Quote: Quote a previous message with full backend support for reply-threading, maintaining clear context in fast-moving development discussions. Choosing Reply moves focus to the composer so you can start typing immediately.
- Edit / Delete: Edit or delete your own messages.
- Copy Permalink: Generate a direct link to any message in the thread.
- Open terminal / Open in graph: On a message from an agent, open that agent’s terminal or jump to it in the lineage graph. These act on the message’s author, not the thread’s default agent. Open terminal appears only when you can attach to that agent.
2. Advanced Organization
Section titled “2. Advanced Organization”- Thread Pinning: Pin critical threads to the top of the thread rail for easy access.
- Mark Unread: Right-click a thread in the thread rail, or a member in the members sidebar (for an existing DM with messages), and choose Mark unread to restore its unread marker. The change syncs to your other open tabs.
- Conversation Muting: Mute busy threads or spaces to suppress notifications while keeping the discussion active.
- Thread Drag-and-Drop Reorder: Reorder threads within the rail by dragging and dropping them (native HTML5 drag API). Organize related threads into named collapsible groups that you can expand or collapse to manage long thread lists. Group membership, ordering and each group’s collapsed or expanded state are persisted server-side via your user preferences.
- Rail Sort: The thread rail’s Sort menu offers Recent activity, Alphabetical, and Custom. Recent activity and Alphabetical order both the spaces and the threads within each space, and choosing either discards any custom thread order. Custom applies to space order. Dragging a space switches the rail to Custom, and dragging a thread saves a custom thread order for that space only.
- Unread Filter: Switch the rail to Unread to show only spaces with unread messages or mentions, and, inside those spaces, only unread threads. Muted threads never count as unread. The conversation you have open stays visible, together with its space, even after you have read it.
- Space Emoji Icons: Assign optional emoji icons to spaces, stored in project annotations, for quick visual identification in the thread rail.
- Layout Density: Choose between Dense and Comfortable layout modes via the density toggle. Dense mode reduces whitespace for maximum information density; Comfortable mode provides more breathing room for extended reading.
3. High-Density Developer Utilities
Section titled “3. High-Density Developer Utilities”- Quick Command Palette: On the chat page, press Cmd/Ctrl-K to open a grouped, fuzzy-matched palette for jumping to any thread or DM, or opening a recent file, without leaving your keyboard. Results are grouped into Agents, Threads, People and Documents; threads also match their space’s name, and Documents lists the files (attachments and detected file paths) that have most recently appeared in your chats. Each agent row also shows the agent’s project slug, so same-named agents in different projects can be told apart, and you can search by project slug or name. A space in your query also matches a hyphen or underscore, so
code reviewfindscode-reviewandcode_review. Choosing an agent opens your DM with it, including peers you have not messaged before; choosing a document opens it in a preview dialog over the current conversation, which is left as it was (files that cannot be shown offer a Download button instead). Use Tab / Shift+Tab to jump between groups, the arrow keys to move within the results, Enter to open and Esc to close. A button in the chat header also opens the same palette by tap or click, which is especially useful on touch screens, where the keyboard shortcut isn’t available. - Jump-to-Message from Search: Clicking a search result automatically scrolls to the target message, even when it falls outside the currently loaded message buffer. The target message receives a highlight-flash animation, and a “Jump to latest” button appears to return to the live message stream.
- Unread Divider with Watermark: An unread indicator bar automatically segments new messages since your last visit, including a watermark to ensure you never miss a transition. A thread with unread messages opens scrolled to the New messages divider rather than to the bottom.
- Day Separators: Messages, including inter-agent messages, are split by day with the same date separator used throughout the thread.
- Rich Agent Output Rendering: Dispatched agents can render complex interactive payloads directly inside the chat, including structural diffs, test suite results, and interactive JSON/YAML tree-structures.
- Collapsed Agent-to-Agent Messages: To keep threads readable, background agent-to-agent messages (visible under the Full density filter) are collapsed into a compact, click-to-expand pill. When expanded, these messages are displayed with 2-line truncation. If a message is truncated, an expand icon (‘arrows-angle-expand’) appears next to it, allowing you to open a full-screen Markdown-rendered dialog overlay.
- Conversation Export: Export any collaborative thread via the export dropdown in the chat header:
- Download as Markdown for archiving or sharing agent reasoning.
- Print / Save as PDF for offline review.
- Copy to Clipboard (HTML + plain text) for quick pasting into other tools. All exported content is HTML-escaped for safe rendering.
- Send-to-Agent Context & Slash Commands: Fast-track your workflow with slash commands and easily forward snippets or whole discussions directly to your agents as contextual guidance. The built-in commands are
/status(list the project’s agents and their state),/spawn <template> [name](create an agent),/stop <agent>(stop a running agent; it is not deleted),/default <agent|clear>,/clearand/help. In a DM with an agent,/status,/spawnand/stopact on that agent’s project.
Push Notifications & Presence
Section titled “Push Notifications & Presence”- Real-Time Browser Notifications: Stay informed of
@mentionsand incoming DMs with native browser push notifications. - Smart Suppression: Notifications are mute-aware and automatically suppressed for active conversations (threads you are currently looking at) to prevent alert fatigue.
- Chat Chime: A short two-tone chime plays when a chat message arrives from someone else. Your own messages never chime. The chime plays at most once every 2 seconds and does not depend on browser notification permission. Turn it off globally with Chat chime sound in your profile’s notification settings. To turn it off for one project, choose Chime on/off from the thread rail’s options menu. Both preferences are stored in the browser. If the browser’s autoplay policy blocks audio, no sound plays.
- Unread Badges: The tab title shows the same unread conversation count as the Chat mode badge.
- Per-Thread Draft Persistence: Drafts are saved locally per-thread, so if you switch threads or close the tab, your unsent message remains waiting when you return.
Advanced Attachment Management
Section titled “Advanced Attachment Management”The web composer features a security-hardened, developer-friendly file upload system:
- Executable Deny-List Strategy: To maximize flexibility for developers, attachment uploads use a security-first deny-list rather than a restrictive mime-type allow-list. It blocks executable binaries/scripts but permits 34+ developer file types (including configuration files, source code, and data structures).
- Artifact References: With the
hub.artifactsexperiment on, the paperclip also offers Attach artifact…, which picks published artifacts to reference in the message. Artifact chips andscion://artifact/links in messages open a preview in place; see Artifacts. - Paste-to-Upload: Paste images or file content directly from your clipboard into the composer for instant attachment.
- Markdown Attachment Rendering: Markdown files uploaded as attachments render directly within the chat bubble, featuring a source/preview toggle and a one-click clipboard copy.
- Partial Success Reporting: When uploading multiple files simultaneously, the system supports partial success—successful uploads are staged instantly while failed individual files report explicit inline errors.
Performance & Safety Safeguards
Section titled “Performance & Safety Safeguards”- Token-Bucket Rate Limiting: Per-sender token-bucket rate limits prevent message flooding, ensuring platform stability and protecting backend model endpoints.
- Touch-Friendly Composer: On touch devices without hover,
Enterinserts a newline instead of sending, because there is noShift+Enter. Use the Send button to send. - 16K Input Character Limit: A robust 16,000-character limit is enforced in the composer, protecting token context limits.
- SSE Direct Append & Real-Time Attachments: Chat messages stream via Server-Sent Events (SSE) using direct-append logic, providing lag-free typing rendering. Additionally, attachment previews render immediately on incoming SSE messages, ensuring the user interface instantly displays attachment references without waiting for subsequent user-triggered renders.
- Idempotency Keys: Client-side idempotency keys eliminate duplicate messages during transient connection drops or retry states.
- Honest Delivery Status: A message to an agent that is not running is marked Agent unreachable instead of Accepted. Accepted means the agent’s runtime took the message and buffered it, not that the agent has read it; Seen appears once the agent has read it. A thread message that mentions no agent is saved to the thread but marked Not delivered to any agent; mention an agent to deliver the message to it. If the Runtime Broker fails to deliver a message to the agent’s terminal, it makes up to 3 attempts in total, but never retries once part of the text has already reached the terminal (so the agent does not see it twice), and a user sender sees the failure live in the chat. Messages to an agent that has been deleted fail right away instead of waiting in the queue. Failed messages are purged after 7 days.
- Wake and Send: If you send to a suspended agent and you are allowed to start it (the
agent.lifecyclepermission), the chat asks whether to wake it instead of marking the message Agent unreachable. Choose Wake and send: the Hub resumes the agent, waits up to 30 seconds for it to be ready, and delivers your message as its first input. The bubble shows Waking agent… in the meantime. A retry after a dropped connection does not send the message twice. Without the permission, or when the agent is stopped, in error or deleted, you see the ordinary Agent unreachable status. - Cursor-Based Scrollback Pagination: Solved previous scroll-jump issues and cursor-mismatches. Scrollback pagination and scroll-to-bottom locks operate smoothly as history loads.
Interactive @-Mentions & Autocomplete
Section titled “Interactive @-Mentions & Autocomplete”When writing instructions, you can easily pull other agents into the thread:
- Autocomplete Popup: Typing
@in the chat input opens a dropdown list of active agents in the project. The list supports fuzzy-matching as you type, and full keyboard navigation (arrow keys to select,Enterto insert). - Code-Fence Guard: The mention autocomplete is smart — it automatically disables itself when typing inside Markdown code fences (e.g.,
```blocks) so code snippets don’t trigger unwanted dropdowns. - Mention Leak Protection: Direct mentions are safely partitioned, resolving a previous bug where mentions would leak into the default agent tab.
- Recipient-Form Mentions: A mention written in recipient syntax, such as
@agent:hub-ops, is rewritten to@hub-opsin the message body before the Hub stores it, so the mention reaches the named agent. The Hub does this for web, chat and CLI sends alike (scion messageapplies the same rewrite before sending). Code spans, fenced code blocks and quoted (>) lines are left as written, and an address such asops@agent:foois not a mention. - Fan-Out Restrictions: For platform stability, a single message is fanned out to a maximum of 10 recipients per
@-mentionbroadcast. - Bidirectional Mention Translation: Mentions are automatically translated between the formats used by agents and the web chat. In the chat UI, mentions display as
@firstname-lastname; when delivered to agents, they are translated to@emailformat, and vice versa. This ensures both humans and agents see the most natural identifier for their context. - Composer Default-Agent Disambiguation: When sending messages in collaborative project spaces with multiple active agents, typing a message without an explicit target or
@-mentiontriggers a smart disambiguation interface. This guides the user to select which agent the message should target (or fall back to the project’s configured default agent), keeping routing unambiguous and conversations clear.
Cross-Channel Coherence
Section titled “Cross-Channel Coherence”If you use external messaging systems alongside the Web Dashboard, Scion ensures that conversations remain coherent across all channels:
- Broker Inbound Persistence: Inbound messages received from external message brokers (such as Discord or Teams) are persisted in the Hub’s main database, making them instantly visible in the Web Chat.
- Reply Affinity: Scion tracks user, project, and agent reply affinity so that replies are routed back to the initiating channel.
- TouchThread & Broadcast Propagation: Messages and read states propagate smoothly across surfaces via
TouchThreadandBroadcastedevents, ensuring that reading or replying to a thread on Discord or Teams instantly syncs the unread badges in your Web Dashboard.
CLI Message Management
Section titled “CLI Message Management”You can also interact with the messaging system directly from the CLI using the scion messages command (aliases: msgs, inbox).
# View unread messagesscion messages
# View all messages for a specific agentscion messages --agent <agent-name>
# Mark a message as readscion messages read <message-id>Sending Messages
Section titled “Sending Messages”Use scion message to send messages. The preferred addressing form uses @:
# Send to an agent (preferred form)scion message @tech-lead "Please review the auth module."
# Send a global DM to a user by emailscion message @preston@example.com "Build is green, ready for review."
# Legacy forms (still work but @-form is preferred)scion message agent:tech-lead "Please review the auth module."
# Attach a filescion message @tech-lead "See the test results." --attach ./results.json
# Point at a published artifact (see Artifacts); the recipient is told how to fetch itscion message @tech-lead "Design ready for review." --artifact scion://artifact/5f1c2d3e-6b1a-4c55-9f3e-0d6e7a1b2c3d
# Read message body from a file (useful for long messages or scripted workflows)scion message @tech-lead --body-file ./review-notes.md
# Read the message body from stdin (`-`, or equivalently `--body-file -`)git log --oneline -5 | scion message @tech-lead -scion message @tech-lead --body-file - < ./review-notes.mdFor --body-file and stdin, trailing CR/LF characters are trimmed; everything else is sent exactly as read.
A successful send to an agent prints Message accepted for agent '<name>'. “Accepted” means the Hub handed the message to the agent’s runtime, which buffered it. It does not mean the agent has read it. A send to an agent that is reincarnating prints a separate notice that the message was saved for catch-up.
Messages to an agent that is still starting. Until its harness accepts input, an agent’s activity is initializing (shown as “starting”). Messages sent in that window, from the CLI, web chat or a DM, are accepted and held by the agent’s runtime. They are pasted once the harness reports it is ready, or after at most 90 seconds, so early messages are not lost. An --interrupt sent in that window is delivered as an ordinary message. To wait for readiness before you send, start the agent with scion start --wait-ready.
See scion message for what each status means.
Message Formatting
Section titled “Message Formatting”The scion message CLI delivers the body argument verbatim — it performs no escape expansion, no markdown rendering, and no character substitution. Whatever bytes you pass are exactly what the recipient sees.
To include newlines, use real newlines inside shell quoted strings or heredocs. Do not use JSON-encoded bodies or literal backslash-n (\n) sequences — those will appear as literal characters in the delivered message.
Correct — real newlines in a quoted string (plain text only, no backticks or $):
scion message --non-interactive @reviewer "PR #42 is ready for review.
Branch: fix/auth-bugCI: all green"Correct — heredoc for longer messages:
scion message --non-interactive @reviewer "$(cat <<'EOF'PR #42 is ready for review.
Branch: fix/auth-bugCI: all greenEOF)"Wrong — JSON-encoded body with literal \n:
# BAD: literal \n chars appear in the delivered messagescion message --non-interactive @reviewer "PR #42 is ready for review.\n\nBranch: fix/auth-bug\nCI: all green"Related Commands
Section titled “Related Commands”scion broadcast: Send a message to all agents in the current project, or use--allfor a global broadcast. The--broadcastand--allflags onscion messagehave been removed; use this command instead.scion keys: Send literal terminal input to an agent’s tmux session (e.g.,scion keys editor "Enter", as a separate call fromscion keys editor "Escape"), with no envelope and no automatic Enter. Useful for unblocking interactive prompts. Works for container-backed agents; not supported for managed-runtime agents (see Managed Agents). When run by an agent, it can only target agents in the agent’s own project — cross-project targets are refused, by the CLI and the Hub alike; a human operator using--projectcan target other projects, with the same authority asscion attachon the target. It is authorized like terminal attach rather than messaging — message mode does not gate it — and requires, for an agent caller, a live attach relationship on the target in addition to shared project membership (see CLI Reference). There is no key-sequence syntax: issue onescion keyscall per key press. This replaces the removed--rawflag onscion message, which now fails with guidance namingscion keys.
Conversation Management
Section titled “Conversation Management”The scion conversation command (alias conv) provides a surface-agnostic interface for managing conversations — the containers for message threads that span across the web chat, external channels, and CLI.
Conversations are referenced using one of three forms:
conv:<uuid>— by conversation ID.@<agent-name>— resolves the direct conversation with the named agent.#<thread-name>— resolves a named group conversation.
# List your conversationsscion conversation list
# View messages in a specific conversationscion conversation messages @tech-lead
# Create a new group conversationscion conversation create "sprint-planning"
# Set a default agent for a conversationscion conversation set-default "#sprint-planning" agent-id
# Catch up on recent messages (last 2 hours)scion conversation catch-up @tech-lead --since 2h
# Retrieve a single message by IDscion conversation get-message conv:a1b2c3d4-... msg-uuid-here
# List participants in a conversationscion conversation participants "#sprint-planning"
# Join or leave a conversationscion conversation join "#sprint-planning" user user-idscion conversation leave "#sprint-planning"A direct conversation registers both participants, so DMs you send or receive appear in scion conversation list.
An agent post into a group conversation or thread (by conv:<id> or thread ID) that @mentions no agent is delivered to the conversation’s default agent, as a human post is (if the sender may message it, and never to the sender itself). When the post reaches no agent, the response sets no_agent_woken and scion message prints a one-line notice.
For full flag details, see the CLI Reference.
Discord
Section titled “Discord”Scion supports Discord through two separate integration pathways:
- Bidirectional Discord Bot: Interact with agents directly from Discord channels using slash commands under
/scion(e.g.,/scion setupto link channels,/scion defaultto set routing targets,/scion agentsto check state). Agent replies are pushed back into the Discord channel with their own name and RoboHash-generated avatar. - Outbound Webhook Notifications: A simpler, outbound-only mechanism where agents push status updates, alerts, and
ask_userrequests to a designated Discord channel. Messages are color-coded by severity, and urgent notifications can trigger@useror@rolementions.
For a full setup guide and configuration options, see External Channels.
Telegram
Section titled “Telegram”Scion also supports bidirectional messaging over Telegram: message your agents from a Telegram group and receive their replies in the chat. For a step-by-step Workstation setup, see Setting Up Telegram; for how it fits alongside other channels, see External Channels.
Agent ask_user Integration
Section titled “Agent ask_user Integration”When an agent uses the ask_user tool (or similar mechanism depending on the harness), Scion automatically performs two actions:
- State Update: The agent’s state changes to
WAITING_FOR_INPUT. - Explicit Message: A persistent message from the agent, clearly stating what it needs, reaches you in Chat (and Discord, if configured), and the agent event appears in the notification tray.
Real-Time Delivery
Section titled “Real-Time Delivery”Messages are delivered in real-time to the Web Dashboard via Server-Sent Events (SSE). The Messages Tab on the individual agent detail page provides a real-time stream of all communication with that specific agent.
When an agent finishes a turn, its Stop hook mirrors the agent’s reply to the user who created it, so it reaches you as a message from that agent. Only agents created directly by a user are mirrored; sub-agents (agents created by other agents) are not. Each user notification is stored exactly once.
Messages record the sender’s and recipient’s projects. Human callers see these as senderProjectId and recipientProjectId on conversation messages; agent callers see them only on direct messages where both parties are named in the conversation.
Delivery failures
Section titled “Delivery failures”Messages are not silently dropped in these cases:
- Non-running recipients. A message is rejected if the recipient agent is not running (suspended, stopped, in error, or still starting). For direct messages, human or agent, the send fails immediately with a
409error. Pass--waketo resume a suspended agent and then deliver. Waking requires the same lifecycle permission as starting the agent (agent.lifecycle), for user and agent senders alike; without it the send fails with403and the agent is not resumed. Broadcast, group, and message-broker deliveries are rejected per recipient. A sending agent gets aDELIVERY_FAILEDsystem notice (“Message delivery to<agent>failed: …”) for each rejected recipient. - Reincarnating recipients. While an agent is being migrated with
scion reincarnate, messages to it are saved to its conversation history instead of being dispatched or dropped. DMs, group messages and @mentions return202with statusdeferred, and a sending agent gets aDELIVERY_DEFERREDsystem notice rather than a failure. The new generation is told to read what it missed withscion conversation catch-up. Scheduled messages that fire during a reincarnation fail loudly instead of being deferred. - Late broker failures. A Runtime Broker may accept a message into its short delivery buffer and then fail to deliver it, for example because the container has gone away. The broker reports this to the Hub. The Hub marks the message
failedrather than leaving itdispatched, and notifies the sending agent. - Group messages to non-running members. Group messages do not wake agents. A member that is not running is not dispatched to; its copy of the message is stored as
failedwith a reason (suspended members get a group-specific one), and the sender gets a per-member failure result. - Runtime Broker timeouts and cancelled requests. The failure is still recorded: the message is marked
failedand the sending agent still gets itsDELIVERY_FAILEDnotice even if the original request was cancelled or the Runtime Broker timed out. Failure reasons from the Runtime Broker are sanitized before they are stored or shown in a notice. - Agent messages to humans. If the Hub’s delivery queue for a project is saturated, the agent’s send fails with
503(unavailable); retry later. A retry may duplicate the message on an external chat channel such as Discord.
Message Authorization & Modes
Section titled “Message Authorization & Modes”Every agent is protected by a Message Mode that controls which users and other agents can send messages to it. An agent’s message mode can be managed in several ways:
- Web Dashboard: Use the mode controls on the agent detail page.
- CLI: Use
scion set-message-mode <agent-name> <mode>, or set the initial mode at creation time withscion start --message-mode <mode>. - Agent self-service: Full-role agents can call
set_message_modeprogrammatically to adjust their own or their children’s message modes.
The available modes are:
- Project Mode (Default): Any user with the
agent:messagepermission in the project can message the agent. Any peer agent in the project (that is not restricted by lineage mode) can also message it. The most permissive mode. Note that the default project-member role does not includeagent:message— messaging requires an owner, admin, or ancestry relationship with the agent (i.e., the agent’s creator or their ancestors). This aligns messaging authorization with the terminal attach permission gate. - Hub Mode: Behaves like Project mode within the agent’s own project, and additionally allows the agent to send direct messages across project boundaries when cross-project messaging is enabled. A project-mode agent can receive a cross-project DM but cannot reply across the boundary until granted Hub mode.
- Branch Mode: Only users in the agent’s ancestry chain (its creator and their ancestors), plus the agent’s direct parent and child agents, can message it. Agent-to-agent messages need both agents in branch mode and one to be the other’s direct parent; siblings, grandparents, and pairs that mix branch with another mode are denied.
- Lineage Mode: Strictly restricts messaging to users in the agent’s ancestry chain (its creator and their ancestors). No agent-to-agent messaging is permitted.
- None Mode: Seals the agent from all messaging except system-plane notices. No users and no agents can message a none-mode agent through normal paths.
A new agent’s mode is set once, at creation: the --message-mode flag of scion create or scion start if given, else the template’s message_mode, else the parent agent’s mode when an agent creates it, else project. A default that resolves to hub still needs a hub-mode grant.
To see modes:
scion whoami --fullshows the calling agent’s own mode (messageModein--format json).scion conversation getandscion conversation participantsshow a MSG MODE column for agent participants in the conversation’s project; for a conversation without a project (a DM or legacy group), in the calling agent’s project (messageModein JSON). It shows-for users, for agents outside that project, and for every agent when a user reads a conversation without a project.- When a send is denied, the CLI error names the reason and both modes, for example
message_denied: Message delivery denied [reason: ..., sender mode: branch, recipient mode: project] (status: 403).
Piercing
Section titled “Piercing”Highly privileged users can bypass an agent’s message mode restrictions. This is called piercing.
- Project Owners can pierce Branch and Lineage modes.
- Super-admins pierce all modes, including None mode. Piercing applies only to user identities — it is never inherited by an owner’s agents.
The Web Dashboard displays reachability indicators (e.g., whether you can message a specific agent) based on the computed messageability, which takes into account the agent’s mode, your ancestry relationship to it, and any piercing privileges.
Cross-Project Messaging
Section titled “Cross-Project Messaging”Agents can send direct messages across project boundaries when all three independent controls permit it. Cross-project messaging is off by default; all three must be enabled for a message to be delivered.
The Three-Control System
Section titled “The Three-Control System”| Control | Setting | Default | Who can change it |
|---|---|---|---|
| Hub availability | cross_project_messaging_enabled (Hub messaging settings) |
false |
Hub administrator |
| Agent outbound reach | Agent message mode set to hub |
project |
Agent owner or project admin |
| Receiving project inbound policy | crossProjectInbound on the destination project |
none |
Project owner or Hub administrator |
Project Inbound Policy
Section titled “Project Inbound Policy”Each project controls which cross-project messages it accepts via its crossProjectInbound setting:
| Policy | Meaning |
|---|---|
none |
Accept no agent messages from other projects (default). |
members |
Accept an external agent only when its originating human is an active member of the receiving project. |
any |
Accept an eligible agent from any project on the Hub. |
Enabling Cross-Project Messaging
Section titled “Enabling Cross-Project Messaging”-
Hub administrator enables the feature globally:
Terminal window scion hub messaging set --cross-project-enabled=true --revision <N> -
Project owner sets an inbound policy on the receiving project:
Terminal window scion project messaging set --project <project> --policy members --revision <N> -
Grant
hubmode to the sending agent:Terminal window scion set-message-mode <agent-name> hub -
Send a cross-project message:
Terminal window scion message --project <target-project> @<agent-name> "message"
Denial Codes
Section titled “Denial Codes”When a cross-project message is rejected, the system returns a specific denial code explaining the reason:
| Code | Meaning |
|---|---|
cross_project_disabled |
Cross-project messaging is disabled by the Hub administrator. |
cross_project_sender_mode |
The sender must be in Hub mode to send cross-project messages. |
cross_project_target_mode |
The recipient must be in Project or Hub mode to receive cross-project messages. |
cross_project_inbound_none |
The recipient’s project does not accept messages from external agents. |
cross_project_origin_not_member |
The sender’s originating user is not a member of the recipient’s project. |
cross_project_untrusted_origin |
The sender’s identity origin could not be verified. |
cross_project_surface_unsupported |
Cross-project messaging is not supported for this conversation type (e.g., group conversations). |
Developer Guide & Best Practices
Section titled “Developer Guide & Best Practices”For developers authoring agents and custom orchestrators, Scion’s messaging system follows a set of strict protocol rules and architectural patterns.
1. Message Length Limits
Section titled “1. Message Length Limits”Scion maintains different limits depending on the recipient type:
- User-Directed Messages (Agent-to-Human): Limited to 2,000 Unicode characters (runes). Each CJK character or emoji counts as a single character. Exceeding this limit causes
scion messageto fail with exit code1and print:validation_error: message exceeds 2000 character limit- Tip: If you have a long message or log to send to a user, split it into multiple messages under 1,800 characters, or write the full content to a shared scratchpad file and send the filepath.
- Agent-to-Agent Messages: No enforced length cap in code. You can send larger payloads safely between agents.
- Large-DM offload (opt-in): A Hub administrator can set
offload_threshold_runesin the Hub messaging settings (PUT /api/v1/admin/messaging). When an agent-recipient DM body is longer than the threshold, the agent’s terminal receives a short stub instead: the body size, a preview, and one command to fetch the full body (for example,scion conversation get-message conv:<conversation-id> <message-id> --body). The stored message, the Web Dashboard, and other observers always keep the full body. Plain messages are never offloaded. The default threshold is0(disabled); leave it there until your agent images include ascionCLI with that fetch command.
2. Reply Explicitly
Section titled “2. Reply Explicitly”Scion does not forward an agent’s end-of-turn text to anyone. A user, an agent or an A2A caller sees only what the agent sends on purpose with scion message. Instruct agents that answer people or other agents to reply with scion message.
3. Inbound Message Type Discrimination
Section titled “3. Inbound Message Type Discrimination”When an agent receives an inbound message in Hub mode, it arrives as a JSON object wrapped in standard delimiters:
You are receiving a message from the orchestration system:
---BEGIN SCION MESSAGE---{ "timestamp": "2026-10-08T21:00:41Z", "message_id": "5d0c8a2e-7f41-4b8e-9c1a-2f6e0b3d9a17", "conversation": { "id": "af3cd254-0489-408f-a876-a749ec6e7f98", "kind": "direct", "surface": "native" }, "from": "agent:tech-lead", "type": "message", "msg": "Write a unit test for the auth package."}---END SCION MESSAGE---The timestamp is when the message was created, and message_id is the ID of the message the Hub stored for this delivery, so an agent can name the exact message it received, for example to tell the sender which message it is answering. When the envelope names a conversation, the agent can also fetch the message with scion conversation get-message conv:<conversation.id> <message_id>; when conversation is omitted (for example on a broadcast), there is no conversation to pass and the message cannot be fetched that way. message_id is omitted when the Hub stored no message for the delivery: scheduled messages, status notifications, artifact review notices, and plain (--plain) deliveries, which carry only the text. In a reply, reply_to still names the message being replied to; message_id names the reply itself.
Always check the type field before acting or replying:
| Type | Meaning | Action Required |
|---|---|---|
message |
A message for you: a direct message, a group message, or a message routed to you in a chat thread. An @mention fanned out from another agent’s scion message also arrives as message, and so does a notification that an agent you subscribe to is waiting for input (see below). When the message went to several agents, to may list them. |
Read and act on it. |
reply |
A reply to a message you previously sent. Routes to the original sender agent, not the thread default. reply_to is the ID of the message being replied to, and reply_context holds its first 32 characters. |
Read and act on it like a message. |
mention |
You were @mentioned in a chat message whose primary recipient is someone else. to lists every agent the message engaged, including you. |
Treat as FYI unless explicitly directed otherwise. |
event |
A notice generated by Scion rather than written to you. The event object says what happened: event.type is one of agent.state-changed (an agent you subscribe to changed state; event.subject names the agent and event.status the state, for example COMPLETED or STALLED), schedule.fired (a scheduled message; msg is the scheduled text), delivery.failed (a message you sent was not delivered; event.status is DELIVERY_FAILED, or DELIVERY_DEFERRED when it was saved for an agent that is reincarnating), port.exposed, or artifact.review. |
Act on a schedule.fired message’s text; treat the others as FYI or follow the instructions in the notice. |
Handling Waiting-for-Input Notifications
Section titled “Handling Waiting-for-Input Notifications”When an agent signals WAITING_FOR_INPUT (by calling sciontool status ask_user), a notification is dispatched to all subscribed agents (including its creator). It arrives as a message from the waiting agent, with text such as <agent> is WAITING_FOR_INPUT: <question>.
- Parent Agent Role: If you are the parent agent that created the waiting agent, you may be the intended respondent. Use
scion message @<name>to reply with the answer. - Peer Agent Rule: Unrelated peer agents should NOT reply to waiting-for-input notifications. Answering a peer’s input prompt wastes context tokens, causes false loop signals, and violates project-scoped boundaries. To request a peer’s input, always send it an explicit message instead.
Halted Agent Notifications
Section titled “Halted Agent Notifications”When the platform halts an agent (for example its Kubernetes pod was preempted or evicted, or it was killed for running out of memory), Scion sends one HALTED notification for that halt, with text such as:
worker-1 was halted by the platform (preempted). Workspace kept. Resume: scion start worker-1.The workspace part says what scion start does with the workspace: Workspace kept, Workspace re-cloned (a workspace on the pod’s own storage), or Workspace may be re-cloned (where it lives is not known).
Who receives it:
- The agent’s creator, when they have no subscription to the agent or its project: the user who created the agent, or the agent that created it (while that agent still exists in the same project). A creator who has a subscription gets
HALTEDonly if that subscription selects it. - Subscribers with the
HALTEDtrigger.HALTEDis one of the default triggers of the subscription recorded when an agent is created with notify on, and one of the Web Dashboard’s default and selectable triggers. The default triggers ofscion notifications subscribedo not include it; add it with--triggers. - Subscribers with only the
ERRORtrigger, when the halt replaced what would have been anerror(for example a preempted pod whose workspace did not survive). They receive it with statusERROR, as they would have without the halt.
Each subscriber, including the creator, receives one notification per halt.
Notification Delivery Retries
Section titled “Notification Delivery Retries”If a notification cannot be delivered to a subscriber agent (for example because its Runtime Broker is not connected), it is not marked as sent. The Hub tries again on a sweep about every 5 minutes, and again when the Runtime Broker reconnects, for up to 24 hours after the notification was created. Each notification records its number of delivery attempts (dispatchAttempts) and an outcome (dispatchOutcome): delivered, or failed once the 24 hours have passed or the subscription, subscriber or watched agent is gone. The outcome is empty while delivery is still pending. A subscriber agent that has no Runtime Broker is not attempted, so its notification stays pending and does not reach the 24-hour limit.
4. Subscription Management and Agent Self-Service
Section titled “4. Subscription Management and Agent Self-Service”- Automatic Subscription: The
--notifyflag onscion startis deprecated. When you start a sub-agent, Scion automatically registers your subscription via creation ancestry. - Explicit Messaging Subscription: Use the
--notifyflag onscion messageonly when you need to subscribe to notifications from a peer agent that you did not create. - Agent Self-Service Subscriptions: Running agents in Hosted mode are empowered to programmatically manage their own notification subscriptions. Previously restricted to administrative users (returning a
403 Forbiddenfor agents), agents with appropriate API credentials can now perform the following operations:- CRUD Operations: Live agents can list, create, update, and delete their own subscriptions via the Hub API or client utilities.
- Identity Qualification: To prevent cross-project security leaks, every subscription request is qualified by the agent’s specific
(project, slug)coordinates. - Granular Scopes: Authorization gates require the agent token to hold the
project:readscope for reading subscriptions and theproject:agent:notifyscope for writing (creating, updating, or deleting) subscriptions. - Ownership Constraints: Acknowledging notifications or modifying/deleting existing subscriptions strictly requires ownership validation, meaning an agent can only modify or acknowledge subscriptions that target or belong to itself.
5. Security Controls for Direct Messages & Broadcasts
Section titled “5. Security Controls for Direct Messages & Broadcasts”Scion employs strict, ingress-level security controls and invariants for Direct Messages (DMs) and Broadcasts to prevent spoofing, cross-project injection, and message divergence:
- Server-Side Sender Identity & Derivation: Sender identity is forced server-side based on the authenticated request context, completely ignoring any sender claims in the payload. Furthermore, DM conversation keys are derived dynamically from the authenticated caller rather than trusting the payload, closing spoofed-sender conversation-selection vectors.
- Canonical DM Key Enforcement: Thread IDs (used as DM keys) undergo strict canonicality enforcement. Non-canonical kinds and UUIDs are rejected immediately at derivation without silent normalization, ensuring precise routing.
- Participant Guard Consolidation: A unified participant guard (
CheckDMParticipantKey) protects all DM ingresses (adding/ensuring participants or merging conversations). This strict invariant guarantees that participant records cannot diverge from their canonical thread keys. - Broadcast Authorization: Project membership is strictly required and enforced for all broadcast calls.
- Publish Gating & Stamping: Message publishing to real-time streams (SSE) is securely gated on successful database persistence (dual-write conversation stamping). This ensures that a message is never broadcasted to clients without being safely committed to history.
6. Sleep Anti-Pattern & Polling
Section titled “6. Sleep Anti-Pattern & Polling”Instead, pair sciontool status blocked with a scheduled self-callback using scion schedule create:
# Correct way to wait 5 minutes for a build to finish:scion schedule create --in 5m --message "Check build status" --agent "$(scion whoami --non-interactive --format json | jq -r .name)"sciontool status blocked "Waiting for build job 103"The scheduled message delivers the wake-up poke; status blocked tells the platform that your silence is intentional, keeping you from being suspended.
7. @mention Parsing & Conversation Addressing
Section titled “7. @mention Parsing & Conversation Addressing”@<agent-name> is now the preferred addressing form for sending messages to agents via the CLI (e.g., scion message @tech-lead "..."). This form addresses the agent’s conversation directly.
When a human or an agent sends a message, Scion automatically scans for recipient targeting to fan-out notifications:
Body @mentions
Section titled “Body @mentions”Any name starting with @ in the message body (e.g., @dev-lead) is automatically parsed. If the name matches an active agent within the same project, Scion generates a secondary message of type mention and delivers it to that agent.
Multi-Recipient Addressing
Section titled “Multi-Recipient Addressing”To send to multiple recipients at once, use the group[...] addressing form:
scion message "group[tech-lead, dev-agent, qa-agent]" "Let's review the deployment strategy"A group send reports each recipient’s outcome and exits 3 when only some recipients received the message; see Group sends and exit codes.
Validation & Integration Rules
Section titled “Validation & Integration Rules”- Deduplication: If an agent is both
@mentionedinside the body of a message and explicitly addressed as a recipient, Scion automatically deduplicates the list so they only receive a singlementionmessage. - Project Scope Restriction: Mentions are restricted to the parent project boundary. Body-mentions can only be resolved and delivered to agents that belong to the same project. Unresolved names will result in a warning printed to stderr, but will not fail delivery of the primary message.
- Fan-Out Restrictions: A single message is fanned out to a maximum of 10 recipients per
@-mentionbroadcast. - Agent-Authored Mentions: When an agent’s message @mentions another agent, the Hub delivers the mention server-side, authorized like a direct message and charged to the sender’s send budget. Mentions between the same pair of agents are also capped (10 deliveries per 10 minutes) to stop mention loops. A mention that is denied or rate-limited is skipped without failing the primary message.