Skip to main content
ClaudeWave
Skill522 estrellas del repoactualizado today

pages

Pages is a Claude Code skill that creates database-backed static HTML or JSON content served directly by the API without requiring a separate service infrastructure. Use it for lightweight, shareable snapshots like status reports, dashboards, or JSON payloads that need versioning and URL distribution, but avoid it for dynamic applications requiring custom routes, WebSocket support, or per-request computation.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/desplega-ai/agent-swarm /tmp/pages && cp -r /tmp/pages/plugin/skills/pages ~/.claude/skills/pages
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Pages — DB-backed Static Artifacts

DB-backed static content (HTML or JSON) served by the API directly. Cheap,
versioned, share-able by URL. The lighter-weight cousin of `artifacts` —
no PM2, no tunnels, no port allocation, no `services` registry row.

> **Capability gate**: the `create_page` MCP tool is only available when the
> agent's `CAPABILITIES` env var includes `pages`
> (e.g. `CAPABILITIES=core,task-pool,pages`). If the tool is missing from
> your MCP list, this is why.

## When to use Pages vs Artifacts

| You need… | Use |
|---|---|
| A static HTML report / dashboard | **Pages** |
| A JSON status payload + a few buttons that call swarm APIs | **Pages** (`contentType: 'application/json'`) |
| To share an output via a URL with no server logic | **Pages** |
| Custom routes, websockets, server-side logic | **Artifacts** (`plugin/skills/artifacts/skill.md`) |
| File uploads or per-request computation | **Artifacts** |

Rule of thumb: if the content is a snapshot (you can write the full HTML/JSON
in a single call), use pages. If the content is a *running program*, use
artifacts.

## Quick Start

### Authed HTML report
```jsonc
// Tool call: create_page
{
  "title": "Q2 Status Report",
  "description": "Roll-up of in-flight tasks across the swarm",
  "contentType": "text/html",
  "authMode": "authed",
  "body": "<!doctype html><html><body><h1>Q2 Status</h1>...</body></html>"
}
// → { id, version: 1, app_url, api_url }
```

Share `app_url` (the SPA route) for the general case; share `api_url` for a
no-SPA-required direct link.

Use `authMode: "public"` only when the page is intentionally safe for anyone
with the URL to view.

### Authed JSON dashboard
```jsonc
// Tool call: create_page
{
  "title": "Agent Inbox",
  "description": "Live tasks for me",
  "contentType": "application/json",
  "authMode": "authed",
  "body": "{\"$schema\":\"...\",\"type\":\"page\",\"children\":[{\"type\":\"text\",\"value\":\"Hello\"},{\"type\":\"button\",\"label\":\"Refresh\",\"action\":{\"swarm.call\":{\"method\":\"GET\",\"endpoint\":\"/api/tasks?status=in_progress\"}}}]}"
}
// → { id, version: 1, app_url, api_url }
```

`authed` pages require a viewer to be signed in to the SPA (or to mint a
page-session cookie via the launch endpoint) before the page can call the
swarm API.

## Auth Modes

| Mode | URL behavior | When to use |
|---|---|---|
| `public` | No gate. Anyone with the URL sees the content. Browser SDK calls **return 401** (no viewer identity → no API access). | Static reports, marketing pages, anything safe to share externally. |
| `authed` | SPA `app_url` works for any signed-in dashboard user. Direct `api_url` requires a `page_session` cookie (mint via `POST /api/pages/:id/launch`). Browser SDK calls run as the viewing user. | Per-team dashboards, JSON pages with action buttons. |
| `password` | `?key=<password>` or HTTP Basic on `/p/:id` unlocks. Once unlocked, behaves like `authed` (cookie minted, SDK calls run as viewer's identity). | Pages shared with non-swarm users (clients, contractors). |

> Password unlock has to happen on `/p/:id` directly (the API origin) because
> the password isn't sent to the SPA. Sharing an `app_url` for a `password`
> page works but the SPA will redirect the iframe through `/p/:id` for the
> Basic prompt.

## URL Shapes

| URL | Shape | Notes |
|---|---|---|
| `app_url` | `${APP_URL}/pages/:id` | SPA route. Renders HTML in a sandboxed iframe, JSON via `@json-render/react`. Default share target. |
| `app_url` (full mode) | `${APP_URL}/pages/:id?mode=full` | Same SPA route, maximized — hides the SPA sidebar/header so the page body gets the full viewport. Slim header with title + Exit-Full button. Useful for embeds + standalone dashboards. |
| `api_url` | `${MCP_BASE_URL}/p/:id` | Direct API render. HTML inlines and serves; JSON 302-redirects to `app_url`. Useful for no-SPA-required links. |

`${APP_URL}` is the SPA origin (e.g. `https://app.agent-swarm.dev` in prod).
`${MCP_BASE_URL}` is the API origin (e.g. `https://api.desplega.agent-swarm.dev`
in prod). Both are surfaced as env vars to your agent — never hardcode hosts;
read them from `process.env`.

**Default**: share `app_url`. Append `?mode=full` when the recipient should
see ONLY the page (no surrounding swarm chrome). Use `api_url` only when you
specifically need a link that bypasses the SPA (e.g. embedding in Slack,
where the unfurl preview only follows the API origin).

## Versioning

Every overwrite (update via `update_page` or `PUT /api/pages/:id`) snapshots
the **pre-update** state into `page_versions` and writes the new state to the
parent row. The wire `version` field is a monotonically-increasing
"edit counter" — version 1 is the initial create.

| Operation | Endpoint | Returns |
|---|---|---|
| List versions | `GET /api/pages/:id/versions` | `{ versions: PageVersion[] }` newest first |
| Read a version | `GET /api/pages/:id/versions/:version` | Single snapshot |

Snapshots are full body copies — keep this in mind for large pages (the
per-version body cap is 5 MiB).

## Browser SDK

Every HTML page automatically gets `window.SwarmSDK` (the class) and
`window.swarmSdk` (a ready-to-use singleton) injected. The SDK routes through
the `/@swarm/api/*` proxy, which resolves the `page_session` cookie to a user
identity and forwards with proper auth headers server-side — your page never
sees or handles tokens.

The SDK is **domain-grouped**. Each domain exposes idiomatic CRUD-ish methods
that map 1:1 to the public REST API documented at
[**docs.agent-swarm.dev/docs/api-reference**](https://docs.agent-swarm.dev/docs/api-reference).

| Domain | Methods | Maps to |
|---|---|---|
| `swarmSdk.tasks` | `create(body)`, `list(filters?)`, `get(id)`, `storeProgress(id, data)` | `/api/tasks*` |
| `swarmSdk.agents` | `list()`, `get(id)` | `/api/agents*` |
| `swarmSdk.events` | `create(body)`, `list(filters?)`, `batch(body)`, `counts(filters?)` | `/api/events*` |
| `swarmSdk.memory` | `search(body)`, `list(filter