Live Observer Dashboard¶
The Claw dashboard lets you watch a society execute in real-time. It visualizes the agent graph, streams events as they flow along edges, and tracks artifact changes — all in your browser.
Quick Start¶
# 1. Build the dashboard (one time)
cd dashboard && npm install && npm run build && cd ..
# 2. Run any society with the dashboard
uv run python examples/pr_review_dashboard.py
# 3. Open http://127.0.0.1:8765 in your browser
That's it. The dashboard shows the society graph, streams events in real-time, and shuts down when the society completes.
Using serve() in Your Own Code¶
The serve() function is a drop-in replacement for calling LocalRuntime.run() directly. It runs the society and dashboard server concurrently:
import asyncio
from claw import Society, Agent, Delegation, serve
from claw.llm import MockLLM
# Build your society
s = Society(name="my-society")
alice = Agent(name="alice", role="worker", model="mock")
bob = Agent(name="bob", role="reviewer", model="mock")
s.connect(alice, bob, Delegation())
# Run with dashboard (instead of LocalRuntime.run())
result = asyncio.run(serve(
s,
task="Do something interesting",
llm=MockLLM(),
))
serve() Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
society |
Society |
required | The society to execute |
task |
str |
required | Task description to seed the first event |
llm |
LLM |
required | LLM backend (MockLLM, LiteLLMBackend, etc.) |
host |
str |
"127.0.0.1" |
Server bind address |
port |
int |
8765 |
Server bind port |
artifacts |
list |
None |
Artifacts to pre-register |
Return Value¶
serve() returns a SocietyResult — the same object you get from LocalRuntime.run(). The server shuts down automatically after the society completes.
Dashboard Layout¶
┌─────────────────────────────────────────────────────┐
│ 🦀 Claw │ society-name │ Running │ Events: 12 │ ● │ ← Header
├────────────────────────────────┬────────────────────┤
│ │ 10:32:01 pm → cod… │
│ Graph View │ 10:32:01 coder → … │
│ │ 10:32:02 reviewer… │ ← Event Feed
│ [pm] ──→ [coder] ──→ [rev] │ 10:32:02 coder → … │
│ │ 10:32:03 reviewer… │
├────────────────────────────────┴────────────────────┤
│ Agent: coder │ Artifacts │ │ ← Detail Panel
│ Role: implementer │ Model: mock │ Events: 5 │
└─────────────────────────────────────────────────────┘
- Graph View (center, 60%): Agent nodes with status indicators, color-coded edges
- Event Feed (right, 25%): Chronological log with filtering
- Detail Panel (bottom, 15%): Agent details or artifact version history
Node Status Colors¶
| Status | Color | Meaning |
|---|---|---|
| Idle | Gray | Waiting for events |
| Active | Green | Currently executing |
| Completed | Blue | Society has terminated |
Edge Type Colors¶
| Edge Type | Color |
|---|---|
| Cooperation | Green |
| Competition | Red |
| Oversight | Blue |
| Delegation | Orange |
| Coopetition | Purple |
Development Workflow¶
For working on the dashboard frontend with hot module replacement:
# Terminal 1: Run the Python server + society
uv run python examples/pr_review_dashboard.py
# Terminal 2: Run Vite dev server with HMR
cd dashboard && npm run dev
Then open http://localhost:5173 (Vite dev server). The Vite config proxies /ws and /api requests to the Python server on port 8765.
Advanced: Manual Setup¶
If you need more control (e.g., custom CORS, running the observer independently):
import asyncio
import uvicorn
from claw import LocalRuntime, Society
from claw.server import WebSocketObserver, create_app
society = build_your_society()
llm = your_llm_backend()
# Create observer and app separately
observer = WebSocketObserver(society, buffer_size=1000)
app = create_app(observer, cors_origins=["https://my-domain.com"])
# Create runtime with observer
runtime = LocalRuntime(llm, observer=observer)
# Run server and society however you want
async def main():
config = uvicorn.Config(app, host="0.0.0.0", port=8765)
server = uvicorn.Server(config)
server_task = asyncio.create_task(server.serve())
result = await runtime.run(society, "my task")
server.should_exit = True
await server_task
return result
asyncio.run(main())
REST API¶
The server also exposes REST endpoints (useful for debugging or building custom UIs):
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Serves the dashboard (or a help page if not built) |
/api/society |
GET | Current society graph as JSON |
/api/artifacts |
GET | Current artifact state |
/api/trace |
GET | Full buffered event trace |
/ws |
WebSocket | Live event stream |
Late-Joining Clients¶
The server buffers the last 500 events (configurable via buffer_size). If you open the dashboard after the society has started, you'll receive a replay of buffered events before switching to the live stream.