agent-swarm.devagent-swarm.dev
UI

Overview

The Agent Swarm dashboard — what it is, the hosted instance at app.agent-swarm.dev, and how to self-host it

The Agent Swarm dashboard is the web UI for operating a swarm: watch agents, tasks, and inter-agent chat in real time, review approvals, manage workflows, scripts, schedules, skills, and memory, and administer settings — secrets, API keys, integrations, and swarm configuration.

Apps

The Apps surface hosts schema-backed applications created by agents. Use the Apps guide to decide when to build one, understand the definition primitives, and start from a complete example. See the Apps API reference for lifecycle endpoints.

Appearance

Settings → Appearance lets each browser choose light, dark, or system mode and select a built-in visual preset. The preference stays local to the browser connection. Apps may request their own canvas theme, while viewers can override it without changing the app definition.

Usage attribution

The Usage page can filter costs by canonical requester and shows Cost by User alongside the overall totals. Spend tied to a user is attributed to that identity; background work without a requester is grouped as Unattributed (autonomous) so operator-driven and autonomous spend remain distinguishable.

When a dashboard tab authenticates with a user-bound aswt_ token, the dashboard resolves the principal from GET /api/whoami and locks the tab to that user. Identity switching and local identity overrides stay hidden so requester and audit attribution cannot diverge from the bearer token. Operator-key sessions keep the existing user picker.

Subscriptions vs API

The Usage page compares each subscription credential (Claude OAuth, Codex OAuth) with what its sessions would cost at API prices. The plan cost is the monthly list price, prorated per day from the credential's first session in the window. Saved is the API value minus that plan cost.

The plan of each credential shows on the Usage page and in the Plan column of Settings → Provider keys:

  • Detected: a Codex token names its ChatGPT plan, and the worker reports it. The token says pro for both Pro tiers, so it maps to Pro 20x.
  • Estimated: a Claude token cannot name its plan. The API estimates it from the 7-day rate-limit window: the spend at API prices divided by the share of the window used. It needs at least 25% of the week used, and usage of the same account outside the swarm can make it read one tier low.
  • Set by you: pick a plan on either page. Your choice wins over a detected or estimated plan. Use detected plan removes it.

Credentials with no plan are left out of the savings total.

Task list filters

The Tasks page keeps its filters in the URL so views can be bookmarked and shared. In addition to status, agent, schedule, heartbeat visibility, and text search, the Requested by facet can show work attributed to a specific user, Me for the current dashboard identity, or Unattributed for tasks without a canonical requester. The requester filter is single-select and is never enabled by default.

File attachments

Paste files or screenshots into the session composer, drop files onto it, or use its paperclip button to attach them. The composer lists selected files before sending; remove a file with its × button.

Each file can be up to 50 MB. The composer accepts PDF, text, Markdown, CSV, JSON, Word, Excel, PowerPoint, PNG, JPEG, GIF, WebP, and ZIP files. Unsupported types and oversized files show an error before upload; valid files in the same batch remain attachable. Add a message before sending.

Press Enter to send, Shift+Enter to insert a newline, or Cmd/Ctrl+Enter to send. Attachment links in task prompts open the file viewer.

Tool result images

Expand a tool result in a task log to see supported inline images alongside its text. Previews load as they approach the viewport; click a preview to open the image at full size. Supported formats are PNG, JPEG, GIF, WebP, and AVIF.

If an image cannot render, use Copy result or Show full output to inspect the original result.

Notifications

The header bell opens dashboard announcements. Read, dismissed, and done states are saved for the current user and persist across reloads and devices. The Slack Connect card lets you request an invitation by email, dismiss the announcement, or mark that you already have a channel.

Notification interactions send event details to the configured feedback_endpoint (Desplega's feedback service by default). Your email address is included only when you submit an invitation request.

Hosted dashboard

We host the latest build at app.agent-swarm.dev.

It is a browser-storage-only client: operator connections you enter (API URL + API key) are kept in browser local storage, and requests go straight from your browser to your swarm's API. Embedded ?apiUrl=...&apiKey=aswt_... user-token connections are tab-local in session storage, so separate tabs cannot overwrite one another's identity. Nothing is proxied or persisted on our side, and the same hosted dashboard can connect to any swarm — a local dev server, your self-hosted deployment, or a cloud swarm. Operator-key sessions can save multiple connections and switch between them from the sidebar.

Connecting

Enter your API URL and key in the in-app connection panel, or open the dashboard with ?apiUrl=...&apiKey=... query parameters to pre-fill a connection (the onboard wizard prints exactly such a URL). Your swarm's API must be reachable from your browser.

Connect an outside app (ChatGPT, Claude, Codex, Cursor)

The agent-swarm.dev connector lets ChatGPT, Claude, Codex, and Cursor send and read tasks on your swarm as you. The connector gets a user token for you. You never copy or paste a token.

  1. On the connector page, choose your swarm's dashboard (by default the hosted app.agent-swarm.dev) and click Continue to your swarm. A new tab opens the dashboard's /connect page.
  2. Pick the connection to use if the dashboard has more than one. With no connection yet, add one first. The dashboard then returns you to /connect.
  3. Pick yourself from the list of people. A connection that uses your own aswt_ token skips this step. The dashboard remembers your last choice for each connection.
  4. Confirm. The dashboard asks the swarm for a single-use code that expires in 10 minutes, then sends the tab back to the connector. The connector trades the code for a token and shows "All set".

The token can do what you can do on the swarm, nothing more. The swarm's public API origin (PUBLIC_MCP_BASE_URL) must use https://. A loopback http://localhost origin also passes, for local development stacks only. The Connect to ChatGPT button on a person's Tokens tab starts the same flow.

To mint a token by hand instead, open People, select yourself, and click Mint token on the Tokens tab. Copy the token when it is shown: it is shown only once. Revoke it from the same tab.

Self-hosting

The dashboard is a static single-page app (Vite + React) in apps/ui/ — there is no server component, so it can be served from any static host:

cd apps/ui
bun install
bun run build   # outputs apps/ui/dist/

Deploy the dist/ directory to your static host of choice (Vercel, Netlify, nginx, S3 + CDN, ...).

Or run the published image. It serves the same build with nginx on port 8080 as a non-root user, answers /healthz for probes, and needs only /tmp writable:

docker run --rm --read-only --tmpfs /tmp --cap-drop ALL --security-opt no-new-privileges -p 8080:8080 ghcr.io/desplega-ai/agent-swarm-ui:<version>

Use the same <version> as your API image. The image takes no runtime configuration: VITE_* values are compiled in at build time, so enter the API URL and key in the connection panel.

Keep Pages off the dashboard origin

The dashboard keeps connection keys in browser storage, and Pages (/p/*, /@swarm/*) run agent-authored scripts. Never serve Pages from the dashboard's origin, or a page script can read those keys.

Two layouts work:

  • Separate origins (simplest): dashboard on app.example.com, API on api.example.com. On the API, set CORS_ALLOWED_ORIGINS=https://app.example.com so the dashboard can call it, APP_URL=https://app.example.com so the Pages viewer may frame pages and swarm links open your dashboard, and PUBLIC_MCP_BASE_URL=https://api.example.com.
  • Dashboard and JSON API on one origin, for example behind an SSO proxy that should cover both with one session. On the dashboard host, route the prefix /api/ (including the /api/realtime WebSocket upgrade) and the exact paths /health and /status to the API, and everything else to the dashboard. Keep /p/, /@swarm/, /mcp, /mcp-user and /docs on the API's own host, and keep PUBLIC_MCP_BASE_URL pointing there, because page links, OAuth redirects and MCP clients use it. The dashboard's Pages viewer loads pages from the connection URL, so it does not work in this layout; open pages through their links on the API host instead.

To embed a public page in another site, such as a chart in a blog post, set PAGES_FRAME_ANCESTORS on the API to the embedding origins, comma or space separated (for example https://www.example.com https://example.com). Entries use CSP host-source syntax; invalid entries are dropped with a warning. The list applies only to pages with access mode public; authed and password pages stay embeddable by the APP_URL origins alone. It does not change APP_URL or link resolution.

The image only lets its own origin frame the dashboard (frame-ancestors 'self'), so embedding the dashboard in another site is not supported. The Helm chart and Compose examples do not deploy the dashboard image yet.

For a custom dashboard origin, set CORS_ALLOWED_ORIGINS on the API. A custom list replaces the built-in hosted/dev defaults, so include every trusted dashboard origin you use. See the CORS deployment guide.

Self-hosted builds omit the Plausible page-view script. The hosted dashboard sets the build-time flag VITE_PLAUSIBLE_ANALYTICS=1, which injects a Plausible snippet; leave it unset to omit that script from your build. VITE_PLAUSIBLE_SCRIPT_ID selects the Plausible site for a second deployment such as the public demo. Notification feedback described above uses a separate endpoint.

For local development:

cd apps/ui && bun install && bun run dev

This serves the dashboard at http://localhost:5274 and proxies /api/* to a local API server on http://localhost:3013.

On this page