diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 7a329b98..f8eef164 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -137,8 +137,17 @@ export default defineConfig({ ] }, { - text: 'Teams', - items: [{ text: 'Argus Hub', link: '/argus-hub' }] + text: 'Using Argus Hub', + items: [ + { text: 'Overview', link: '/argus-hub' }, + { text: 'Configuration', link: '/argus-hub/configuration' }, + { text: 'Activity', link: '/argus-hub/activity' }, + { text: 'Tasks', link: '/argus-hub/tasks' }, + { text: 'Tools', link: '/argus-hub/tools' }, + { text: 'Team', link: '/argus-hub/team' }, + { text: 'MCP', link: '/argus-hub/mcp' }, + { text: 'Export', link: '/argus-hub/export' } + ] }, { text: 'Reference', diff --git a/docs/argus-hub.md b/docs/argus-hub.md index 68c05d7d..7b33d3fa 100644 --- a/docs/argus-hub.md +++ b/docs/argus-hub.md @@ -2,48 +2,30 @@ description: Run an Argus Hub so a team can pool its usage into one org-wide dashboard. Setup, connecting people and what each person sends. --- -# Argus Hub +# Argus Hub: Overview -Argus Hub is a self-hosted server that collects usage data from multiple Argus clients and -presents an org-wide [dashboard](/terminology#dashboard). It is the on-premises alternative to -the hosted `argus-dash` backend. +[Argus Hub](https://github.com/Agent-Deployment-Co/argus-hub) is a self-hosted server that pools session, task, and usage data +from a team's [Argus](https://github.com/Agent-Deployment-Co/argus) clients into one org-wide dashboard. Argus Hub runs +entirely on your own network. -Each person points Argus at the Hub and uses the normal [sync](/terminology#sync) command. Hub +Each person points their Argus client at an Argus Hub instance and uses the normal [sync](/terminology#sync) command. Argus Hub receives the usage snapshot at `POST /api/sync`, combines it in one database and tags it by user. Nothing is forwarded anywhere else. The raw prompt and response text stays on each person's machine, as do their BYO model API keys. -## Set up a Hub - -Hub requires Node.js 20.17 or later, or Bun 1.0 or later. Start it with: - -```bash -npx @agentdeploymentco/argus-hub serve --port 4343 -``` - -The first startup creates `data/hub.db`, generates an API key and generates an admin password. -Both values are printed once, so copy them to a secure location before closing the terminal. - -The **API key** authenticates uploads from Argus clients. The **admin password** protects the -dashboard at `http://localhost:4343/login` and the Hub's read-only MCP endpoint. Set -`ADMIN_PASSWORD` before starting Hub to keep the same dashboard password across restarts. If you -do not set it, Hub generates a new password each time it starts. - -::: warning Keep the credentials private -The API key allows clients to upload data. The admin password allows access to the organization's -pooled usage data. Do not put either value in source control or share them in a public channel. -::: +Setting an Argus Hub up, including generating its secret key, API key and admin password, is covered in +[Configuration](/argus-hub/configuration#quick-start). ## Connect Argus clients -In the desktop app, open **Settings** and enter the Hub URL and API key. The app uploads on a +In the desktop app, open **Settings** and enter the Argus Hub URL and API key. The app uploads on a schedule after the connection is configured. The app stores the key securely and shows a masked value after you save it.
-![Argus Hub settings with a Hub URL and masked Hub key.](./images/screenshots/argus-hub-settings@1920x1080@2.webp) +![Argus Hub settings with an Argus Hub URL and masked Argus Hub key.](../images/screenshots/argus-hub-settings@1920x1080@2.webp)
@@ -62,8 +44,8 @@ export ARGUS_HUB_URL=https://hub.internal:4343 export ARGUS_HUB_KEY=hub-example-key ``` -With a Hub configured, `argus sync` uploads to that Hub instead of the hosted service. No -`argus login` or OAuth flow is needed. Hub identifies a person from the client's latest identity +With an Argus Hub configured, `argus sync` uploads to that Argus Hub instead of the hosted service. No +`argus login` or OAuth flow is needed. Argus Hub identifies a person from the client's latest identity signal, using the Claude or Codex OAuth email when available and falling back to the local Git name. Repeat clients from the same person are grouped together. @@ -83,214 +65,68 @@ To upload one snapshot immediately: npx @agentdeploymentco/argus sync ``` -## Configure the Hub - -Hub reads `hub.json` from the current directory, then environment variables, then command-line -flags. A later source takes precedence over an earlier one. - -| CLI flag | Environment variable | `hub.json` key | Default | What it controls | -|---|---|---|---|---| -| `--port` | `HUB_PORT` | `port` | `4343` | Port Hub listens on | -| `--data-dir` | `HUB_DATA_DIR` | `dataDir` | `./data` | Folder containing `hub.db` | -| None | `ADMIN_PASSWORD` | None | Random | Dashboard and MCP password | -| None | `HUB_INSECURE_COOKIE_HOSTS` | None | None | Hostnames allowed to use a non-`Secure` cookie for private plain-HTTP deployments | - -For example: - -```json -{ - "port": 4343, - "dataDir": "/var/lib/argus-hub" -} -``` - -There is no `HUB_KEY` setting. Hub stores API keys in `hub.db`. If the database has no API keys -when Hub starts, it generates a key for the Default organization and prints it to the terminal. - -Only use `HUB_INSECURE_COOKIE_HOSTS` for hostnames reachable through a private network. Never list -a hostname that is reachable from the public internet. - -To rotate a key, delete the old key's row from the Hub database, then restart Hub. Hub only -generates a new key when the `api_keys` table is empty, so disabling a key with `is_enabled = 0` -does not trigger this: rotation requires removing the row outright, not just disabling it. A -disabled key is rejected before Hub reads the upload body. - -## Run Hub continuously - -Hub runs in the foreground, so a service manager can restart it and collect its logs. The Argus -Hub repository contains the Dockerfile and the complete service examples. The common deployment -shapes are below. - -### Linux with systemd - -Save this as `/etc/systemd/system/argus-hub.service`: - -```ini -[Unit] -Description=Argus Hub -After=network.target - -[Service] -Type=simple -ExecStart=npx @agentdeploymentco/argus-hub serve --port 4343 -WorkingDirectory=/srv/argus-hub -Environment=HUB_DATA_DIR=/srv/argus-hub/data -Restart=on-failure -RestartSec=5 - -[Install] -WantedBy=multi-user.target -``` - -Enable and follow it with: - -```bash -sudo systemctl enable --now argus-hub -sudo journalctl -fu argus-hub -``` - -Set `ADMIN_PASSWORD` in the service environment so a restart does not change the dashboard -password. - -### Docker - -Build the image and persist `/data`, which contains `hub.db`: - -```bash -docker build -t argus-hub . -docker run -d \ - --name argus-hub \ - -p 4343:4343 \ - -v argus-hub-data:/data \ - argus-hub -``` - -Pass `ADMIN_PASSWORD` with `-e` or an env file. The image exposes `GET /healthz`, which returns -`200 ok` without authentication for container health checks and Kubernetes liveness probes. - -For Docker Compose, persist the same data volume: - -```yaml -services: - argus-hub: - build: . - restart: unless-stopped - ports: - - "4343:4343" - volumes: - - argus-hub-data:/data - -volumes: - argus-hub-data: -``` - -### macOS with launchd - -Create a LaunchAgent at `~/Library/LaunchAgents/co.agentdeployment.argus-hub.plist`, set its -working directory and `HUB_DATA_DIR`, then load it: - -```bash -launchctl load ~/Library/LaunchAgents/co.agentdeployment.argus-hub.plist -``` - -Use the service definition in the [Argus Hub repository](https://github.com/Agent-Deployment-Co/argus-hub) -for the complete plist, including log paths and restart behavior. +Argus Hub's port, data directory, secret key and admin password, plus how to keep it running and +private, are covered in [Configuration](/argus-hub/configuration). ## Use the dashboard -Open the Hub URL in a browser. The dashboard groups organization-wide usage into these views: +Open the Argus Hub URL in a browser. The dashboard groups organization-wide usage into five views, +each covered in depth under **Using Argus Hub** in the nav:
-![Argus Hub activity dashboard showing organization-wide usage, tasks, token usage and cost.](./images/screenshots/argus-hub-dashboard@1920x1080@2.webp) +![The Argus Hub Activity view: headline totals, the daily activity chart and cost by model.](../images/screenshots/argus-hub-activity@1920x1080@2.webp)
| View | What you can see | |---|---| -| Activity | Usage and cost for the whole organization or one person | -| Tasks | Extracted tasks, including outcomes, frustration and interrupted rates, and top failure signals | -| Tools | Tool and MCP server usage across the organization or for one person | -| Team | Per-user sessions, tokens, estimated cost and last-sync time | -| Export | Download the full dataset as a Snowflake-ready zip | - -The user/group picker appears after at least one client syncs. Leave it on **All** for an -organization-wide view, or choose one person or group to scope Activity, Tasks and Tools. The -Team table can be sorted by any column, and clicking a row opens that person's own activity view. - -## Query Hub from an agent - -Hub provides a read-only [MCP](https://modelcontextprotocol.io) endpoint at `POST /mcp`. It uses -the stateless Streamable HTTP transport, so an MCP client sends JSON-RPC requests directly over -HTTPS without a subprocess or a session. - -| Tool | What it answers | -|---|---| -| `query_activity` | Usage and cost over a time window, including the previous window for comparison | -| `query_tasks` | A paged, filterable list of extracted tasks | -| `query_task_quality` | Success, frustration and interruption rates, outcomes over time and failure signals | -| `query_tool_usage` | Which tools and MCP servers people use | -| `query_users` | User IDs, display names, emails, last-sync time, sessions, tokens and cost | - -The first four query tools accept `since`, `until`, `project`, `source`, `user` and `group` -filters. The `source` filter accepts `claude`, `codex`, `gemini` or `cowork`. The `group` filter -takes a groupId, or `__none__` for users with no group assigned. `query_users` accepts an -optional `group` filter (matching a groupId or groupName) and can help you find a `userId` before -scoping another query. - -Authenticate with the Hub admin password: - -```text -Authorization: Bearer -``` - -For Claude Code, add the endpoint with: - -```bash -claude mcp add --transport http argus-hub https://hub.internal:4343/mcp \ - --header "Authorization: Bearer " -``` - -Treat the admin password as a shared read credential after you give it to an agent. Anyone who -holds it can query the organization's activity, tasks and tool usage. If Hub runs without -`ADMIN_PASSWORD`, the MCP route is open, so set a password for any shared or network-accessible -deployment. +| [Activity](/argus-hub/activity) | Usage and cost for the whole organization, trended against the prior window | +| [Tasks](/argus-hub/tasks) | Extracted tasks, outcomes, frustration and friction, top failure signals | +| [Tools](/argus-hub/tools) | Tool, skill and MCP server usage across the organization | +| [Team](/argus-hub/team) | Per-user sessions, tokens, estimated cost, last-sync time and groups | +| Labels | Argus Hub-wide task labels: create, apply and remove them (see [Argus Hub labels](/argus-hub/tasks#argus-hub-labels)) | +| [Export](/argus-hub/export) | Download the full dataset, or load it into Snowflake | -## Export Hub data +The group picker appears after at least one client syncs and someone has been put in a group. +Leave it on **All** for an organization-wide view, or choose a group to scope Activity, Tasks and +Tools. The Team table lists everyone by group, and clicking a row opens that person's own +activity view. -`argus-hub export snowflake` creates a consistent Snowflake-ready snapshot of the live Hub -database. Add `--load` to upload it with the built-in connector, or use the generated JSONL files -and `load.sql` for a manual or scheduled load. +**Settings** holds the task LLM provider Argus Hub will use for organization-level task labeling. +Nothing in Argus Hub calls this provider yet beyond a **Test connection** check on the Settings page +itself; it's reserved for a future feature. Any API key you save there is encrypted in `hub.db` +with `HUB_SECRET_KEY`. -See [Export Argus Hub data to Snowflake](https://github.com/Agent-Deployment-Co/argus-hub/blob/main/docs/snowflake.md) -for data coverage, setup, authentication, scheduling and limitations. +## MCP -## Keep a Hub private +Argus Hub also provides a read-only-by-default [MCP](https://modelcontextprotocol.io) endpoint at +`POST /mcp`, so an agent can query activity, tasks and tool usage directly. See +[MCP](/argus-hub/mcp) for the full tool list, filters, authentication and a worked +example. -Place Hub behind a VPN or a reverse proxy with TLS. Do not expose it directly to the internet. -The Hub database contains the session data of every syncing user, so restrict filesystem access -and include it in backups. Hub sets new database files to mode `0600`. +## Export Argus Hub data -The client sends resolved usage rows, session summaries, tasks, interaction metadata, tool and MCP -invocations and labels. It does not send retained prompt and response text or BYO API keys. The -client's local `argus.db` file never leaves the machine as a file. +`argus-hub export snowflake` creates a consistent Snowflake-ready snapshot of the live Argus Hub +database, from the dashboard or the command line. See [Export](/argus-hub/export) for both paths and +the Snowflake load flow. ## Data flow ```text -Argus clients --POST /api/sync--> Hub ingest --> hub.db +Argus clients --POST /api/sync--> Argus Hub ingest --> hub.db | +--> dashboard and MCP queries ``` -Hub supports multiple organizations. Each API key belongs to one organization. Run separate Hub +Argus Hub supports multiple organizations. Each API key belongs to one organization. Run separate Argus Hub instances when unrelated tenants need strict isolation. ## License Argus Hub is licensed under the [Functional Source License 1.1](https://github.com/Agent-Deployment-Co/argus-hub/blob/main/LICENSE), which converts to MIT two years after each release. You can use, modify, distribute and build on -Hub for personal, internal or commercial purposes. For the first two years, you cannot run a paid +Argus Hub for personal, internal or commercial purposes. For the first two years, you cannot run a paid hosted service whose primary offering is Argus Hub as a service. The restriction does not cover a larger product where agent-usage reporting is a small feature. diff --git a/docs/argus-hub/activity.md b/docs/argus-hub/activity.md new file mode 100644 index 00000000..2c94ef9d --- /dev/null +++ b/docs/argus-hub/activity.md @@ -0,0 +1,90 @@ +--- +description: What the Argus Hub Activity view shows, org-wide totals, trends against the prior window, and rankings by person and by source. +--- + +# Argus Hub: Activity + +Activity is Argus Hub's home view: how much agent work the organization did in the +window you're looking at, and how that work is spread across people and +[sources](/terminology#source). It opens with headline totals, then breaks +those totals down over time, by model, by person and by source. + +
+ +![The Argus Hub Activity view: headline totals with trends against the prior window, the daily activity chart and cost by model.](../images/screenshots/argus-hub-activity@1920x1080@2.webp) + +
+ +## Filters + +A filter bar sits above the view: + +- **Date** narrows the window, with quick presets or your own From and To + dates. Argus Hub defaults to the last 30 days. +- **Sources** narrows to one agent. +- **Group** narrows to one [group](/argus-hub/team#groups) of people, or to + **Ungrouped** for people with no group assigned. It only appears once at + least one person has been put in a group. + +Activity has no per-person filter of its own. To see one person's usage, +open their row in the [Team](/argus-hub/team) table, which takes you to their own +activity page (see [Users](#users) below). A Reset button clears the +filters back to the 30-day, all-sources default. + +## Headline totals + +Four stat cards open the view: **Active sessions**, **Tasks** (with the +success rate among tasks that reached a clear outcome), **Token usage** +(with estimated cost), and **Active users**. Every card carries a trend +line comparing the current window to the window immediately before it, of +the same length, something like `+12% vs. prior window`, a flat reading, +or nothing at all if there's no prior window to compare against yet. + +## Activity over time + +A daily bar chart, with a toggle to switch what it plots: Sessions, Tasks, +Tokens, Cost or Active users. Every day in the window gets a bar, including +days with no activity, so a quiet stretch reads as a gap rather than +disappearing from the axis. + +## Cost by model + +A horizontal bar chart of the window's spend, broken down by +[model](/terminology#model). Each bar's tooltip shows the dollar amount, +its share of total spend and the tokens behind it. Models Argus can't price +are excluded here and called out in a note below the headline totals +instead. + +## Users + +Per-user rankings stay hidden until the organization has at least three +people syncing, so a small team never gets singled out by name. Once +there's enough of a cohort, this section shows a **Most active** and +**Least active** top-5, each row tagged by how recently that person has +synced: + +- **Active**: syncing and scoring normally. +- **Idle**: still syncing, but scoring low this window. +- **Silent**: hasn't synced in 3 or more days. + +Rank is an **activity score** from 0 to 100, blending active days, +sessions and tokens, each measured against the busiest person in the +window and weighted equally. Every raw number behind the score sits in the +full table underneath, sorted by any column, so the ranking is never a +black box. Click a name, in the mini-lists or the table, to open that +person's own activity page: the same view a single Argus client shows for +their own usage (see [Sessions](/sessions), [Metric Views](/metric-views)), +scoped to them. + +
+ +![One person's activity page, reached from the Team table, the same Activity view scoped to their usage alone.](../images/screenshots/argus-hub-user-activity@1920x1080@2.webp) + +
+ +## Sources + +A table ranking each agent by sessions, distinct users, tokens, cost and +task success rate, sorted by sessions descending. A note calls out the +least-adopted source in the window, a candidate for more onboarding or for +retiring if it isn't earning its keep. diff --git a/docs/argus-hub/configuration.md b/docs/argus-hub/configuration.md new file mode 100644 index 00000000..40433ed9 --- /dev/null +++ b/docs/argus-hub/configuration.md @@ -0,0 +1,171 @@ +--- +description: Configure Argus Hub's port, data directory and secret key, keep it running with systemd, Docker or launchd, and keep a deployment private. +--- + +# Argus Hub: Configuration + +Argus Hub starts with one command and a generated secret key. From there, this page covers setting +its port and data directory, keeping it running with a service manager, and keeping a deployment +private on your network. + +## Quick Start + +Argus Hub requires Node.js 20.17 or later, or Bun 1.0 or later. + +Generate a secret key and start it with: + +```bash +export HUB_SECRET_KEY="$(openssl rand -base64 32)" # save this value +npx @agentdeploymentco/argus-hub serve --port 4343 +``` + +The first startup creates `data/hub.db`, generates an API key and generates an admin password. +Argus Hub prints both values once, so copy them to a secure location before closing the terminal. + +The **API key** authenticates uploads from Argus clients. The **admin password** protects the +dashboard at `http://localhost:4343/login` and Argus Hub's read-only MCP endpoint. Set +`ADMIN_PASSWORD` before starting Argus Hub to keep the same dashboard password across restarts. If you +do not set it, Argus Hub generates a new password each time it starts. + +`HUB_SECRET_KEY` is optional, but without it Argus Hub starts with a warning and disables API-key-based +task LLM providers in **Settings**, since it has nothing to encrypt those keys with in `hub.db`. +Set it once, keep it stable across restarts, and back it up separately from `hub.db`: losing it +makes any provider keys already stored there unreadable. + +::: warning Keep the credentials private +The API key allows clients to upload data. The admin password allows access to the organization's +pooled usage data. Do not put either value in source control or share them in a public channel. +::: + +## Configure Argus Hub + +Argus Hub reads `hub.json` from the current directory, then environment variables, then command-line +flags. A later source takes precedence over an earlier one. + +| CLI flag | Environment variable | `hub.json` key | Default | What it controls | +|---|---|---|---|---| +| `--port` | `HUB_PORT` | `port` | `4343` | Port Argus Hub listens on | +| `--data-dir` | `HUB_DATA_DIR` | `dataDir` | `./data` | Folder containing `hub.db` | +| None | `HUB_SECRET_KEY` | None | None | Base64 encoding of 32 random bytes; encrypts task LLM provider keys stored in `hub.db`. Without it, those providers stay disabled | +| None | `ADMIN_PASSWORD` | None | Random | Dashboard and MCP password | +| None | `HUB_INSECURE_COOKIE_HOSTS` | None | None | Hostnames allowed to use a non-`Secure` cookie for private plain-HTTP deployments | + +For example: + +```json +{ + "port": 4343, + "dataDir": "/var/lib/argus-hub" +} +``` + +There is no `HUB_KEY` setting. Argus Hub stores API keys in `hub.db`. If the database has no API keys +when Argus Hub starts, it generates a key for the Default organization and prints it to the terminal. + +Only use `HUB_INSECURE_COOKIE_HOSTS` for hostnames reachable through a private network. Never list +a hostname that is reachable from the public internet. + +To rotate a key, delete the old key's row from the Argus Hub database, then restart Argus Hub. Argus Hub only +generates a new key when the `api_keys` table is empty, so disabling a key with `is_enabled = 0` +does not trigger this: rotation requires removing the row outright, not just disabling it. Argus +Hub rejects a disabled key before reading the upload body. + +## Run Argus Hub continuously + +Argus Hub runs in the foreground, so a service manager can restart it and collect its logs. The Argus +Hub repository contains the Dockerfile and the complete service examples. The common deployment +shapes are below. + +### Linux with systemd + +Save this as `/etc/systemd/system/argus-hub.service`: + +```ini +[Unit] +Description=Argus Hub +After=network.target + +[Service] +Type=simple +ExecStart=npx @agentdeploymentco/argus-hub serve --port 4343 +WorkingDirectory=/srv/argus-hub +Environment=HUB_DATA_DIR=/srv/argus-hub/data +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +Enable and follow it with: + +```bash +sudo systemctl enable --now argus-hub +sudo journalctl -fu argus-hub +``` + +Set `ADMIN_PASSWORD` in the service environment so a restart does not change the dashboard +password. + +### Docker + +Pull the published image and persist `/data`, which contains `hub.db`: + +```bash +docker pull ghcr.io/agent-deployment-co/argus-hub:latest +docker run -d \ + --name argus-hub \ + -p 4343:4343 \ + -v argus-hub-data:/data \ + --env-file hub.env \ + ghcr.io/agent-deployment-co/argus-hub:latest +``` + +The package is public, so no `docker login` is needed to pull it. Prefer pinning to a specific +`` or `sha-` tag over `latest` outside local testing. Building the image +yourself (`docker build -t argus-hub .`) works the same way if you'd rather not pull a +prebuilt image. + +`hub.env` should hold at least `HUB_SECRET_KEY` (see [Quick Start](#quick-start)) and, +if you want it pinned, `ADMIN_PASSWORD`. The image exposes `GET /healthz`, which returns `200 ok` +without authentication for container health checks and Kubernetes liveness probes. + +For Docker Compose, persist the same data volume: + +```yaml +services: + argus-hub: + image: ghcr.io/agent-deployment-co/argus-hub:latest + restart: unless-stopped + ports: + - "4343:4343" + env_file: + - hub.env + volumes: + - argus-hub-data:/data + +volumes: + argus-hub-data: +``` + +### macOS with launchd + +Create a LaunchAgent at `~/Library/LaunchAgents/co.agentdeployment.argus-hub.plist`, set its +working directory and `HUB_DATA_DIR`, then load it: + +```bash +launchctl load ~/Library/LaunchAgents/co.agentdeployment.argus-hub.plist +``` + +Use the service definition in the [Argus Hub repository](https://github.com/Agent-Deployment-Co/argus-hub) +for the complete plist, including log paths and restart behavior. + +## Keep an Argus Hub private + +Place Argus Hub behind a VPN or a reverse proxy with TLS. Do not expose it directly to the internet. +The Argus Hub database contains the session data of every syncing user, so restrict filesystem access +and include it in backups. Argus Hub sets new database files to mode `0600`. + +The client sends resolved usage rows, session summaries, tasks, interaction metadata, tool and MCP +invocations and labels. It does not send retained prompt and response text or BYO API keys. The +client's local `argus.db` file never leaves the machine as a file. diff --git a/docs/argus-hub/export.md b/docs/argus-hub/export.md new file mode 100644 index 00000000..b6689cc9 --- /dev/null +++ b/docs/argus-hub/export.md @@ -0,0 +1,68 @@ +--- +description: Download an Argus Hub's data from the dashboard or the command line, and load it into Snowflake. +--- + +# Argus Hub: Export + +Export gives you the Argus Hub's full dataset as a Snowflake-ready bundle, +either from the dashboard or the command line. Both paths produce the same +contents; the CLI adds the option to load it straight into Snowflake. + +## From the browser + +Open **Export** and click the download button. Your browser streams a zip +straight to disk, so Argus Hub never has to hold the whole archive in memory to +serve it. + +The zip contains one JSONL file per table (organizations, groups, users, +clients, sessions, usage, tasks, interactions, invocations, session labels +and Argus Hub labels), a `manifest.json` with the schema version and a row count +per table, and a `load.sql` with the Snowflake DDL and load statements for +every table. API keys are never included, in the zip or anywhere else. + +
+ +![The Argus Hub Export page, with the download button for the Snowflake-ready zip.](../images/screenshots/argus-hub-export@1920x1080@2.webp) + +
+ +## From the command line + +```bash +npx @agentdeploymentco/argus-hub export snowflake +``` + +Without `--load`, this writes the same bundle to a timestamped folder and +prints where `load.sql` landed. Point `--data-dir` at the Argus Hub's data +folder if you're not running the command from the Argus Hub's working directory. + +Add `--load` to upload the bundle and swap it into Snowflake directly, +passing the connection details: + +```bash +npx @agentdeploymentco/argus-hub export snowflake --load \ + --account your-account \ + --username your-user \ + --database ARGUS_HUB \ + --schema ARGUS_HUB \ + --warehouse your-warehouse \ + --authenticator SNOWFLAKE_JWT \ + --private-key-path /path/to/key.p8 +``` + +Read credentials (password, token, key passphrase) from the environment, +never pass them as a flag. Key-pair authentication is the +recommended choice for a scheduled or unattended load, and browser SSO +only works interactively. + +Each load replaces a table's contents in full: stage the new rows, delete +the old ones, insert the new ones, all inside one transaction. It's a +snapshot replace, not an incremental or change-data-capture load, so +running it again fully supersedes the last load rather than appending to +it. + +See [Export Argus Hub data to Snowflake](https://github.com/Agent-Deployment-Co/argus-hub/blob/main/docs/snowflake.md) +in the Argus Hub repository for the full flag reference, authentication +options and known limitations, including that exported files can contain +personal data (emails, prompts, summaries) and should be handled with the +same care as the Argus Hub's own database. diff --git a/docs/argus-hub/mcp.md b/docs/argus-hub/mcp.md new file mode 100644 index 00000000..b1408579 --- /dev/null +++ b/docs/argus-hub/mcp.md @@ -0,0 +1,99 @@ +--- +description: Query an Argus Hub from an agent over MCP, the full tool list, filters, authentication and a worked example. +--- + +# Argus Hub: MCP + +Argus Hub exposes its data through [MCP](https://modelcontextprotocol.io) at +`POST /mcp`, so an agent can answer questions about the organization's +usage directly, instead of someone opening the dashboard. It's read-only: +nothing an agent sends through this endpoint changes what's synced or +who's in it, apart from the label tools below, which only add or remove an +Argus Hub label. + +## Transport + +The endpoint uses the stateless Streamable HTTP transport: every request +is a self-contained JSON-RPC call over a single POST to `/mcp`, and Argus Hub +answers it without any `initialize` handshake or session to keep alive. +There's nothing to warm up and nothing cached between calls, so an MCP +client can send `tools/list` or `tools/call` straight away. + +## Authentication + +Authenticate with Argus Hub's admin password, the same one that unlocks the +dashboard: + +```text +Authorization: Bearer +``` + +Argus Hub rejects a missing or wrong password before reading the request +body. If Argus Hub runs with no admin password configured, `/mcp` is open to +anyone who can reach it, so set one for any Argus Hub reachable outside your own +machine. + +For Claude Code: + +```bash +claude mcp add --transport http argus-hub https://hub.internal:4343/mcp \ + --header "Authorization: Bearer " +``` + +Treat the password as a shared read (and light write) credential once +you've given it to an agent. Anyone holding it can query the +organization's activity, tasks and tool usage, and add or apply labels. + +## Filters + +`query_activity`, `query_tasks`, `query_task_quality` and `query_tool_usage` +share one set of filters: + +| Filter | Meaning | +|---|---| +| `since`, `until` | Date range (`YYYY-MM-DD`), inclusive. Defaults to the last 30 days if omitted. | +| `project` | Substring match on the project path. | +| `source` | One of `claude`, `codex`, `gemini`, `cowork`. | +| `user` | One `userId`, from `query_users`. Omit for the whole organization. | +| `group` | A `groupId`, or `__none__` for people with no group. | + +`query_tasks` adds `q` (free-text search), `outcome` (comma-separated +`success`, `failure`, `unknown`) and paging with `limit` (default 50, +maximum 200) and `offset`. `query_users` only takes `group`. It's a +roster, not a windowed report, so it's the tool to call first to find a +`userId` before scoping the others. + +## Tools + +| Tool | What it answers | +|---|---| +| `query_users` | The roster: user IDs, display names, emails, group, last-sync time, sessions, tokens and cost. | +| `query_activity` | Usage and cost over the window, plus the same figures for the prior window for comparison. | +| `query_tasks` | A paged, filterable list of tasks, with outcome counts for the filtered set. | +| `query_task_quality` | Success, frustration and friction rates, outcomes over time, and the top failure signals. | +| `query_tool_usage` | Which tools, skills and MCP servers people use, and how usage compares across sources. | +| `list_labels` | Every [Argus Hub label](/argus-hub/tasks#argus-hub-labels) defined on this Argus Hub, with how many tasks carry it. | +| `create_label` | Adds a new Argus Hub label. | +| `set_task_label` | Applies or removes an Argus Hub label on one task. | + +A query tool with no matching data returns an empty result (an empty task +list, an empty roster) rather than an error. `query_activity` and +`query_task_quality` are the exception: they return an error when the +organization has no data at all in the window. + +## A worked example + +Ask an agent something like: + +> Who on the team has the highest Claude Code spend this month, and does +> their task success rate look normal? + +A reasonable path: call `query_users` to find people, `query_activity` +scoped to `source: "claude"` and this month's `since`/`until` to rank +spend, then `query_task_quality` with the same filters (or `user` set to +the top spender) to read their success and frustration rates against the +organization's. + +Every tool's response comes back as a JSON string in the result content, +so have the agent parse it rather than expect structured fields directly +on the MCP response. diff --git a/docs/argus-hub/tasks.md b/docs/argus-hub/tasks.md new file mode 100644 index 00000000..f889fbdf --- /dev/null +++ b/docs/argus-hub/tasks.md @@ -0,0 +1,98 @@ +--- +description: How Argus Hub rolls up task outcomes, frustration and failure signals across the organization, and how to label tasks for your team. +--- + +# Argus Hub: Tasks + +Argus Hub's Tasks view takes the same per-session [task](/terminology#task) +extraction described in [Tasks](/tasks), a task's description, its outcome +and how much friction it took, and rolls it up across everyone syncing to +the Argus Hub. Where the single-client Tasks view shows one session at a time, +this view is for spotting patterns: which projects or people are hitting +trouble, and what's causing it. + +
+ +![The Argus Hub Tasks view: headline totals, outcome and frustration donuts, and outcome over time.](../images/screenshots/argus-hub-tasks@1920x1080@2.webp) + +
+ +## Filters + +The same filter bar as [Activity](/argus-hub/activity): date range, source, +group. This view adds two filters of its own: a free-text search over task +descriptions and projects, and an outcome filter (success, failure, +unknown) you can combine with it. + +## Headline totals + +Four stat cards: **Total tasks**, **Success rate**, **Frustration rate** and +**Interrupted rate**. Each rate is a share of the tasks with a clear +reading. A task Argus couldn't classify doesn't count against you, and a +card reads as unavailable (`—`) rather than 0% when nothing in the window +has a clear reading yet. + +## Outcome and frustration + +Two breakdowns, each as a donut: **Outcome** (success, failure, unclear) and +**Frustration** (none, moderate, high). Both come from the same free-text +judgment a session's interpretation writes for each task. Argus Hub just +classifies and counts it across everyone, using the same rules a single +client uses, careful about phrases like "not completed" so a negated +success doesn't get miscounted. + +## Trend over time + +A stacked daily bar chart of task outcomes, success, failure and unclear, +one bar per day across the whole window, including days with no tasks. + +## By user, by source, by project + +Three ranked tables, each with task count, success rate and frustration +rate, sorted by volume: **by user**, **by source** and **by project**. Like +the per-user rankings on Activity, the by-user table stays hidden until the +organization has at least three people, so a small team's tasks aren't +attributed by name. + +## Signals and friction + +**Top signals** ranks the short failure-signal tags Argus attaches to tasks +that failed or came out frustrating, the top ten, most common first. +**Friction** rolls up interruptions, declined tool actions and context +compactions the same way [Health](/metric-views#health) does for one +client. It's measured for Claude sessions only, so a count of zero and "no +data" show as different things, and an observed-sessions count makes clear +how much of the window that friction reading actually covers. + +## Argus Hub labels + +Argus Hub labels are separate from the labels you set on a session in the Argus +app itself (see [Sessions](/sessions#labeling-and-hiding-sessions)). Those +stay local to your machine and aren't part of what +[sync](/terminology#sync) uploads. An Argus Hub label instead lives on the Argus Hub +itself, created by whoever runs it, and applied directly to the tasks Argus Hub +has collected. Use them to flag or group tasks across the whole +organization: tasks worth reviewing, tasks tied to a project or +initiative, tasks a specific team should look at. + +- **Create a label.** Open **Labels** to see every label defined on this + Argus Hub. Add one with a name and an optional description of what it means + (shown when you create it, not in the list). Querying labels over + [MCP](/argus-hub/mcp) also returns how many tasks currently carry each one. +- **Apply a label.** On a task in this view, open its label picker to find + an existing label or create one on the spot, and toggle it onto that + task. Applied labels show as pills on the task, both in the list and once + expanded. +- **Remove a label.** Toggle it off the same way, or use **Clear** on a + task to remove every label from it at once. +- **Delete a label.** Deleting a label from the Labels page removes it from + every task that carried it. + +
+ +![The Argus Hub Labels page, listing every Argus Hub label defined on this Argus Hub.](../images/screenshots/argus-hub-labels@1920x1080@2.webp) + +
+ +Argus Hub labels never travel back to a client. They exist only in the Argus Hub's own +database, for whoever has access to the Argus Hub dashboard. diff --git a/docs/argus-hub/team.md b/docs/argus-hub/team.md new file mode 100644 index 00000000..1d6ff07e --- /dev/null +++ b/docs/argus-hub/team.md @@ -0,0 +1,54 @@ +--- +description: The per-person summary table, organizing people into groups, and each person's own activity page. +--- + +# Argus Hub: Team + +Team is the roster: every person whose Argus has ever synced to this Argus Hub, +what they've used, and when they last synced. It's also where you organize +people into groups so Activity, Tasks and Tools can be scoped to a team +rather than the whole organization. + +
+ +![The Argus Hub Team table, people grouped into sections with sessions, tokens, cost and last-sync time.](../images/screenshots/argus-hub-team@1920x1080@2.webp) + +
+ +## The table + +The table lists people in sections, one per group plus a trailing **Ungrouped** +section, each sorted alphabetically by name. There's no column sort here, +since the point of this view is the roster, not ranking. Each row shows +sessions, tokens, estimated cost and when that person last synced. Click a +name to open their own activity page: the same Activity/Projects/Tools/ +Health view the single-client Argus app shows (see [Overview](/overview), +[Metric Views](/metric-views)), scoped to their usage alone. + +## Groups + +Groups are how you scope Argus Hub's other views (Activity, Tasks, Tools) to a +team rather than the whole organization: a department, a pod, whatever +division makes sense for you. Group names must be unique on an Argus Hub. + +- **Create a group** from the button above the table, giving it a name. +- **Rename** or **delete** a group from its section header. Deleting a + group doesn't remove its members, it only ungroups them, moving them + back to the **Ungrouped** section. Nobody's sync history or usage is + affected. +- **Move one person** with the row action next to them: a popover lists + every group, lets you search or create a new one on the spot, and + applies it immediately. **Clear** removes them from any group. +- **Move several at once** by selecting their checkboxes (across sections) + and using the bulk action bar that appears, choosing a target group or + **Ungrouped**. + +Once at least one person has a group, the Group filter appears on +[Activity](/argus-hub/activity), [Tasks](/argus-hub/tasks) and [Tools](/argus-hub/tools), +plus an **Ungrouped** option for anyone not yet assigned. + +
+ +![One person's activity page, reached by clicking their name in the Team table.](../images/screenshots/argus-hub-user-activity@1920x1080@2.webp) + +
diff --git a/docs/argus-hub/tools.md b/docs/argus-hub/tools.md new file mode 100644 index 00000000..d53dc2d0 --- /dev/null +++ b/docs/argus-hub/tools.md @@ -0,0 +1,90 @@ +--- +description: Which skills, tools, MCP servers and plugins the organization reaches for, aggregated across everyone syncing to an Argus Hub. +--- + +# Argus Hub: Tools + +Argus Hub's Tools view covers the same ground as the single-client +[Tools view](/metric-views#tools), skills, tools, MCP servers and plugins, +aggregated across everyone syncing to the Argus Hub, plus a handful of sections +that only make sense once you're looking at more than one person's usage. + +The same filter bar as [Activity](/argus-hub/activity) applies here: date range, +source and group. + +
+ +![The Argus Hub Tools view: the access layer overview and the "what people aren't using" table.](../images/screenshots/argus-hub-tools@1920x1080@2.webp) + +
+ +## Access layer overview + +A stat row for the window: how many distinct **tools**, **skills**, **MCP +servers** and **plugins** were used at all. A note below it calls out what +share of tool calls the top three tools account for, and how many MCP +servers make up the long tail beyond the heavily-used ones. + +## What people aren't using + +A ranked table of the least-reached tools, skills and MCP servers, by call +count and by how few distinct people ever use them. Unlike the +single-client Tools view, Argus Hub only sees what's actually invoked. It has no +visibility into what's installed but never touched, so this section is +strictly about low or single-person usage, not an enabled-but-unused +comparison. + +## MCP servers + +Two charts: calls per [MCP server](/terminology#mcp-server), and the +heaviest tool results by approximate tokens returned into context. A +server with high calls and a low tokens-per-call is cheap and popular; one +with a high tokens-per-call and few distinct users is likely flooding one +person's context, and worth a look before anyone else picks it up. MCP +tools render as `server · tool`, so you can tell which server a heavy +result came from at a glance. + +## Tool friction + +A table of tools paired with an unusual rate of non-normal stop reasons +(errors, timeouts and the like). It only appears once enough of the +window's sessions report a stop reason to make the rate meaningful, since +a handful of sessions would make any single tool look worse than it is. + +## Skills + +The organization's top [skills](/terminology#skill) by tokens, plus how +that use breaks down over time. The table underneath lists each skill's +invocations, distinct users and sources, which is what separates a skill +the whole team leans on from one person's habit. + +## Tools + +The organization's top [tools](/terminology#tool) by call count, grouped +by category, alongside a full table of every tool with its calls, +sessions, users and sources. + +## Plugins + +Argus Hub can only report a plugin as **used** or **not observed** in the +window. It runs server-side with no local install to inspect, so it can't +tell you a plugin is enabled but unused the way the single-client view +does. See [Tools](/metric-views#tools) for that distinction; Argus Hub can only +show what actually got used, and by how many people. + +## Shared vs. solo + +Which tools, skills and MCP servers are used by three or more distinct +people, versus used by only one. Like the per-user rankings elsewhere in +Argus Hub, this stays hidden until the organization has enough people syncing +that singling one out wouldn't be identifying. It's a quick way to spot a +tool worth promoting to the whole team, or one that's meant to stay +personal. + +## Comparing sources + +Once more than one [source](/terminology#source) is syncing, a side-by-side +comparison of tool-category mix and top tools, skills and MCP servers by +source, since raw tool names differ across agents (Claude Code's `Read` and +`Bash` versus Codex's `read_file` and `run_shell_command`, for example). +Categories give you a fair comparison where names don't. diff --git a/docs/images/screenshots/argus-hub-activity@1920x1080@2.webp b/docs/images/screenshots/argus-hub-activity@1920x1080@2.webp new file mode 100644 index 00000000..ad0824b8 Binary files /dev/null and b/docs/images/screenshots/argus-hub-activity@1920x1080@2.webp differ diff --git a/docs/images/screenshots/argus-hub-activity@1920x1280@2.webp b/docs/images/screenshots/argus-hub-activity@1920x1280@2.webp new file mode 100644 index 00000000..296f8c03 Binary files /dev/null and b/docs/images/screenshots/argus-hub-activity@1920x1280@2.webp differ diff --git a/docs/images/screenshots/argus-hub-dashboard@1920x1080@2.webp b/docs/images/screenshots/argus-hub-dashboard@1920x1080@2.webp deleted file mode 100644 index c80ea4ca..00000000 Binary files a/docs/images/screenshots/argus-hub-dashboard@1920x1080@2.webp and /dev/null differ diff --git a/docs/images/screenshots/argus-hub-export@1920x1080@2.webp b/docs/images/screenshots/argus-hub-export@1920x1080@2.webp new file mode 100644 index 00000000..c2e8c2be Binary files /dev/null and b/docs/images/screenshots/argus-hub-export@1920x1080@2.webp differ diff --git a/docs/images/screenshots/argus-hub-export@1920x1280@2.webp b/docs/images/screenshots/argus-hub-export@1920x1280@2.webp new file mode 100644 index 00000000..f1b04db8 Binary files /dev/null and b/docs/images/screenshots/argus-hub-export@1920x1280@2.webp differ diff --git a/docs/images/screenshots/argus-hub-labels@1920x1080@2.webp b/docs/images/screenshots/argus-hub-labels@1920x1080@2.webp new file mode 100644 index 00000000..3908e628 Binary files /dev/null and b/docs/images/screenshots/argus-hub-labels@1920x1080@2.webp differ diff --git a/docs/images/screenshots/argus-hub-labels@1920x1280@2.webp b/docs/images/screenshots/argus-hub-labels@1920x1280@2.webp new file mode 100644 index 00000000..59629e2d Binary files /dev/null and b/docs/images/screenshots/argus-hub-labels@1920x1280@2.webp differ diff --git a/docs/images/screenshots/argus-hub-tasks@1920x1080@2.webp b/docs/images/screenshots/argus-hub-tasks@1920x1080@2.webp new file mode 100644 index 00000000..9e0ba9cb Binary files /dev/null and b/docs/images/screenshots/argus-hub-tasks@1920x1080@2.webp differ diff --git a/docs/images/screenshots/argus-hub-tasks@1920x1280@2.webp b/docs/images/screenshots/argus-hub-tasks@1920x1280@2.webp new file mode 100644 index 00000000..6f8820c7 Binary files /dev/null and b/docs/images/screenshots/argus-hub-tasks@1920x1280@2.webp differ diff --git a/docs/images/screenshots/argus-hub-team@1920x1080@2.webp b/docs/images/screenshots/argus-hub-team@1920x1080@2.webp new file mode 100644 index 00000000..ea7f2123 Binary files /dev/null and b/docs/images/screenshots/argus-hub-team@1920x1080@2.webp differ diff --git a/docs/images/screenshots/argus-hub-team@1920x1280@2.webp b/docs/images/screenshots/argus-hub-team@1920x1280@2.webp new file mode 100644 index 00000000..0da919be Binary files /dev/null and b/docs/images/screenshots/argus-hub-team@1920x1280@2.webp differ diff --git a/docs/images/screenshots/argus-hub-tools@1920x1080@2.webp b/docs/images/screenshots/argus-hub-tools@1920x1080@2.webp new file mode 100644 index 00000000..5c5ca2e6 Binary files /dev/null and b/docs/images/screenshots/argus-hub-tools@1920x1080@2.webp differ diff --git a/docs/images/screenshots/argus-hub-tools@1920x1280@2.webp b/docs/images/screenshots/argus-hub-tools@1920x1280@2.webp new file mode 100644 index 00000000..280b3794 Binary files /dev/null and b/docs/images/screenshots/argus-hub-tools@1920x1280@2.webp differ diff --git a/docs/images/screenshots/argus-hub-user-activity@1920x1080@2.webp b/docs/images/screenshots/argus-hub-user-activity@1920x1080@2.webp new file mode 100644 index 00000000..22a3ede0 Binary files /dev/null and b/docs/images/screenshots/argus-hub-user-activity@1920x1080@2.webp differ diff --git a/docs/images/screenshots/argus-hub-user-activity@1920x1280@2.webp b/docs/images/screenshots/argus-hub-user-activity@1920x1280@2.webp new file mode 100644 index 00000000..a1539cea Binary files /dev/null and b/docs/images/screenshots/argus-hub-user-activity@1920x1280@2.webp differ