Web Dashboard
The Scion Web Dashboard provides a visual interface for managing your agents, projects, and runtime brokers. It complements the CLI by providing real-time status updates and easier management of complex environments.
Open the dashboard on the URL the server prints at start (http://localhost:<port>). HTML artifacts are served with a policy that names that URL, so one opened through another host name, such as 127.0.0.1, shows its page without its own scripts, styles and images (see HTML artifacts). On a Hub with a separate content host (server.hub.content_url), shared artifact links (shareUrl) and HTML artifact views opened from a shared link are served on that content host instead.
Overview
Section titled “Overview”The dashboard is organized into several key areas:
Dashboard Home
Section titled “Dashboard Home”The landing page provides an overview of your active agents across all projects and the status of your runtime brokers.
Notifications & Alerts
Section titled “Notifications & Alerts”The dashboard features an integrated notification framework with real-time SSE delivery.
- Unread Chat Badge: The Chat entry in the mode switcher shows how many of your chat conversations have unread messages, and the browser tab title shows the same count. Messages from your agents arrive as chat conversations; there is no separate inbox tray. See Messaging & Notifications.
- Notification Tray: The bell opens agent events (status changes such as stalls, errors, and requests for input), with agent-scoped filtering. Chat messages do not appear in the tray.
- Browser Push Notifications: Opt-in native browser push notifications ensure you receive alerts even when the dashboard is in the background. Default triggers include
stalledanderrorstates, as well as requests for user input.
Mode Switcher
Section titled “Mode Switcher”The header features a mode switcher that lets you move between the top-level workspaces: Dashboard, Chat, and Terminal. The header adapts to the viewport width in three tiers:
- Wide (above 1100 px): A segmented mode switcher with text labels and icons, with inline buttons for notifications, help, theme, profile, and sign-out.
- Medium (768–1100 px): The mode switcher shows icons only. Notifications, help, theme, profile, and sign-out move into a single account dropdown. A badge dot on the dropdown shows unread notifications.
- Narrow (below 768 px): The mode switcher becomes a dropdown, next to the account dropdown and a hamburger menu.
Notifications stay reachable at every width. The Chat entry shows the unread conversation count, and the Terminal entry shows how many terminal sessions are open.
Keyboard shortcuts: Cmd+1, Cmd+2 and Cmd+3 on macOS (Ctrl+1, Ctrl+2 and Ctrl+3 elsewhere) switch to Dashboard, Chat and Terminal. The shortcuts use the physical digit keys, so they are the same on every keyboard layout. They are on by default; turn them off with the View mode shortcuts switch on your profile settings page. The setting is stored in the browser.
The web UI also works on phones, down to 320 px wide and in landscape, including notched screens and the on-screen keyboard. Wide code blocks and tables scroll sideways on their own instead of widening the page, and a sideways swipe does not trigger the browser’s Back gesture.
Display Timezone & Clock
Section titled “Display Timezone & Clock”The dashboard shows clock times in 24-hour format. The Display timezone card on your profile settings page sets the zone used to show times and to read date/time inputs in native chat and scheduling forms. Agent and project lists, relative times, admin and access-boundary views, log viewers, chat, and the file browser all format times in this zone. Auto, the default, follows your browser’s zone. The value is stored per user as the timezone preference (see the Users API). It affects only what you see, never the TZ of agent containers. For that, see Agent timezone.
Native Web Chat
Section titled “Native Web Chat”When enabled via the web.native_chat feature flag, the dashboard includes a top-level Native Web Chat workspace (a fourth ShellType in the SPA). It offers a rich interface for direct communication and coordination with your running agents and team.
- Project-Scoped Spaces & Shared Threads: Conversations are organized into distinct spaces scoped to specific Projects. Within these spaces, users and agents can collaborate on shared discussion threads.
- Project Context Preservation (Mode Switching): When you switch between Dashboard, Chat, and Terminal modes using the header mode switcher, the system maintains your active project context so you do not lose your place:
- Dashboard → Chat: Clicking the Chat icon while on a project-scoped dashboard page (e.g.,
/projects/:id/...) 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 view defaults back to the top-level dashboard/.
- Dashboard → Chat: Clicking the Chat icon while on a project-scoped dashboard page (e.g.,
- Direct Messages (DMs): Start 1-on-1 direct messages covering both human-to-human (H2H) and human-to-agent (H2A) communication, consolidated as a single “global pair” thread per pair.
- Members Sidebar, Presence & Typing: A right-hand sidebar displays active project members, showcasing real-time online presence status and typing indicators.
- Composer Default-Agent Disambiguation: When sending messages in spaces with multiple active agents, the composer helps resolve which agent is targeted if no explicit mention is used.
- Attachments: Upload file or image attachments directly within the composer, with preview tiles rendered instantly on real-time SSE updates.
- Search: Built-in chat search lets you query across historical messages and threads.
- Clickable File Paths: File paths in chat messages starting with
/workspace/...or/scion-volumes/...automatically render as clickable links, including paths inside inline backtick code spans (fenced code blocks are left untouched). Only file paths are linked, meaning the last segment has an extension or is a known extensionless file such asMakefileorDockerfile. Directory paths stay plain text. Clicking these paths opens an on-demand file viewer dialog, fetching the file contents instantly via existing workspace and shared-directory APIs. - Chat/Log Switcher: Instantly toggle between standard conversational chat with the agent and a real-time stream of the agent’s raw execution logs inside the same view.
- Conversation Export: Export any thread via the export dropdown in the chat header — download as Markdown, print/save as PDF, or copy to clipboard (HTML + plain text). All exported content is HTML-escaped for safe rendering.
- @-Mentions & Autocomplete: Call other agents into the thread by typing
@to trigger a fuzzy-matching, keyboard-navigable agent dropdown. Protected by code-fence guards to prevent triggering inside Markdown code snippets. - Visibility Density Filters: Choose from three filter levels—Conversation (pure dialogue), Verbose (adds mentions/CCs), or Full (adds state updates and background processes)—with preferences saved individually per agent.
- Layout Density: Switch between Dense and Comfortable layout modes via the density toggle to control whitespace and information density across the chat interface.
- Space Emoji Icons: Assign optional emoji icons to spaces (stored in project annotations) for quick visual identification in the thread rail.
- Thread Drag-and-Drop & Collapsible Groups: Reorder threads in the thread rail by drag-and-drop. Organize threads into named collapsible groups; ordering is persisted server-side via user preferences.
- Bidirectional Mention Translation:
@-mentionsare automatically translated between the@firstname-lastnameformat used in the web chat and the@emailformat used by agents, ensuring natural display for each context. - Agent-to-Agent Message Expansion: Background inter-agent communications (displayed in the Full density view) are collapsed into a compact pill to preserve screen space. Expanding the pill lists the messages under date dividers (e.g.
Sep 23, 2026) whenever the day changes. Each message uses a two-line layout: a header with the 24-hour time andsender → recipient, above an indented body limited to 2 lines. Truncated messages feature a zoom/expand icon (arrows-angle-expand) that opens a rich, full-screen Markdown-rendered dialog overlay showing the message’s date and time (e.g.Sep 23, 14:15), closeable via its X button or by clicking outside. - Scheduled Send (experimental): With the
web.chat_scheduled_sendexperiment on (default off), right-clicking Send (or long-pressing it on a touch screen) offers Schedule send, in topics and direct messages. The Hub holds the message and sends it as you at the chosen time, at least one minute and at most 90 days ahead. Until then only you see it, with a Cancel button. The Hub delivers each scheduled message at most once and checks your access again when it sends; a message found more than 60 minutes late is not sent but offered back to you with Send now. See Scheduled Chat Messages. - Coherence Sync: Real-time sync ensures actions taken on external channels (e.g. Discord or Teams) propagate instantly to the Web UI, with delivery state tooltips indicating whether messages succeeded.
Terminal Workspace
Section titled “Terminal Workspace”The Terminal Workspace provides a dedicated, multi-pane terminal environment as a top-level workspace alongside Dashboard and Chat. It allows you to manage interactive terminal sessions with your agents in a persistent, multi-pane layout.
- Multi-Pane Layout: Open multiple agent terminals side by side. The workspace preserves your active pane layout during navigation and places newly opened terminals into available slots. In a multi-pane layout, clicking a terminal in the rail that is not already in a pane puts it in the first empty pane; a terminal already in a pane is focused where it is, and with no empty pane the layout does not change. A multi-pane layout restores its panes in parallel rather than one after another.
- Shareable Layout URLs: Multi-pane layouts (the active preset and which agent occupies each pane) are encoded in the page URL. Reloading the page restores the layout, the browser Back and Forward buttons step through layout changes, and you can bookmark or share the URL to reopen the same multi-pane configuration. Single-pane views keep a clean URL. If the layout parameters are malformed or refer to agents that no longer exist, the workspace falls back safely.
- Session Restore: The Hub saves your list of open terminals and which one was in front, per user, and restores them the next time you open the Terminal Workspace, including from another browser or device. Only the frontmost terminal connects automatically; the others are restored to the rail and connect when you open them. Agents that have been deleted, or that you can no longer attach to, are dropped from the restored list. If the URL names a specific agent or layout, the URL decides what connects.
- Jump to Agent (Cmd+K): The Jump to agent button at the bottom of the Open terminals list, or Cmd+K, opens an agents-only palette (a space in the query also matches a hyphen or underscore in agent names). Cmd+K works from anywhere in the Terminal Workspace, including from inside a focused terminal pane. Ctrl+K works too, but only when focus is outside a pane, because inside a pane it is sent to the terminal. Pressing the shortcut again closes the palette. In a single-pane view, picking an agent shows it like a rail click. In a multi-pane layout, the agent fills the next empty pane, or replaces the focused pane when every pane is in use.
- Cross-Tab Ownership: Terminal sessions are tracked across browser tabs, preventing conflicts when the same agent is accessed from multiple tabs. A terminal connection can be open in only one place at a time. A window that does not own the terminals says Terminals open in another window and offers Move terminals to this window, which closes them in the owning window and opens them in the current one.
- Reconnect Controls: If a terminal session is interrupted, the workspace provides reconnect controls to resume where you left off. When a pane drops for a retriable reason, such as a network blip or a brief loss of the Runtime Broker connection, the workspace makes one automatic reconnect attempt the next time that pane is in front, showing a Reconnecting… overlay. A clean detach, an ended session, or a missing agent is not retried automatically. Attaching to a stopped agent ends right away instead of waiting to retry. When a stopped or crashed agent is restarted, the pane reconnects on its own once the agent is running again; agents in the
errorphase are treated as stopped. If the automatic attempt fails, use the Reconnect button. The All terminals toolbar in the open terminals list has two bulk actions: Reconnect all connects every terminal that is not connected and whose agent still exists, including terminals restored but not yet opened. Remove all inactive (after a confirmation) removes terminals from the list, without affecting the agents: every terminal whose session has dropped or whose agent was deleted, and every restored but not yet opened terminal whose agent is stopped, in theerrorphase, or deleted. Terminals that are connected or still connecting stay, as do restored terminals for agents that are still running. When a button has nothing to act on, it stays focusable and a tooltip explains why. - Scoped PTY Cleanup: When you close a terminal or navigate away, the workspace performs scoped cleanup of its PTY sessions to reclaim resources.
- Pane Focus: In multi-pane layouts, the active pane is highlighted with a focus outline. Switching to a single-pane view automatically removes the outline.
Projects
Section titled “Projects”View and manage your registered projects.
- Create/Register Project: The New Project dialog opens with a Start from picker:
- Blank (default) asks for a Workspace Type: Git Repository, Shared workspace directory (one Hub-managed directory shared by every agent, the default), Empty directory per agent (each agent gets its own private, initially empty directory, with nothing shared and no git repository), or Local Directory (linked) (Workstation only). A confirmation dialog appears when you create a project for a git repository that already has one. For how the workspace types map to sharing modes, see Workspaces & Sharing Modes.
- A project template lists every project created with Create Template on a project’s detail page, and clones it (see Clone Project below). The template’s workspace settings are locked and shown in a summary of what is and isn’t copied. Secrets, agents, history, and chat integrations are not copied. For a git template you can supply an optional Git Remote URL override, and the new project then uses that repository.
- Clone Project: Deep-copy settings, labels, environment variables, GCP service account associations, skills, lifecycle hooks, harness configurations, and templates from an existing project to a new project. Cloned service account registrations are marked as unverified to force re-verification on the target project. Built-in defer-driven rollback ensures transactions are atomic and safe. Supports an optional Git remote override so cloned templates and configurations carry over while target users can supply their own repository.
- Project Settings: Centralized configuration interface for managing project-scoped environment variables, secrets, and injected skills, including “Injection Mode” controls (Always vs. As-Needed). The settings page features a streamlined flow with a “Done” button, hides unnecessary registration options for git-backed projects, and displays Hub-default placeholders for unset configurations. The configuration UI is organized into tabs matching the agent-create form’s existing structure, splitting the general settings into:
- General: Template, harness, model, and telemetry settings.
- Auth & Security: Harness authentication, default agent roles, maximum allowed roles, and default project service accounts.
- Batch Skill Injection: Paste a GitHub directory URL (e.g., referencing a folder containing multiple skill subdirectories) into the skill input to trigger directory-discovery. An interactive checkbox dialog allows selecting which skills to add, and submits them as a single atomic batch, with any embedded credentials/userinfo automatically stripped before logging for safety.
- Members and Visitors (project settings): The Members editor lists the project’s users and groups and their roles. When the
federation.project_visitorsexperiment is on, project owners and admins (and hub admins) also see a Visitors tab beside it. A visitor is a user of another hub or identity provider that this Hub trusts. A visitor can message the project’s agents and see their names and status, but is not a project member. On the Visitors tab:- Add Visitor gives access to one email address, or to every user whose verified email is in an email domain (the domain matches exactly; subdomains are not included). Choose an optional expiry: 7, 30 or 90 days, 1 year, or no expiry.
- Issuer: visitors always come from one trusted issuer. A hub admin must first allow visitor access for that issuer on Admin > Federation. Hub admins pick from the issuers that allow it. Other owners type the issuer URL exactly as the issuer names itself: an
https://URL, which may have a path but no query, fragment or user name, and not the issuer’s discovery document or key set URL. The accepted issuers already used on the project are offered as shortcuts. When the Hub does not accept the issuer or the email, the dialog shows the Hub’s message. - The list shows each domain rule and each visitor with their issuer, status, who granted access and when it expires. Expired means the expiry has passed and Not yet active means the start is still to come; the Hub refuses the visitor in both cases. Otherwise, Pending means the visitor has not sent a request yet, and Active and Suspended follow the visitor’s account. Issuer disabled by hub admin means the hub admin has turned visitor access off for that issuer: the grant is kept, but the visitor’s requests are refused until it is turned back on.
- Change expiry sets a new expiry, counted from now, for a grant by email or a domain rule; it can also shorten the access. A visitor added by a domain rule follows the rule’s expiry. Revoke removes a visitor’s access, and the visitor’s next request is refused (a visitor a rule added is not added again by that rule). Remove on a domain rule removes the rule and every visitor it added.
- The same operations are available from the CLI (
scion project visitors, see the CLI reference) and the API (see the API reference).
- Workspace & File Management: Access the comprehensive inline file editor to view and modify files directly in the browser, featuring integrated Markdown preview capabilities. The file browser supports fuzzy and regex-based filtering for fast navigation. You can also download individual workspace files or generate ZIP archives of entire projects directly from the UI.
- Template Management: Direct server-side importing of templates with immediate UI feedback. Includes full template file browsing, editing, and upload capabilities directly within the dashboard. User-scoped templates can be created, cloned, renamed, and inspected via the profile template management UI. An actions dropdown provides streamlined access to template operations, and rename preserves the template’s display name, description, and harness configuration.
- Shared Directory Management: View and manage project shared directories directly from the Web UI (see Project Shared Directories).
- Agent List & Lineage Views: See all agents belonging to the project, with options to toggle between card, list, and the interactive Agent Lineage Graph view. The agents section is collapsed to a fixed-height, scrollable area by default. Use the expand/collapse toggle to show it at full height. Your choice is remembered in the browser and applies to all projects. In the list view sorted by last update, the Hub sorts the agents server-side: a project with 50 agents or fewer loads in a single request, and a larger project loads one page at a time, with Prev/Next controls and a page size of 25, 50, or 100. A project with more than 2,000 agents, or a free-text label filter, falls back to the unsorted listing.
- Large deployments: The main Agents page and the home dashboard also page through server-sorted results instead of loading every agent. The tree and graph views need the whole set, so they load at most 4 pages of 500 agents and mark the list as capped when there are more. With more than 2,000 agents, the home dashboard shows agent counts only.
- Lineage Graph View: Renders parent/child agent relationships as a zoomable, pannable parent/child forest. Supports a left-to-right horizontal layout option (via a segmented toolbar toggle and
transposeLayout()helper), custom keyboard shortcuts for fast navigation, updated edge and arrowhead geometry for precise alignment, and collapse pruning for complex trees. - Jump to Agent (Cmd/Ctrl+K): On graph views, Cmd+K or Ctrl+K (or the header’s palette button) opens an agents-only palette listing the agents the graph currently shows. Picking one expands its collapsed ancestors, then centers, highlights, and focuses its node. Nothing is refetched and no filter changes.
- Inline Integration: The lineage graph is an inline tree/graph component rendered directly in the main agent content slot on both the main Agents page and individual Project detail pages. Filters for agent status and labels apply automatically across card, list, and graph views.
Agents
Section titled “Agents”Detailed view for individual agents, featuring a high-density tabbed layout and improved breadcrumb navigation with a dedicated back button.
- Unified Agent Creation: A unified single-page interface for creating and configuring agents that merges the previous two-phase create/configure flow into a single step (removing the
editingAgentIdround-trip flow).-
Primary Fields: The default visible section features fields for Name, Project, Template, Harness (Type), Broker, Profile (with a native Runtime Profile Selector that dynamically populates available profiles based on the selected broker), Task, and Notify settings.
-
Additional Options: A collapsible area, shared with the Edit page’s form, in five tabs:
- General: Branch (git projects only), Model (a model ID, or pick a size alias), Thinking level, Container image, Container user, Telemetry, and Auto-expose ports with its port filter and scan interval.
- Auth & Security: Agent role, Message mode, Harness authentication and GCP Identity.
- Prompts: System prompt and Agent instructions.
- Limits & Resources: Max turns, Max model calls, Max duration, and CPU, memory and disk requests and limits.
- Environment & Labels: environment variables and labels.
The request carries only the options you set; the Hub resolves everything else. A field you leave empty shows, as grey placeholder text, the value it will inherit and where it comes from (the template, the project settings or the Hub defaults), when the page can read it from those settings; otherwise it just says Inherited. These placeholders cover the template, the project settings and the Hub’s public settings only, not every source the Hub consults. Choices such as Telemetry, Agent role or Harness authentication start blank, meaning inherit (an inherited Agent role is the project default, capped at the project maximum); pick a value to set it, and Clear returns a field to its inherited value. Unlimited removes a limit and is separate from Clear. A project’s telemetry setting overrides the agent’s value, so when the project sets it, the Telemetry placeholder says so. The Hub-wide public telemetry setting is not shown as an inherited value, because the Hub does not apply it when it creates an agent. GCP Identity starts with no mode chosen (unless the project’s default applies), and the hint explains which default the server applies; any pick, including Block, is sent as your choice.
-
Form Actions: Start creates the agent and starts it, then opens the agent’s page. Cancel leaves the form without creating anything. The form has no create-only action; to create an agent without starting it, use
scion create. If the agent is created but does not start, a toast says so with the reason, and the agent remains in the list.
-
- Agent Identity & Roles: The agent detail page includes an expanded GCP Identity card that displays the service account email and target Google Cloud project for all identity modes. This card also displays a color-coded role badge representing the agent’s active authorization tier (
full,baseline,readonly, ornone). - Quick-Message Button: Found on agent details, list, and graph cards. Instantly open an interactive modal dialog to chat with an agent (use
Enterto send,Shift+Enterfor a newline), gated by your existing message permissions. When web chat is available, an Open agent DM button closes the dialog and opens the agent’s direct message in chat, carrying over any text you have not sent yet. - Agent Badges (experiment): With the
web.agent_badgesexperiment on (default off), agent cards and rows on the Agents and project pages, and every graph card, start with a harness vendor mark and the agent’s configured model size (S, M, L or XL, chosen as a size alias at create). Hover for the harness and the size in full. Multi-vendor harnesses (OpenCode, Copilot, Hermes) show only the harness mark. An agent started with an explicit model ID, or with no model, has no size chip, and a custom harness shows ?. - Graph Card Terminal Shortcut: Connect straight to an agent’s interactive terminal directly from its card in the graph view via a dedicated, icon-only shortcut button. Gated by attach capability and disabled when the agent is offline.
- Status Tab: Real-time view of agent lifecycle (Starting, Thinking, Waiting, etc.), including the
suspendedanderrorphases. Includes stalled agent detection to flag agents that are alive but hung (activitystalled) and offline detection for agents whose heartbeat has gone silent (activityoffline). An agent with activityinitializing(its harness is not yet reading input) is shown as starting. An agent with activityblocked(intentionally waiting) is shown as waiting on others, and an agent with activitywaiting_for_inputis shown as waiting on parent; the API and CLI still reportblockedandwaiting_for_input. A crashed agent (non-zero exit) is shown in theerrorphase using structuredExitCodeandExitReasondata for high-fidelity crash detection, and can be restarted from the UI. - Logs Tab: Streamed logs from the agent container via the integrated Cloud Log Viewer.
- Messages Tab: A dedicated tab for viewing structured messages sent to and from the agent.
- Configuration Tab: Dedicated tab for viewing the applied configuration of the agent, featuring a new telemetry configuration card. If you can manage the agent’s lifecycle, the tab also has a Reincarnate button that, after a confirmation, stops the agent and re-provisions it with its current configuration (the web counterpart of
scion reincarnate). - Edit Page: The agent page has an Edit button in every phase for users who can update the agent. The Edit page (
/agents/<id>/edit) shows every setting of the agent, in the same form as Additional Options on the create page. The old Configure page is gone;/agents/<id>/configureopens the Edit page.- Grouping: By function shows an Agent section (name, next task, and the fields fixed at creation), then sections matching the create page’s tabs. With the
web.agent_editexperiment on (the default), a toggle adds By when it applies, which groups the same fields by what the agent’s phase does with an edit: Applies at next start (a suspended agent: Applies at resume; a running agent: Held until the next start), Needs reincarnation (prompts, unless the agent’s Runtime Broker renders them again at start, then the role and GCP identity under Changes identity), Takes effect immediately, and Fixed. The page remembers your choice, and a strip at the top counts the fields by when an edit applies. With the experiment off, the page shows the by-function view only. - Fields: Each field says when an edit applies, shows an unset field’s inherited value as a placeholder, and shows a lock with the reason when it cannot be edited. Clear reverts a value set on the agent to its inherited value (a field that only inherits has nothing to clear; the name and the next task have no Clear), and Unlimited removes a limit. On Auto-expose ports and Resources the button is Undo, which discards your change. Unlimited on Max duration applies at the next start or resume like any other edit. Clear reaches the agent at its next start when its Runtime Broker applies cleared values at start, and otherwise at its next reincarnation. Unlimited on Max turns is reported as held for reincarnation on every Runtime Broker; it does not yet override an inherited limit at a start or a reincarnation (ptone/scion#5605). The page says when each change applies.
- Environment variables start from the agent’s current environment, and are sent only when you change them or the auto-expose control. Saving a change replaces the agent’s stored environment with the list shown, so values the page cannot show you, such as
GITHUB_TOKEN, are not kept (ptone/scion#5599 tracks keeping them). A user who cannot attach to the agent does not see its environment, so for them the environment and auto-expose fields are locked. - Auto-expose ports shows a value set on the agent as the control’s value; a value inherited from the project or the Hub default is grey placeholder text with its source, so picking it sets it on the agent. Undo discards your change to the control.
- Name and labels can be edited in every phase and take effect immediately. The name can be replaced but not emptied. Message mode is shown read-only; change it on the Messaging card of the agent page.
- Timezone pins the agent’s container timezone and is saved with Save like any other field; Clear unpins it. A change applies at the agent’s next start. See Agent timezone.
- Next task is the task given when the agent next starts fresh. It can be replaced but not emptied. A resume continues the conversation and does not send it, so it cannot be edited for a suspended agent.
- Not editable yet: a running agent’s container settings (model, limits, environment and so on), the system prompt and agent instructions (in every phase, unless the agent’s Runtime Broker renders them again at start: then they apply at the next start of an agent with no container), and, after the first start, the role and GCP identity. These show their badge (for example Needs reincarnation) and stay disabled until saving such edits for later is available. A created agent’s GCP identity can be edited; its role cannot.
- Actions: Save sends only the fields you changed. Save & Start (
created,stopped,error) or Save & Resume (suspended) also starts the agent with the new values; a running agent has Save only. When edits are held for a reincarnation, Reincarnate… is offered too, and its confirmation names them. If someone else changed the agent after the page loaded, the save is refused and the page offers Reload, keeping your edits. Delete stays on the agent page; Back to agent returns there.
- Grouping: By function shows an Agent section (name, next task, and the fields fixed at creation), then sections matching the create page’s tabs. With the
- Debug Panel: A full-height panel providing a real-time stream of SSE events and internal state transitions for advanced troubleshooting and observability.
- Terminal: Interactive terminal access to the agent’s workspace, featuring full Tmux support. Includes a dedicated terminal toolbar, seamless window switching (agent/shell), automatic window size adjustment, extended key sequence support (like
Shift+Enter), and modifier-based text selection (Shift-drag orOption-drag on macOS). For detailed configuration, see Interactive Sessions with Tmux. - Workspace Content Previews: Content preview capabilities for workspace files directly within the UI, allowing you to quickly inspect agent output and project data.
- Lifecycle Control: Start, stop, suspend, restart, or delete agents from the UI. Suspending an agent preserves its harness session so a later start continues the conversation rather than starting fresh, while restarting a crashed (
error) agent runs a clean session. For anerroragent you can instead choose Resume (best effort), which asks for confirmation and then tries to continue the interrupted harness session. Includes bulk operations like the “Stop All” button for efficient bulk shutdown of all agents within a project. To reclaim resources, the Hub can also auto-suspend stalled agents whenserver.hub.auto_suspend_stalledis on (off by default); a message sent with wake resumes them. See Agent Lifecycle. - Agent Delete States: The Hub deletes agents in the background, so a deleted agent stays visible with a Deleting… badge until the Hub reports it gone, and the agent detail page then returns to the list. While an agent is deleting, its Start, Stop, Suspend, Resume, and Delete actions are hidden. If the delete fails, the agent shows Delete failed (with the reason) or Delete interrupted (the Hub stopped working on it), the actions come back, and a banner offers Retry and Force. Force finishes removing the agent even when the Runtime Broker has not confirmed that its container is gone. When the outcome is unknown, or the delete failed while finishing, starting the agent is blocked until you retry or force the delete. A failed-delete badge clears after about 15 minutes.
Runtime Brokers
Section titled “Runtime Brokers”Monitor the infrastructure nodes where your agents are executing.
- Status: See which brokers are online and their current load.
- Configuration: View broker capabilities (Docker, K8s, etc.). The WebPTY tag is on only for a Runtime Broker whose runtime can serve the web terminal: Docker, Podman, Apple container, Kubernetes and Cloud Run sandbox.
- Agent Cap: The Brokers page lists each Runtime Broker’s running-agent count against its effective
max_agents_per_brokercap (for example, “7 / 30”), with the cap’s source (Runtime Broker setting, entitlement, or hub default) in a tooltip. When an admin has turned off Runtime Broker quota enforcement, the cap is marked not enforced. - Version: The Brokers page shows each Runtime Broker’s version next to the Hub’s (“Hub: v1.3.0”). A Runtime Broker whose version differs from the Hub’s is marked with a warning icon; one that has not reported a version, or that cannot be compared because Hub instances run different versions during an upgrade, is marked unknown (never as matching). See Version mismatch below.
- Runtime Broker Settings: A Runtime Broker’s detail page has a Settings section for overrides that apply to that Runtime Broker only. Max concurrent agents can be left on the inherited default or set to a custom value (
0means unlimited); the page shows the current count, the effective limit, and where it comes from. Editing requires thequota.updatepermission. See the Runtime Broker settings API.
Version mismatch
Section titled “Version mismatch”After a Hub upgrade, the Brokers page and the Health page show which Runtime Brokers run a different Scion version from the Hub. The Hub compares versions and every page shows its result:
- Version: a Runtime Broker reports its build version when it joins or registers, and refreshes it with every heartbeat it sends with its own credentials. A co-located Runtime Broker that runs without its own credentials (for example under development authentication) records the server’s version each time the server starts, so its version stays current without the heartbeat. The version is the release tag for a tagged build and the first 8 characters of the commit otherwise, the same form the Hub reports for itself.
- Hub version: the version every live Hub instance reports. While Hub instances run different versions (a rolling upgrade), there is no single Hub version, so every Runtime Broker is shown as unknown.
- Match rule: the two versions must be identical. There is no normalisation, so
1.2.0andv1.2.0differ. - Needs attention: an online Runtime Broker whose version differs adds a
broker_version_mismatchwarning to the Health page (it does not change the overall status) and counts for the Needs attention filter of the Brokers area. An offline Runtime Broker keeps only its offline item. A Runtime Broker whose version is unknown adds nothing. - The summary’s runtime broker rows carry
version_status(match,mismatchorunknown); the Runtime Broker list (with or withoutprojectId) andGET /api/v1/runtime-brokers/:idcarryversionStatus, and both list responses carry the comparedhubVersion(see the API reference).
Known limitations:
- A Runtime Broker built from the same commit as the Hub, but one with a release tag and one without, is shown as different.
- A Runtime Broker older than this feature reports its version only when it joins, and an untagged one reports none (unknown). A Runtime Broker rolled back to such a build keeps showing the version its newer build last reported until it joins again.
- A locally modified build shows the version of the commit it was built from.
Admin Management Suite
Section titled “Admin Management Suite”Centralized views for managing the Scion infrastructure and access control (available to administrative users). Each admin page and navigation item is shown only to users whose permissions allow that page (from GET /api/v1/auth/admin-status); holding one admin permission does not reveal the rest. On the Hub Resources page (/settings), the Secrets tab is shown only to super-admins. The Environment Variables tab needs hub.env_vars.read; only super-admins can add, edit or delete Hub-level variables, and other users with that permission see a read-only list without secrets.
-
Users: View and manage user accounts and roles. Opening the delete dialog for a user queries
GET /api/v1/users/{id}/delete-blockersand lists what blocks the delete: the user’s agents that have not been deleted (with theirdeletionStatewhen a delete is under way or failed), and the user’s active delegations to existing agents not already in that list. Delete those agents before removing the user (see Deleting users). With thehub.user_delete_force_cascadeexperiment on, the dialog also offers Force delete, and a user being deleted shows asdeletingwith a Deletion status panel listing each agent’s outcome (see Force-deleting a user). -
Groups: Create and manage custom membership groups for policy-based authorization.
-
Federation: Manage the trusted external issuers whose credentials the Hub accepts (see OIDC-Based Federation). When the
federation.project_visitorsexperiment is on, the dialog for ahuboruserissuer has the switch Allow project owners to grant visitor access to users from this issuer (theallow_visitor_grantssetting, off by default). It controls whether project owners can add visitors from that issuer on a project’s Visitors tab. The Default Role field is no longer shown foruserissuers, because it has no effect; an existingdefault_rolevalue is kept and ignored. Saving an issuer keeps the settings the dialog does not show (such asaccept_user_tokens,allowed_domainsandallowed_gcp_projects); changing the issuer’s type drops them, because they apply only to the type they were set for. -
Access Boundaries: Full-featured admin suite for defining and managing monotonic permission ceilings (AccessConstraints) via a guided authoring workflow, inventory page, and dry-run preview engine.
-
Service Accounts: Manage and validate registered Google Service Accounts for use with the metadata emulation pipeline.
-
Brokers: Comprehensive broker detail pages providing a grouped view of all active agents by their respective projects.
-
Health Dashboard: The Health page (
/health, also/admin/health) shows the current state of the whole system, with optional auto-refresh. It is built from the database only, so every Hub replica shows the same page apart from the “this instance” marker. The one exception is a failed read on the serving instance itself: for example, “Runtime broker data not available” reports that the serving instance could not read the Runtime Broker table. Access requires thehub.health.readpermission. The header shows the overall status and, whenmonitoring_dashboard_urlis set, an Open monitoring dashboard link. The page has these sections:- Needs attention: shown first, at full width. It lists the summary’s ranked attention items in server order, with the server’s message for each. An item about a Runtime Broker, agent or integration links to it. An item about one Hub instance links to its row in the Hub instances table. An item about a failing schedule links to its project’s schedules page and shows a detail line: the target agent, how many runs failed, the time of the last failure and the stored last error (shortened, with the full text on hover). An item about a schedule the Hub paused itself also links to its project’s schedules page and shows the reason as fixed text, the target agent and when the schedule was last updated. A reason this page does not know is shown as “reason not recognized”.
- Hub: the whole fleet of Hub instances: the fleet status (see Fleet status below), “N of M instances healthy” (live instances only), the version (or
mixedwhen live instances run different versions), and every failing check of a live instance, labelled with its instance and linked to its row in the Hub instances table. Uptime, per-instance checks and database connection pool figures are in that table, not here. When the Hub’s own identity lacks the IAM access it needs to run the service account assignment check on a live instance, this card also shows the remedy, the instances that report it and a link to the access it needs. Each instance reports this through its row as the checksa_assign_check(degraded), so it counts in the fleet status like any other check; it is not a/healthzcheck. - Dispatch (beside the Hub card): stuck messages to agents, stuck Runtime Broker dispatches, and Runtime Broker dispatches that failed in the last hour.
- Hub instances: one row per Hub instance (process) with its label, state, version, uptime, last reported status with any failing checks listed under it, its own database connection pool (DB pool: connections in use / pool limit, or in use alone when the pool has no limit; hover for idle connections and the total number of waits for a connection since the instance started), the integrations it runs (Integrations: the total, then how many are unhealthy, degraded or unknown; hover for every count), and when it was last seen. The serving instance is marked “(this instance)” and listed first among instances in its state. The list is built from the database only, so every Hub replica shows the same list. See Hub instances in an HA deployment below.
- Runtime brokers: a compact table with each Runtime Broker’s status, runtime, Health, workspace storage, running agents and agents needing attention, version, and last heartbeat. The Health column comes from the optional self-health report each Runtime Broker sends with its heartbeat. The Version column marks a Runtime Broker whose version differs from the Hub’s, and the table header names the Hub’s version (see Version mismatch). Plugin records are not listed here.
- Integrations: chat plugins with their platform, health, connection state, version, and the Hub instances that run them (Managed by, by label), linking to the integrations page. Health is merged across every live Hub instance, so it is the same whichever replica serves the page (see Integrations across Hub instances below). Callers without the
hub.integrations.readpermission see only the counts by health, with no integration names, in this section and in the Hub instances table. Hidden when no plugins are registered. - Agents: active and total counts, counts by phase, and lists of agents in the
errorphase, crashed, or offline, each linking to the agent.
Failing schedules: the summary’s
schedulessection lists active recurring schedules whose most recent run failed, most recent failure first (at most 50, with the total). Each row has the schedule’s name, project, event type, target agent, run and error counts, the time of the last failure and its stored last error (cut to 300 characters, with an ellipsis when longer). It uses only what every schedule already records, so it shows the last run, not a run history or a count of consecutive failures. A caller sees only the schedules of projects where they holdscheduled_event.read(the schedules API checksscheduled_event.readto read one schedule andscheduled_event.listto list them). One summary reads at most 2,000 failing schedules, newest schedule first; past that,scan_limitedis true andtotalis a lower bound. Each listed schedule adds aschedulewarning to Needs attention. Failing schedules never change the overall status. When the schedules cannot be listed,schedulesis null and a “Scheduled event data not available” warning is added.Schedules paused by the Hub: the same section’s
pausedlist holds paused schedules that carry a status reason, which only the Hub sets when it pauses a schedule itself:creator_deleted(the agent or user the schedule runs under was deleted) orcron_zone_unsupported(the cron expression has aCRON_TZ=orTZ=zone prefix, which is not supported; the zone belongs in the schedule’s time zone field). A schedule a user paused has no reason and is not listed. Each row has the schedule’s name, project, event type, target agent, itsreasonandupdated_at, the time of its last update.reasonis one of the two values above, orotherfor a stored reason this Hub does not know; the stored text itself is not returned. Rows are most recently updated first, at most 50, withpaused_total. The same per-projectscheduled_event.readrule and the same 2,000-row scan limit apply, separately from the failing list, withpaused_truncatedandpaused_scan_limited. Each listed schedule adds aschedulewarning to Needs attention, with a fixed sentence for its reason. Paused schedules never change the overall status. When the paused schedules cannot be listed,pausedis null,paused_unavailableis true and a “Hub-paused scheduled event data not available” warning is added; the failing list is shown. When the failing schedules cannot be listed,schedulesis null, as above.One policy sets the overall status of the summary. It is the worst of: the fleet status of the Hub instances (below);
degradedwhen a Runtime Broker is not online, reports itselfdegradedorunhealthy(including an online Runtime Broker whose control channel is not connected, so it cannot receive commands:broker_command_path), or reports an unhealthy NFS workspace share;degradedwhen dispatch has stuck messages or stuck Runtime Broker dispatches;degradedwhen an integration reports unhealthy; anddegradedwhen at least 5% of agents are inerrororcrashed. (A service account assignment check that cannot run is the instance’ssa_assign_check, counted in the fleet status.) A section that could not be read adds a warning but does not change the status. The same policy producesattention, a ranked “Needs attention” list in theGET /api/v1/admin/health/summaryresponse. Each entry has aseverity(criticalorwarning), akind(hub_check,hub_instance,broker_offline,broker_degraded,broker_command_path,broker_nfs,broker_host_identity,broker_version_mismatch,integration,dispatch,agentsorschedule), asubject, and a fixed, server-writtenmessage.Fleet status
Section titled “Fleet status”The
hubsection of the summary describes every Hub instance together, from the rows in thehub_instancestable (see Hub instances in an HA deployment). The serving instance runs no check of its own for the summary: no database ping, no plugin call and no connection pool read. Its own checks reach the page through its row, like every other instance’s. Only live instances count. Withnlive instances, of whichureportunhealthy:- no live instance (
n= 0):unhealthy, with the critical item “No hub instance is reporting”; - more than half unhealthy (2
u>n):unhealthy; - any live instance
degradedorunhealthy:degraded; - otherwise
healthy.
So one unhealthy instance out of three is
degraded(a warning), two out of three isunhealthy, and a single-instance Hub (including SQLite) that is unhealthy isunhealthy. When the fleet is not healthy, the attention list starts with “N of M hub instances healthy”. Each failing check of each live instance adds onehub_checkitem about that instance (“Hub check X is not healthy on instance L”). These items are critical only when the fleet status isunhealthy, otherwise warnings; critical checks (database,workspace_storage) are listed first.- A stale instance is outside the count and does not change the status. For 15 minutes after its last write it adds the warning “Hub instance L stopped reporting”.
- A stopped instance (clean shutdown) adds nothing.
- If the serving instance cannot read the
hub_instancestable, the fleet status isunknown, the warning “Hub instance data not available” is added, and the overall status does not change. - If the serving instance cannot read the database at all,
GET /api/v1/admin/health/summaryreturns HTTP 503 with a fixed message and no partial data, and the page shows “Health data not available (database unreachable from this hub instance)”. Such an instance cannot write its own row either, so the other replicas show it as stale.
The summary’s
hubfields arestatus(the fleet status),version,instance_id(the serving instance),connected_brokers,active_agents,projects,instances(live instances counted by status:live,healthy,degraded,unhealthy; null when the table could not be read) andunhealthy_checks(each withinstance_id,instance_label,nameandvalue). Uptime is per instance and is computed by the page from each instance’s start time./healthzand/readyzare unchanged: they check the process that answers them.The Health page does not show stalled agents or stall settings: stalls are routine and are not a health signal, so the summary carries no stall data. To change the stall threshold or turn on auto-suspend of stalled agents, use Admin > Server Config (
server.hub.stalled_threshold,server.hub.auto_suspend_stalled).For rates and per-replica history, see the Hub monitoring dashboard.
Hub instances in an HA deployment
Section titled “Hub instances in an HA deployment”Every Hub process writes a small row about itself to the
hub_instancestable: once at start, then every 15 seconds (with ±10% jitter). The row holds the instance’s label (the pod name; on Cloud Run, the revision and the first 8 characters of the instance ID; otherwise the host name), its version, its start time, its overall status, its checks reduced to fixed values (healthy,degraded,unhealthy,available,unavailableorunknown; a check with any other value is stored asunknown, and a check whose name is not 1-64 characters of lower-case letters, digits and_is not stored), and its database connection pool (connections in use, idle, the pool limit, and the total waits for a connection). The in-use, idle and wait figures are refreshed on every write, so they are at most one write interval old. The instance’s label, version, status, checks and pool figures are kept within 4 KiB together (the instance ID and timestamps are not counted). The Health page shows each instance’s own pool from its row; the instance serving the page does not read its own pool separately. A restart is a new process, so it gets a new row; the label shows that two rows belong to the same pod. On a single-node SQLite Hub the table shows the one running instance and that instance’s earlier restarts.The summary computes each instance’s state when it is read:
- live: the instance wrote its row within the last 45 seconds (three write intervals).
- stale: the instance has not written its row for more than 45 seconds. The process stopped without a clean shutdown (for example, it was killed or its node was lost), or it is running but cannot write to the database. A stale instance’s status and version are its last report, shown greyed.
- stopped: the instance shut down cleanly. On a graceful shutdown the Hub stops its writer and records the stop time in its row (within a 2-second budget), so the instance shows as stopped at once, greyed, and never as stale. If the stop cannot be recorded in time, the instance shows as stale instead.
Instances whose last write (or stop) is within the last hour are listed, up to 50. Older rows stay in the table until they are pruned: once an hour, one Hub replica deletes the rows whose last write (or stop) is more than 24 hours old. If a running instance’s row is ever deleted, the instance writes it again on its next write, with a new start time. During a rolling upgrade, a Hub replica that predates this table does not appear in the list, and when such a replica serves the page, the Hub instances table is hidden. “Hub instance data not available” means the serving instance could not read the table.
Integrations across Hub instances
Section titled “Integrations across Hub instances”Each Hub instance also writes the health of the chat plugins it runs to its row, on the same 15-second schedule: at most 32 plugins, each with its name, health (
healthy,degraded,unhealthyorunknown), whether it is connected, and its version. When the plugin supervisor detects a lost RPC session, the instance reportsconnected: falsewith healthdegraded(State: "restarting", attempts 1–4) orunhealthy(State: "failing", after 5 consecutive failed attempts); adegradedintegration adds the warning"Integration <name> is degraded"to Needs attention, and anunhealthyintegration adds"Integration <name> is unhealthy"and degrades the overall summary status (see Message-Bus Plugin Supervision). The plugin’s own health message and details are never stored. A plugin that does not answer within 2 seconds is stored asunknown. These health queries run only in this background write, so opening more Health pages adds no plugin calls; the summary itself queries no plugin.The summary merges the reports of the live instances for each plugin:
- Health is the worst value any live instance reports.
unknownnever hides a known value, and is shown only when no live instance reports a known one. - Connected is
yesonly when every instance that reported a known health says connected. An instance whose report isunknown(for example, its plugin did not answer in time) does not count, as for health. When no instance reports a known health, Connected isyesonly when every reporting instance says connected. - Version comes from the most recent report.
- Managed by lists the reporting instances. The
reported_atfield in the API response is the oldest report used.
A stale or stopped instance’s report is never used. A plugin that has a Hub record but that no live instance reports shows as
unknownwith the reason “not run by any running hub instance”. If the serving instance cannot read the Hub instance table, plugins with a Hub record showunknownwith the reason “hub instance data not available”. A change in a plugin’s health appears on the page after the next write of the instance that runs it (within 15 seconds) plus the next page refresh.On Cloud Run, keep CPU always allocated (
--no-cpu-throttling, which the shipped deploy script sets) so each instance keeps writing its row between requests. With CPU throttling, an idle instance stops writing and shows as stale. -
Metrics Dashboard: View infrastructure health and agent telemetry metrics. Access requires the
hub.metrics.readpermission scope. For details on the metrics collected, see Metrics & OpenTelemetry. Daily charts group days by calendar day in your display zone, and their headings name that zone (see Metrics dashboard day buckets). -
Server Configuration Editor: A full-featured settings editor at
/admin/server-config. The General settings tab is organized into dedicated cards (General, Agent Defaults with sub-tabs, and Project Default Settings) withDefaultModel,DefaultThinkingLevel,DefaultHarnessAuth, and the Telemetry toggle under Agent Defaults, and the Hub Server tab groups the Message Broker configuration and the editable agent start claim timing fields (start_claim_lease_ttl,start_max_duration,start_unconfirmed_hold,start_create_unconfirmed_hold; see Admin Settings). -
Maintenance Mode: Toggle maintenance mode and edit the maintenance banner message on
/admin/maintenancefor the Hub and Web servers to facilitate safe infrastructure updates.
Authentication
Section titled “Authentication”The dashboard supports several authentication methods:
- OAuth (Google/GitHub): For standard user access.
- Development Auto-login: For local development.
See the Authentication Guide for setup instructions.
API Proxying
Section titled “API Proxying”The Go server handles API proxying, token injection, and session management so the browser never handles raw API keys or long-lived tokens directly.