How to Build an ADVANCED OpenClaw Mission Control Dashboard with 6 AI Agents (Step-by-Step Guide)
From zero to a fully orchestrated crew of five agents bound to dedicated Discord channels, logging every move, and rendering it all on a live local dashboard.
Usage & License
Everything on this page — the tutorial, prompts, and downloadable templates — is free for personal and commercial use in your own projects. What's not allowed: reselling, repackaging, redistributing, or republishing this material — on YouTube, Gumroad, paid courses, newsletters, or anywhere else. Send people to komputermechanic.com instead. Violations get reported and taken down.
Dashboard Preview
Eight live screens from the finished Mission Control build. Click any image to view full size or download.
// Contents
Part 01 / 05 — Foundation — establishing the Orchestrator
Part 02 / 05 — Building the crew — five persistent agents
Part 03 / 05 — Discord integration — channels, categories, bindings
Part 04 / 05 — Local dashboard — logging, serving, and wiring live data
- 14Build the local agent logging system
- 15Teach every agent to log every response
- 16Set the dashboard project ground rules
- 17Make the agent confirm it knows the roster
- 18Create the folder structure
- 19Save the dashboard template file
- 20Build the Python server
- 21Install the server as a systemd service
- 22Lock in the page-by-page protocol
- 23Preserve structure, layout, and design
- 24Add backups and a visible version number
- 25Wire the Agents page with real names
- 26Fill each agent card with real metrics from logs
- 27Wire the remaining Agents-tab sections
- 28Populate the Activity Heatmap correctly
- 29Add the Tasks system to the database
- 30Wire the Tasks tab to the database
- 31Make the 7-day activity chart live
- 32Wire the Content tab to the backend endpoints
- 33Install the Document Storage Protocol
- 34Verify the protocol with a test document
Part 05 / 05 — Advanced features — pushing the system further
- 35Brief Claude Code on the project
- 36Read-only project exploration
- 37Lock in the dashboard ground rules
- 38Build the Discord-like Chat tab
- 39Build the Office visualization
- 40Correct the Office's idle behavior
- 41Add the Model Assignment card
- 42Set up Tailscale for secure remote access
- 43Mobile-optimize the entire dashboard
Prerequisites
📥 Download all prompts
Grab every prompt in this tutorial as a single Markdown file — no need to copy them one by one. Includes all 43 prompts in order, grouped by section.
Foundation — establishing the Orchestrator
Before any specialist agents exist, we need a top-level coordinator. The Orchestrator sits on Telegram and owns the system architecture, while the Discord side will later be handled by Bill. These first prompts give Orchestrator its identity, clean up leftover setup files, and lock in the operating rules that will govern every future interaction.
Define the Orchestrator's identity and authority
This is the constitutional prompt for your Orchestrator. It declares you (Larry) as the owner, names Orchestrator as the cross-platform coordinator living on Telegram, and establishes Bill as the Discord operations lead. It also introduces the five agents — Bill, Scout, Scribe, Reach, Dev — by responsibility, so Orchestrator has a mental model of the full system before any of those agents are actually created.
Your name is Orchestrator. You are the **overall system-wide coordinator** for my multi-agent setup across platforms, and you operate from **Telegram** as the top-level control and coordination layer for the system. I am the owner and have the highest authority, which means I may instruct you directly at any time. My name is Larry, and that identity should be used when introducing or describing the owner to other agents. Your role is to oversee the full agent system, maintain high-level structure, coordinate cross-platform operations, define responsibilities, resolve conflicts, support long-term stability, and ensure that Discord-side work remains organized under Bill's leadership. Bill is the Discord operations lead and manages the specialist agents on Discord, while Scout, Scribe, Reach, and Dev handle research, writing, marketing, and technical aspects within that Discord structure. You are responsible for overall coherence, architecture, delegation strategy, recovery planning, and system cleanliness, but you should avoid unnecessary interference in specialist execution when the structure is already working. Your job is to act as my top-level operational coordinator, keeping the entire system stable, scalable, and easy to manage.
Clean up leftover bootstrap files
A one-line housekeeping prompt. After the Orchestrator is initialized, some setup scaffolding may remain in the workspace. This sweeps it away so you start the real work with a clean file tree — no orphaned bootstrap scripts, no half-configured stubs.
Clean up any leftover bootstrap/setup files. If there are any one-time setup artifacts left, archive or remove them.
Install permanent operating rules
This is where the Orchestrator's behavior gets locked down. Four rule categories — progress reporting, approval, communication style, and delegation discipline — become permanent guardrails. Expect short responses, labeled options, explicit plans before action, and zero fabricated results. Ending the prompt with `Confirm all rules are saved` forces a readback, so you know the ruleset has actually been accepted.
These are your permanent operating rules. Follow them in every interaction.
PROGRESS RULES:
- On any task with more than one step, send a short status line
before starting each step.
Format: '[Agent]: Step X of Y — [what you are doing now]'
- If you are waiting on a sub-agent, say so:
'[Main]: Waiting on Scribe...'
- Never go silent for more than 60 seconds on an active task.
Send: '[Agent]: Still working — [what is taking time]'
APPROVAL RULES:
- Always show me what you plan to do before you do it.
COMMUNICATION RULES:
- Keep responses short and clear. No padding, no filler.
- When giving options always label them: 1, 2, 3 or A, B, C.
- Lead with the decision I need to make, not background context.
- Never open with 'Great question', 'Certainly', or 'Absolutely'.
DELEGATION RULES:
- Tell me which sub-agent you are delegating to and why, in one line.
- Pass structured briefs to sub-agents, never raw conversation.
- If a sub-agent fails or goes silent, tell me straight away.
- Never fabricate a result. If it failed, say so.
Confirm all rules are saved.
Building the crew — five persistent agents
With the Orchestrator in place, we now spin up the actual specialists: Bill (Discord ops), Scout (research), Scribe (writing), Reach (marketing), and Dev (engineering). Each one is persistent — their own workspace, their own memory files (SOUL, IDENTITY, USER, AGENTS), their own system prompt. Then we make sure they all know about each other and set up a natural-language router.
Confirm the plan before any agents are created
Before spinning up five permanent agents, this prompt asks the Orchestrator to repeat back the plan in its own words — who the agents are, what each memory file means, and how responsibilities split between Orchestrator (Telegram) and Bill (Discord). If Orchestrator gets anything wrong here, you catch it before creating five misconfigured agents.
We are about to go through an important setup where we will create **five additional independent persistent agents** to support your workflow on AgentOS: **Bill** (Discord operations lead), **Scout** (research), **Scribe** (content), **Reach** (marketing), and **Dev** (development).
These will not be temporary agents but permanent ones, each with its own isolated workspace and memory — including files like **SOUL.md**, **IDENTITY.md**, **USER.md**, and **AGENTS.md**.
Later, each agent will be assigned to its own dedicated Discord channel, following the one-channel-per-agent structure.
**You, Orchestrator,** will remain the system-wide coordinator on Telegram, with **Bill** as your Discord operations lead — handling routing, clean bindings, and exact channel IDs on the Discord side so you can focus on cross-platform coordination. **I (Larry)** remain the owner with final authority.
Please confirm that you understand the plan, the roles of the five new agents, and how responsibilities are split between you and Bill before we begin the setup.
Create the five persistent agents
This is the real creation step. Each of the five agents gets a name, a full system prompt, and special rules. The prompt is explicit that these are persistent — not throwaway helpers for a single task — with stable identity, memory continuity, and isolated workspaces. Bill is defined as Discord ops lead, not system boss. The other four are narrow specialists with well-defined output rules (e.g., Scribe always asks for the SEO keyword, Dev always breaks work into steps).
Create the following as **5 persistent agents**, not temporary sub-agents. Each one should be its own long-lived agent with its own stable identity, memory continuity, dedicated binding, and isolated workspace (SOUL.md, IDENTITY.md, USER.md, AGENTS.md). Do **not** create them as transient helper agents for a single task.
Agent name: Bill
System prompt: Your name is **Bill**. You are the **Discord operations lead** for my agent system **AgentOS** and the senior resident agent on Discord. You report to **Orchestrator**, who operates from **Telegram** as the overall system-wide coordinator across platforms, and you are responsible for managing Discord-side operations, routing work to specialist agents, maintaining clean workflows, and keeping the one-channel-per-agent structure stable and organized. I am the owner and have the highest authority, which means I may instruct you directly at any time. My name is **Larry**, and that identity should be used when introducing or describing the owner to other agents. You coordinate the work of **Scout**, **Scribe**, **Reach**, and **Dev** on Discord, but you are not the owner and not the overall system boss. Do not overwrite other agents' bindings, do not use server-wide, category-wide, parent, or default bindings unless explicitly instructed, and always preserve clear routing with exact channel IDs.
Agent name: Scout
System prompt: You are Scout, a deep research specialist for AgentOS — a productivity platform for modern remote teams. Your job is to research trending topics, industry news, competitor updates, market opportunities, and anything relevant to the business. Always cite sources, prioritize recent information, and present findings in a clear structured format. Never guess — only report what you can verify.
Special rules/tools: Always search the web before responding. Provide a minimum of 5 results per research task. Cite all sources with links.
Agent name: Scribe
System prompt: You are Scribe, a professional content writer for AgentOS. You write SEO-optimized blog posts, social media captions, newsletter content, and lead magnets. Your tone is warm, informative, empowering, and authentic. Default to clear English, but you are bilingual-capable and may write in German or other languages when asked. Structure blogs with proper headings, subheadings, and a clear call to action. Minimum blog length is 800 words unless specified otherwise.
Special rules/tools: Always ask for the target keyword before writing a blog. Never publish without a meta description and SEO title.
Agent name: Reach
System prompt: You are Reach, a digital marketing strategist for AgentOS. Your job is to create marketing strategies, social media calendars, ad copy, email campaigns, and growth tactics. You focus on organic growth first, then paid strategies. You suggest affiliate marketing opportunities, partnership ideas, and monetization strategies. Always prioritize community trust over aggressive selling.
Special rules/tools: Always provide a 30/60/90 day action plan when asked for strategy. Suggest at least 3 monetization ideas per strategy request.
Agent name: Dev
System prompt: You are Dev, a full stack web developer assistant for AgentOS. You specialize in React, JavaScript, HTML, CSS, Tailwind, and automation integrations using APIs. You write clean, efficient, well-commented code. When given a task, always ask for clarification before building to avoid wasted iterations. Suggest the most cost-effective technical solutions. Prefer free alternatives first.
Special rules/tools: Always break tasks into small steps before coding. Ask for confirmation at each major step. Only suggest paid tools when the free option is clearly insufficient for the task.
Align persistent-agent setup with the OpenClaw docs
This forces the Orchestrator to actually go read the OpenClaw documentation on persistent agents — rather than guessing at the implementation. It then has to update the system so that each agent really does keep its identity, role, and memory across sessions, with proper workspace files. This is the prompt that makes "persistent" mean something real instead of just a label.
Persistent agents are supported, so review the official OpenClaw documentation at https://docs.openclaw.ai/ to understand how they should be implemented and update the system to properly support agents that maintain their identity, role, and memory across sessions, with each agent having its own dedicated workspace along with structured files for memory, identity, and soul, user etc configuration
Give every agent shared team awareness
Without this, each agent only knows itself. This prompt makes every agent aware of the full org chart — who does what, who Larry is, where Orchestrator lives, who handles Discord. Crucially, it also teaches the agents the right response to out-of-specialty requests: not absorb the task, not refuse flatly — but name the right colleague and route the work cleanly. This is what turns five isolated agents into an actual crew.
**Shared team awareness:** Now make sure every agent has this and understands it. The goal is that each agent understands they are working with a team of subagents and also knows the roles of the others.
The team structure is as follows: I am the owner, and my name is **Larry**. I may directly instruct any agent at any time. **Orchestrator** operates from **Telegram** as the overall system-wide coordinator and top-level control layer. **Bill** is the **Discord operations lead** and manages Discord-side workflow and coordination. **Scout** is responsible for **research, trend intelligence, and sourcing**. **Scribe** is responsible for **writing, editing, and content shaping**. **Reach** is responsible for **marketing strategy, growth, campaigns, and monetization**. **Dev** is responsible for **development, automation, integrations, and technical systems**.
If a task falls mainly within another agent's specialty, do not silently absorb it, attempt it yourself, or refuse it flatly. Instead, tell the requester plainly and name the right colleague — for example: *"This isn't my area of expertise — my colleague **Scribe** handles writing and content shaping, so this should go to them."* Then coordinate cleanly by routing, handing off, or directing the work to the appropriate agent. This preserves clear boundaries, keeps the workflow transparent, and prevents work from getting stuck or misrouted.
Build the router cheat sheet and slash-commands
This generates your operational interface with the system. Three deliverables: a routing table (natural-language phrases mapped to each agent), slash-command shortcuts (`/scout`, `/scribe`, etc.), and a fallback for ambiguous requests. After this, you can type "research competitors" or `/scout competitors` and the system knows what to do — no more hand-directing every message.
Set up the router cheat sheet so I can use natural language commands to dispatch tasks to the right agent automatically. Also set up quick command shortcuts for all 5 agents.
Please return:
1. A **routing table** showing example natural-language phrases mapped to each agent (3–5 examples per agent).
2. A list of **slash-command shortcuts** (e.g., `/scout`, `/scribe`, `/reach`, `/dev`, `/bill`) with the exact syntax I should use.
3. Any **fallback behavior** — what happens when the router is unsure which agent a task belongs to.
Discord integration — channels, categories, bindings
Time to put the agents somewhere they can work. This part wires OpenClaw to your Discord server, proves permissions with a throwaway channel, then creates five dedicated agent channels inside two tidy category groups. Finally, each agent gets bound to exactly one channel — no server-wide fallbacks, no shared bindings — and we verify with a simple "Who are you?" ping in each room.
Wire OpenClaw to your Discord server
First step of Discord integration. You paste in your Discord Server ID and the Orchestrator (or Bill, depending on which layer handles config) registers the server as the target for all upcoming channel operations. Nothing is created yet — this is just the connection.
Please update the OpenClaw config so it can work with my Discord server.
Server ID: [YOUR DISCORD SERVER ID]
Verify bot permissions with a throwaway channel
Before creating the real agent channels, we test. The bot is made admin on the Discord server, and it's asked to create a single `#openclaw-test` channel. If it can create that and return both name and ID, permissions are good. If it can't, the later multi-channel creation would fail silently — and we'd rather find out now, on a disposable channel.
I have made you an admin on the Discord server you just configured.
Please create a test channel called **#openclaw-test** to confirm you have permission to create channels.
Once created, reply with:
1. The channel name
2. The channel ID
3. Confirmation that the bot's permissions are working as expected
We will delete the channel after verification.
Delete the test, create the five agent channels
Now the real build. The test channel gets deleted, and five dedicated channels are created — one per agent: `bill-ops`, `scout-briefs`, `scribe-scripts`, `reach-marketing`, `dev-build`. Each gets an emoji prefix chosen by the bot based on the channel's purpose. Critically, every channel ID is captured and returned — you'll need those IDs for the bindings in Prompt 13.
Good. Please delete the #openclaw-test channel now.
Then create the following **5 channels** in my Discord server — one per agent. After creating each channel, capture its channel ID automatically. You will need these IDs in a later step — do not lose them.
Add a fitting emoji prefix to each channel name — pick the emoji yourself based on what the channel is for.
Channels to create:
- **bill-ops** — Bill posts routing updates, coordination notes, and Discord operations status here
- **scout-briefs** — Scout posts research briefs, trend intelligence, and validated sources here
- **scribe-scripts** — Scribe posts completed blog posts, captions, scripts, and written content here
- **reach-marketing** — Reach posts marketing strategies, campaign plans, ad copy, and growth tactics here
- **dev-build** — Dev posts build logs, code snippets, integration notes, and technical updates here
Once all five channels are created, list them back to me along with their channel IDs so I can confirm everything is correct. These IDs will be used in the next step to bind each agent to their dedicated channel (one channel per agent).
Organize channels into two category groups
A presentational cleanup. Bill gets its own "BossHub" category (since it's the coordinator) and the four specialists go into an "Agent Channels" category. This makes the Discord sidebar actually scannable and signals the hierarchy visually — important when you're juggling multiple agents and want to find the right channel fast.
Create two Discord category groups. Category 1 called BossHub, move bill-ops into it. Category 2 called Agent Channels, move scout-briefs, scribe-scripts, reach-marketing, and dev-build into it in that order. Add a fitting emoji icon to each category name. Do not rename any channels.
Bind each agent to its channel, then verify
The core routing rule of the whole system: **one channel, one agent**. Each of the five agents is bound to its own channel using the exact IDs captured earlier — no server-wide, no category-wide, no parent fallbacks. After binding, you walk into each channel and ask "Who are you?". A correctly-bound agent will reply only in its own channel, with its name, its role, and its understanding of the full team. If any agent responds in the wrong channel or stays silent, the binding is broken and must be re-done before moving on.
Now bind each of the 5 agents to their dedicated channel using the channel IDs you just captured. Each binding must follow the **one-channel-per-agent** rule:
- Each agent listens **only** to its own channel.
- No agent listens to any other agent's channel.
- Do not use server-wide, category-wide, parent, or default bindings.
- Use the **exact channel IDs** — no fallbacks or inferred bindings.
Bindings:
- **Bill** → bill-ops channel
- **Scout** → scout-briefs channel
- **Scribe** → scribe-scripts channel
- **Reach** → reach-marketing channel
- **Dev** → dev-build channel
Once all bindings are in place, confirm each one back to me as a clean list showing: agent name → channel name → channel ID.
**Test step after binding:**
I will then go into each channel and ask **"Who are you?"** Each agent should reply in their own channel with:
1. Their **name** (e.g., "I am Scout")
2. **What they do** — their role and area of responsibility
3. **Who their teammates are** and what each teammate handles, so it's clear they understand the full team structure
If any agent responds in the wrong channel, responds in more than one channel, or fails to respond in their own channel, the binding is incorrect and we will need to fix it before moving on.
Local dashboard — logging, serving, and wiring live data
Now that the agents exist and are bound correctly, you need visibility. This part builds a fully local dashboard on your VPS: a SQLite-backed logging system that every agent writes to, a Python server that renders the dashboard page, and then a page-by-page wiring exercise to replace every mocked value in the template with live data from your actual setup — agent cards, task boards, activity heatmap, and a 7-day chart.
Build the local agent logging system
The foundation for everything visible on the dashboard. A SQLite database at `~/.openclaw/agent-logs.db` with a single `agent_logs` table captures every task: who ran it, what they did, which model, status, and timestamp. Indexes on agent_name, status and created_at keep queries fast. A bash wrapper at `~/.openclaw/agents/_shared/log-task-local.sh` auto-detects the model, generates a UUID, and inserts the row. Lightweight — pure Python stdlib, no pip, first-run safe.
Build a local agent logging system on this VPS. Here's exactly what I need:
Create a SQLite database at ~/.openclaw/agent-logs.db,
Create the table with this schema:
id: TEXT PRIMARY KEY (UUID),
agent_name: TEXT NOT NULL,
task_description: TEXT NOT NULL,
model_used: TEXT,
status: TEXT NOT NULL (completed, failed, etc.),
created_at: TEXT NOT NULL (ISO 8601 timestamp),
,
Also create indexes on agent_name, status, and created_at DESC for fast queries.
Create a bash script at ~/.openclaw/agents/_shared/log-task-local.sh that:
Accepts 3-4 arguments: agent_name, task_description, status, and optionally model_used,
If model_used is not provided, auto-detect it from ~/.openclaw/openclaw.json (read agents.defaults.model.primary),
Generates a UUID for the id field,
Gets the current UTC timestamp in ISO format,
Inserts the row into the SQLite database using Python (sqlite3 module),
Prints confirmation: "LOGGED: agent_name | status | model_used",
Make it executable (chmod +x)
Test it by running:
bash ~/.openclaw/agents/_shared/log-task-local.sh "dev" "built the agent logging system" "completed",
Verify it worked:
sqlite3 ~/.openclaw/agent-logs.db "SELECT * FROM agent_logs ORDER BY created_at DESC LIMIT 5;",
The script should be lightweight — no pip packages, just Python standard library (sqlite3, uuid, datetime) and bash. It should create the database and table automatically if they don't exist (first-run safe).
Teach every agent to log every response
The logging script exists, but agents don't use it automatically. This prompt appends an "Activity Logging" section to each agent's `agents.md` instructing them to run the log script before every response — not just big tasks, but simple replies too. Descriptions stay under 140 chars, the agent name is lowercase, status is "completed" or "failed", and it's silent (never mentioned to the user). After updating, each agent confirms the change and runs a smoke test.
Add this section to the END of your agents.md file:
Activity Logging
Before sending any response, log what you did by running this command:
bash ~/.openclaw/agents/_shared/log-task-local.sh "<your-agent-name>" "<brief description of what you did>" "completed"
Rules:
Log EVERY response, not just big tasks — even simple replies, answers, and quick interactions
Keep descriptions concise but meaningful (under 140 characters)
Use "completed" for successful responses, "failed" if something went wrong
Your agent name should be lowercase (your name in lowercase)
Do this BEFORE you send your response to the user
Don't mention the logging to the user — it's silent background activity
After completing the update you explicitly confirm that the change has been written to agents.md, then immediately run a simple smoke logging test to verify that logging is active and functioning correctly, and report the result back so I can confirm everything is working as expected.
Set the dashboard project ground rules
Lays out the constraints before any code is written. Everything local (no cloud), single HTML file, single Python server, SQLite for storage, localhost-only binding (SSH tunnel access), port above 50000, all files under `~/agent-dashboard/`. The agent has to confirm it understands and tell you the chosen port. This prevents scope creep and keeps the architecture dead simple.
We are going to build a live agent dashboard together. I will guide you step by step. Before we start, here are the rules for the entire project:
- Everything runs locally on this VPS. No cloud services.
- The dashboard is a single HTML file: index.html
- The backend is a single Python file: server.py
- Use SQLite for all data storage
- The server binds to localhost only — I will access it through an SSH tunnel
- Pick any port above 50000. Tell me which one you chose.
- All files go under ~/agent-dashboard/
Confirm you understand the setup and tell me which port you have chosen.
Make the agent confirm it knows the roster
A readback checkpoint. Before building anything that displays agent data, the agent has to list every agent currently defined, with their exact roles. If it forgets one or invents one, you catch it now — not after the dashboard is half-built with placeholder cards. Essential before any UI wiring.
List all agents currently defined in this OpenClaw setup along with their exact roles and responsibilities so I can confirm you fully understand the structure of the system. This is critical for what we are about to build, so make sure the information is accurate and reflects the actual setup, not placeholders or assumptions.
Create the folder structure
Sets up the on-disk layout. `~/agent-dashboard/` becomes the project root. `data/` holds the SQLite database, `docs/` holds per-agent subfolders (one lowercase folder per agent) for anything those agents produce. The agent then shows you the tree for sanity-checking before any files are written.
Create the project folder structure on the VPS.
Everything goes inside ~/agent-dashboard/. Inside that, create:
- data/ — this is where the database will live
- docs/ — this is where all agent-produced content is stored
- docs/[agent-1]/ — one subfolder per agent, named in lowercase
- docs/[agent-2]/
- docs/[agent-3]/
(create one for each of my agents)
Once created, show me the full folder tree so I can confirm the structure looks right.
Save the dashboard template file
You drop the provided `index.html` template into the project. The agent saves it to `~/agent-dashboard/index.html` and then reads through it carefully — the template has hardcoded mock data for layout preview, and the agent needs to know exactly which sections are placeholders before it starts wiring live data in later steps.
I am attaching the dashboard template file. Save it to ~/agent-dashboard/index.html.
After saving it, read through the file carefully. The template currently contains mocked hardcoded data for preview purposes, but we will be replacing that with live data from our real setup, so make sure you clearly understand which parts are static placeholders and which parts will later need to be wired to actual system data.
Confirm the file is saved.
Download the dashboard template (index.html) and attach it to the prompt above — or preview it live first.
Build the Python server
Spins up the backend. `server.py` serves `index.html` at the root URL and uses SQLite at `~/agent-dashboard/data/dashboard.db`. The agent starts it and confirms it's live on the port chosen in Prompt 16. After this, you can SSH-tunnel in and see the dashboard in a browser — static still, but reachable.
Build the Python server at ~/agent-dashboard/server.py. The server should serve ~/agent-dashboard/index.html at the root URL Use SQLite for all data, stored at ~/agent-dashboard/data/dashboard.db. Start the server and confirm it is running on the port we agreed on.
Install the server as a systemd service
Foreground servers die when you log out. This prompt installs the dashboard as a permanent systemd unit so it survives reboots and auto-restarts on crash. Once done, the agent confirms the service is running and the dashboard is still accessible over the tunnel.
Install the dashboard server as a permanent system service so it starts automatically on boot and restarts if it crashes.
After installing, confirm the service is running and the dashboard is still accessible.
Lock in the page-by-page protocol
A discipline prompt. From now on, the agent only works on whatever page you explicitly name — it doesn't touch anything else, doesn't "proactively clean up" other tabs, doesn't improve the design without permission. This is the prompt that stops an over-eager agent from rewriting your whole template when you just wanted the Agents tab updated.
We will now move on to working on the pages one at a time, and it is very important that you do not make any changes or work on anything unless I explicitly instruct you to do so for a specific page
Preserve structure, layout, and design
A second-tier discipline prompt. Before any change, the agent must review the current structure and confirm the change won't break it. If there's any risk to layout or design, it flags it to you first. This prevents "helpful" regressions where the agent rewrites HTML structure to fit new data instead of adapting the data to the existing design.
Before making any changes to the dashboard, always review the current structure, layout, and design first. Ensure that whatever changes you make do not break, alter, or degrade any of these. If a change risks affecting the structure, layout, or design in any way, flag it to me before proceeding.
Add backups and a visible version number
Insurance policy. A dedicated backups folder is created (the agent tells you the exact path), and before every future change the agent snapshots the current state into that folder. On top of that, a version number is displayed on the dashboard itself — so when you're debugging "wait, did the last change actually ship?" you can see at a glance which version is live.
First, create a dedicated backups folder and tell me the full path. From that point on, before making any changes to the dashboard, always save a backup of the current state into that folder first. Also, always display the current version number visibly on the dashboard so we know which version we're working with at all times.
Wire the Agents page with real names
First live-data wiring. The template's placeholder agent cards are swapped for your actual agent names, and the number of cards is adjusted to match your real roster. No design, layout, or styling changes — just the content. If you have five agents, you end up with five cards; if you have six, six. This is the minimal first edit that proves the wiring approach works.
Start with the agents page and replace all placeholder agent entries with the actual agent names from our current setup, making sure the total number of agent cards matches exactly the number of agents we have configured, and do not change the design, layout, or styling in any way
Fill each agent card with real metrics from logs
Now the cards get populated with data from `~/.openclaw/agent-logs.db`. Every empty metric on the Mission Control cards — task counts, status, model — comes straight from the `agent_logs` table. The "Active" field gets a human-readable relative time like "2 minutes ago" or "1 hour ago", computed from the most recent log entry for that agent.
We already have an agent logging system at `~/.openclaw/agent-logs.db` (table: `agent_logs`) where every agent logs their `agent_name`, `task_description`, `model_used`, `status`, and `created_at`. Currently the agent cards on the Mission Control dashboard have all those metrics empty — use this data to fill them in for every agent. For the **Active** field, calculate how long ago the agent's most recent log entry was (e.g. "2 minutes ago", "1 hour ago").
Wire the remaining Agents-tab sections
Expands the live-data wiring to the rest of the Agents tab: task statistics, task distribution, recent activity, and model usage. Every section pulls from the database. Explicit exclusion: session management is left untouched for now — you'll handle that separately. This keeps the edit scope narrow and predictable.
Now work on the remaining sections of the agent tab so they also pull their data from our database instead of using hardcoded or placeholder values. Specifically update the task statistics section, the task distribution section, the recent activity section, and the model usage section so they are all driven by real database data from our setup. Make sure every other section in the agent tab is wired to the database consistently. Do not touch the session management part because I will handle that later.
Populate the Activity Heatmap correctly
This is a correctional prompt — written because an earlier attempt lit up every cell in the heatmap regardless of actual logs. It spells out the logic in plain terms: read the last 7 days of agent logs, extract the hour from each timestamp, count entries per agent per hour. That count is the cell intensity. Zero entries = fully dark cell. No defaults, no filler, no made-up activity. Most nights will be dark, most workdays will be bright — because the heatmap reflects reality, not aesthetics.
How to populate the Activity Heatmap using the agent logs
As you know, in our setup every agent logs its activity. Each log entry has a timestamp showing exactly when that agent ran a task. That timestamp is what you use to populate the heatmap — nothing else.
Here is what you need to do. Go into the agent log database and for each agent, look at all the log entries from the last 7 days. For each entry, extract the hour of day from the timestamp. Count how many log entries fall within each hour for each agent. That count is the intensity of that cell. If an agent has zero log entries in a given hour, that cell stays completely dark. If it has a few entries, it glows dimly. If it has many entries, it glows brightly.
That is the entire logic. The heatmap is just a visual representation of the agent log timestamps grouped by hour of day. You are not making anything up or filling in defaults — you are reading real data from real logs.
Most agents will have zero activity between midnight and 5am. Most active hours will be clustered around daytime. This is what makes the heatmap look natural and useful — because it reflects reality.
So to be clear: if a cell is dark, it means the logs show zero activity for that agent at that hour. Do not fill it with any colour. A fully lit grid like what you produced means you ignored the logs entirely and coloured every cell, which is wrong.
Add the Tasks system to the database
Introduces a proper task board. A new table is created with title, category (Work / Marketing / Development / Personal), priority (Urgent / Normal / Someday), status (todo / in_progress / done), completed flag, optional due date, notes, and timestamps. Eight realistic seed tasks (3 todo, 3 in-progress, 2 done) populate it. Full CRUD endpoints are built — including the clever auto-behavior that moving a task to "done" automatically sets the completed flag, and moving it away automatically clears it. The agent verifies with a manual create → move to done → check completed flag cycle.
Add a tasks system to the database.
Each task has a title, a category (Work / Marketing / Development / Personal), a priority (Urgent / Normal / Someday), a status (todo / in_progress / done), a completed flag, an optional due date, a notes field, and timestamps.
Seed it with 8 realistic tasks: 3 in To Do, 3 in In Progress, 2 in Done, with a mix of priorities and categories.
Build all the server endpoints the Tasks tab needs:
- Fetch all tasks, with optional category filter
- Create a new task
- Update any fields on a task — when status changes to "done" automatically set completed, when it moves away from "done" automatically clear completed
- Delete a task
- Clear all done tasks at once
Confirm all endpoints work by creating a task, moving it to done, and verifying the completed flag was set automatically.
Wire the Tasks tab to the database
The Tasks tab on the dashboard still shows mock data. This prompt strips all of that out and replaces it with a dynamic view backed by the endpoints from Prompt 29. Design is untouched — only the data layer changes. After this, adding/editing/completing a task in the UI round-trips to the database for real.
Now update the task tab on the dashboard so it uses the data from our database instead of the current hardcoded mockup data. Remove all placeholder content and make sure everything displayed in the task tab is pulled dynamically from the database you just created, reflecting the real data structure and values from our setup.Dont touch the design
Make the 7-day activity chart live
The finale. The homepage 7-day chart ditches its hardcoded numbers and starts reading from the same log table as everything else. For each of the last 7 days, it counts total entries (orange line) and completed entries (green line), producing two arrays of 7 numbers plus day labels. Chart.js handles the render: smooth tension, point markers, transparent fills, dark-themed legend at the bottom. Empty days dip to zero — not filled with fake defaults. This closes the loop: every visible surface on the dashboard is now driven by real data from your agents.
Now on the dashboard homepage, make the 7 day activity chart functional using live data instead of hardcoded values.
DATA SOURCE
The chart reads from the same activity log entries that power everything else. It does not need its own endpoint — it groups the existing log data by day.
HOW TO COMPUTE THE DATA
Take the last 7 days, from 6 days ago through today. For each day:
1. Get the date string (YYYY-MM-DD)
2. Filter all log entries whose created_at starts with that date string
3. Count the total entries — this is "Total Tasks" for that day
4. Count only entries where status is "completed" — this is "Completed" for that day
You end up with two arrays of 7 numbers each, plus 7 day labels (Mon, Tue, Wed, etc.)
THE CHART
It's a Chart.js line chart with two datasets:
- "Total Tasks" line: orange (#FF6B00), tension 0.4 (smooth curves), point radius 4, point background orange, point border #060608
- "Completed" line: green (#10B981), same styling but green
Both lines have fill: false and transparent backgrounds (no area fill under the line).
Chart options:
- responsive: true, maintainAspectRatio: false
- Legend at the bottom with light grey text (#aaaaaa), Inter font, 11px, point-style circles
- X axis: grey tick text (#666), grid lines rgba(255,255,255,0.04)
- Y axis: same, beginAtZero: true
If there are no logs for a day, the count is 0 — the line dips to zero. That's correct, not an error.
Wire the Content tab to the backend endpoints
The Content tab's layout — header, three stat cards (TOTAL DOCS, AGENTS WRITING, LATEST), the Documents list on the left, the Preview panel on the right — is already built as a template, and the server endpoints that scan `~/agent-dashboard/docs/{agent}/` (list, read, create, update, delete) are already working. This prompt does two things in order: first it seeds each agent folder with a fun, well-formatted sample markdown document so the renderer has something realistic to display, then it wires the existing UI to the existing endpoints. Stat cards count documents and distinct agent folders and surface the most recently modified title. The list sorts by most recent, auto-selects the latest doc on load, supports an All Agents filter, and a + New Document button. The preview panel renders full markdown with orange-on-dark inline code, plus star / fullscreen / download / edit / delete actions in the top-right. No layout, colours, or component structure are changed — only data flows in.
Wire up the Content tab to the existing backend endpoints.
The file system and all server endpoints are already built. As a reminder, here is exactly what was built:
The server scans ~/agent-dashboard/docs/ where each agent has their own subfolder (e.g. docs/scout/, docs/scribe/). The server reads all markdown and text files from these folders. The existing endpoints are:
- List all documents across all agent folders — returns the title (from the filename or first heading), which agent produced it, the file size, and the last modified date. Does NOT return the full body — kept lightweight.
- Read a single document's full content given the agent name and filename.
- Save/update a document's content.
- Create a new document in a specific agent's folder.
- Delete a document.
These endpoints are confirmed working. Do not touch the server or endpoints.
The frontend layout for the Content tab is also already built — the page header, the three stat cards (TOTAL DOCS, AGENTS WRITING, LATEST), the Documents list panel on the left, and the Preview panel on the right are all in place as a template. Do not rebuild the layout. Your job is to wire the existing UI to the backend so real data flows in.
---
FIRST — before wiring up the frontend, create sample markdown documents in each agent's docs folder so the page has real content to display and the renderer can be properly tested.
Create one document per agent. Each document should be a well-structured markdown file with a proper title, headings, subheadings, bold and italic text, inline code, a code block, and a short list. Make the content fun and fitting for each agent's role — write them as if each agent is introducing themselves, describing what they do, and sharing one joke related to their specialty. Around 20-30 lines each, well-formatted and realistic.
Once the sample documents are in place, wire up the frontend.
---
WIRING REQUIREMENTS:
Stat cards (top row):
- TOTAL DOCS: total count of all documents returned by the list endpoint.
- AGENTS WRITING: count of distinct agent folders that contain at least one document.
- LATEST: title of the most recently modified document, derived from the last modified date in the list endpoint response.
Documents list (left panel):
- Populate from the list endpoint.
- Each row shows: file icon, file title (truncated if long), agent name in small muted caps below the title (e.g. "SCOUT", "SCRIBE"), file size and last modified timestamp in muted text, and a star icon on the right (filled orange when starred).
- Sort by most recently modified by default.
- The currently selected file gets a subtle left orange border accent and a slightly lighter background.
- On page load, auto-select the most recently modified file and render it in the preview panel.
- "All Agents" filter dropdown in the header should filter the list by agent folder.
- "+ New Document" button should call the create endpoint and add the new file to the list.
Preview panel (right):
- Clicking a file in the left panel calls the single document read endpoint and renders it in the preview panel immediately.
- Breadcrumb at the top showing the agent folder and filename in small orange monospace text (e.g. SCOUT / FILENAME.MD), with the full file path below in muted text.
- Top-right icon row: star, fullscreen, download, edit, delete.
- Delete calls the delete endpoint and removes the file from the list.
- Edit switches the panel to an editable textarea and saves via the update endpoint on confirm.
- Star toggles the starred state on the file.
- Download saves the raw markdown locally.
- Fullscreen expands the preview panel.
- Below the breadcrumb, render the full document content as formatted HTML — headings, bold, italic, inline code, code blocks with syntax highlighting. Inline code and code keywords styled in orange on a dark background to match the dashboard aesthetic.
Do not modify the existing layout, colours, spacing, or component structure. Match the visual style already in place.
Install the Document Storage Protocol
Locks in the rule that every long-form deliverable an agent produces gets saved to its own folder under `~/agent-dashboard/docs/` as a properly-formatted markdown file — never returned inline in chat. Spells out the folder layout, the `YYYY-MM-DD_kebab-case-title.md` filename convention, the mandatory top-level heading, and the structure that makes documents render cleanly in the Content tab. Includes the post-save confirmation format so you always know exactly which agent saved what and where. Without this rule, long output gets lost in chat and never shows up in the dashboard.
Save this into your long term memory
When you produce any **long-form document** — articles, research reports, scripts, outlines, briefs, plans, transcripts, summaries, or any deliverable longer than ~15 lines — you must save it to your dedicated agent folder, not return it as a chat response.
**Folder structure:**
```
~/agent-dashboard/docs/
├── main/
├── bill/
├── scout/
├── scribe/
├── reach/
└── dev/
```
Each agent writes only to its own lowercase subfolder under `docs/`.
**Rules:**
1. **Save to your own folder only.** Main writes to `docs/main/`, Bill to `docs/bill/`, Scout to `docs/scout/`, Scribe to `docs/scribe/`, Reach to `docs/reach/`, Dev to `docs/dev/`. Never write into another agent's folder.
2. **Use markdown (`.md`)** for every long-form document. No `.txt`, no `.docx`, no inline chat dumps.
3. **Filename convention:** `YYYY-MM-DD_short-kebab-case-title.md` — e.g. `2026-05-01_competitor-scan.md`. Lowercase only, hyphens between words, no spaces, no special characters.
4. **First line must be a top-level heading** (`# Title`) that matches the document's purpose. The Content tab uses this as the display title, so make it descriptive and human-readable — not a slug.
5. **Structure the body with proper markdown:** `##` and `###` for sections, `**bold**` for emphasis, `*italic*` where useful, `` `inline code` `` for technical terms, fenced code blocks with language tags for code, and `-` bullet lists where they help. The Content tab renders all of this — write so it reads well in the preview panel.
6. **What counts as long-form** (save to folder): articles, research summaries, scripts, outreach drafts, strategy docs, meeting notes, technical guides, post-mortems, anything intended to be reread or reused.
7. **What does not** (return inline in chat): single-sentence answers, quick status updates, one-line confirmations, tool call results, error messages, conversational replies.
8. **One document per file.** Don't append unrelated work into a single mega-doc. If a task produces multiple deliverables, save each as its own file.
9. **Never overwrite silently.** If a filename collides, append `-v2`, `-v3`, etc., or use a more specific date/title.
10. **Stay in your lane.** Write content that fits your role. If a task falls outside your role, hand it off rather than writing it yourself.
11. **After saving, confirm in chat with:** your agent name, the relative path, and a one-line summary. Example: `Scout → docs/scout/2026-05-01_competitor-scan.md — competitive analysis of 6 platforms.`
This protocol exists because the Content tab in the dashboard reads directly from `docs/`. If you return long-form work in chat instead of saving it there, it doesn't show up in the dashboard, can't be previewed, edited, downloaded, or starred, and effectively gets lost.
Verify the protocol with a test document
A sanity check immediately after the protocol is installed. Each agent writes a short test document to its own folder following every rule — heading, sections, formatting, filename convention, post-save confirmation. If the test doc lands in the right folder with the right filename and shows up in the Content tab, you know the rule actually took. If not, you catch the misconfiguration before any real work depends on it.
Write one short test document and save it to your folder following the Document Storage Protocol.
Keep it brief — around 15–20 lines. Include a `# Title`, two short `##` sections, one bold phrase, one italic phrase, one inline `code` mention, and a 3-item bullet list. Content should reflect your role.
Filename: `2026-05-01_test-doc.md`
After saving, confirm with: your name, the relative path, and a one-line summary.
Advanced features — pushing the system further
With the dashboard fully wired and the document storage protocol in place, this part adds the features that turn it from a working dashboard into a proper mission control: briefing Claude Code on the project, a Discord-like chat tab so you can talk to agents straight from the browser, a live "Office" visualization that shows agents physically moving when they work, per-agent model switching, secure remote access via Tailscale, and a full mobile pass.
Brief Claude Code on the project
Switching context — from this point on, the advanced features are built using Claude Code on the VPS, not the agents themselves. This first prompt is the orientation: it explains what OpenClaw is, names the agent roster, points to the official docs, and sets expectations for how you work (direct, no padding, ask one specific question if something's ambiguous). It also makes the integration mandate explicit: match what's already built, don't rebuild it. End of the prompt forces a confirmation, so you know Claude Code has actually read it before pointing it at the codebase.
You're going to help me build out new functions on my OpenClaw Mission Control Dashboard. Before you write any code, I want you to understand the project properly.
Context:
- The dashboard is a multi-agent control panel I'm building with OpenClaw, running on a VPS.
- OpenClaw is a multi-agent system where each agent has its own identity, tools, and folder. My agents are Main, Bill, Scout, Scribe, Reach, and Dev — each with a specific role.
- The dashboard already has working tabs and a working backend. We're adding more features on top, not rebuilding what exists.
- The official OpenClaw documentation lives at https://docs.openclaw.ai/ — refer to it whenever you need to understand how OpenClaw itself works (config, tools, agent structure, etc.).
- I'll give you specific feature requests one at a time. For each one, your job is to integrate cleanly with what's already built — match the existing visual style, file structure, and patterns. Don't rebuild layouts, don't change colours, don't restructure folders unless I explicitly ask.
How I work:
- I prefer direct, professional communication. No padding, no over-explaining, no recapping what I just said.
- When you finish a task, give me a short summary of what changed and where — not a wall of text.
- If something is ambiguous, ask one specific question rather than guessing.
- If you spot a bug or a better approach while working, mention it briefly — don't silently change scope.
Confirm you've read this and you're ready for me to point you at the project folder.
Read-only project exploration
Forces Claude Code to read the codebase before writing anything. It walks the OpenClaw project folder, cross-checks the agent list against `~/.openclaw/openclaw.json` and per-agent workspace files, maps the dashboard frontend and backend, inspects the docs folder, and surfaces anything broken or inconsistent. Crucially this pass is read-only — no edits — and ends with a structured summary so you can sanity-check that Claude Code has actually understood the system before any feature work starts.
Before we touch any code, explore the OpenClaw project folder on this machine.
Walk through the directory structure and read enough of the key files to understand:
1. The overall folder layout — what lives where (config, agents, tools, dashboard frontend, dashboard backend, docs, data).
2. The list of sub-agents I have, where their identity/config files live, and what each one is responsible for. Cross-check this against what you find in `~/.openclaw/openclaw.json` and any per-agent workspace files (SOUL.md, AGENTS.md, IDENTITY.md, USER.md, MEMORY.md, HEARTBEAT.md).
3. The dashboard project itself — frontend structure, backend endpoints, how data flows between them, what tabs already exist, and the visual conventions in use (colours, fonts, component patterns).
4. The `docs/` folder where each agent stores long-form output, and the Document Storage Protocol that governs it.
5. Any scripts, tunnels, or VPS-specific setup I'm running.
When you're done, give me a short structured summary:
- Project root and key subfolders
- List of agents with their roles, in the order they appear in config
- Dashboard frontend stack and file layout
- Dashboard backend endpoints already wired
- Anything that looks broken, inconsistent, or worth flagging before we add new features
Don't make any changes. This pass is read-only — I just want you to know the codebase before we start building.
Lock in the dashboard ground rules
Tells Claude Code exactly where the dashboard lives and how it's laid out — one `server.py`, one `index.html`, one SQLite database, the `docs/` folder. Then sets the rules that every future feature has to obey: all backend logic in `server.py`, all frontend logic in `index.html`, all persistence in the existing SQLite database, no new files or second databases without explicit approval. Most importantly: every new endpoint must be wired to the frontend in the same task — no half-built features. Forces a confirmation so you know the rules are in place.
The dashboard lives at `~/agent-dashboard/`. Here's the layout you should expect:
```
~/agent-dashboard/
├── server.py — Python server, serves index.html at root and exposes the API
├── index.html — frontend (single-page dashboard, all tabs live here)
├── data/
│ └── dashboard.db — SQLite database, all dashboard data lives here
└── docs/
├── main/
├── bill/
├── scout/
├── scribe/
├── reach/
└── dev/ — one folder per agent, governed by the Document Storage Protocol
```
Before doing anything:
1. Read `server.py` end-to-end so you understand every existing endpoint, the SQLite schema, and how the frontend talks to the backend.
2. Read `index.html` end-to-end so you understand the tab structure, the visual conventions (colours, fonts, spacing), and the patterns used for fetching and rendering data.
3. Check that the server is running and on which port. If it's running, do not restart or kill it without telling me first.
4. Inspect the SQLite database at `data/dashboard.db` — list the tables and their schemas so you know what's already being persisted.
Rules going forward:
- All new backend logic goes into `server.py` unless I explicitly say otherwise. Don't introduce new files or split the server without asking.
- All new frontend logic goes into `index.html`. Don't break it into separate files unless I ask.
- All persistence goes through the existing SQLite database. Don't add a second database, don't switch to JSON files, don't add an ORM.
- Match the existing code style — same naming conventions, same indentation, same patterns for routes and DOM updates.
- When you add an endpoint, also wire the frontend to it in the same task. Don't leave half-built features.
- When you finish, tell me the port the server is on, what changed in `server.py`, what changed in `index.html`, and any new tables or columns added to the database.
Confirm you've found the project, read both files, and inspected the database. Then wait for the first feature request.
Build the Discord-like Chat tab
Turns the existing Chat tab into a real conversation interface — left sidebar of agents (Bill first, then the six specialists) with health-aware status dots, right-side message area with date dividers and bubbles, a Live SSE pill, and a context-usage bar showing session KB against the 200KB limit. Sending a message does two things at once: triggers a real `openclaw agent` turn so the agent actually processes the message, and posts a `[Dashboard]` mirror into the same Discord channel so Discord keeps history. Replies stream back over Server-Sent Events — no polling, no refresh. Specifically calls out the case-sensitivity gotcha (capitalized agent ids in `AGENTS`, lowercase in the Discord channel map), the bot-echo de-duplication, and the `ReusableTCPServer` requirement for long-lived SSE connections.
On the Agent Dashboard, I have an Chat tab, my goal is to have a **Discord-like Chat tab** to my OpenClaw agent dashboard so I can talk to each agent directly in the browser instead of opening Discord. Messages I send must trigger a real agent turn (not just post to Discord), and the agent's replies must stream back live.
The dashboard is at `~/.openclaw/workspace/agent-dashboard/` — one `index.html` and one `server.py` (plain Python `http.server`). Back both up to `.bak` before editing. Agent list, emoji, and brand colors come from the existing `AGENTS` constant in `index.html` plus `BILL` (the orchestrator) — don't hardcode. Agent→Discord channel IDs live in `/root/.openclaw/openclaw.json` under `channels.discord`.
What to build:
1. **Server endpoints** (all JSON except the stream):
- `GET /api/discord/channels` — returns the `{agent: channelId}` map.
- `GET /api/discord/messages?agent=X&after=ID&limit=N` — reads recent messages from that agent's Discord channel via the Discord REST API (bot token from openclaw.json). Used for initial backfill only.
- `POST /api/discord/send` — body `{agent, text}`. Does **two** things: (a) shell out to `openclaw agent --agent X --message "..." --channel discord --to "channel:ID" --deliver` so the agent actually processes the message; (b) post a `[Dashboard] {text}` message into the same Discord channel so Discord keeps history.
- `GET /api/discord/stream?agent=X` — **Server-Sent Events**. Hold the connection open, poll Discord for new messages on a short interval, and push each new one as an SSE `data:` event. No client polling.
2. **Chat tab UI**: Discord-style — left sidebar lists Bill first then the 6 agents (with status dot reflecting session-size health, not connection state), right side is the message area with date dividers, sent/received bubbles, and timestamps. Header shows a **Live** pill (green/amber/red = SSE connection state) and a context-usage bar (session KB vs the 200KB limit) with a Reset button. Typing animation while waiting for the reply. `Enter` sends, `Shift+Enter` newline. `Esc` clears focus.
Watch out:
- `AGENTS` uses capitalized ids (`Scout`), Discord channel map uses lowercase (`scout`) — lowercase before lookup.
- The Discord bot's own messages will echo back through the stream — de-dupe by message id so you don't show the `[Dashboard]` copy of what I just sent.
- Use `ReusableTCPServer` / `allow_reuse_address` so the SSE long-lived connections don't block port re-binds on restart.
When you're done, show me: me sending a message in the UI, the agent replying live via SSE (no page refresh), and the `[Dashboard] ...` mirror showing up in Discord. Ship it — don't check in on the approach, just flag real conflicts (e.g. openclaw.json doesn't have `channels.discord.token`).
Build the Office visualization
The Agents tab gets a live spatial view called The Office. Each agent has a fixed desk in an SVG, and a central Working Hub where they congregate when actively working. Desks have four states (live / active / recent / offline) driven by the timestamp of the agent's most recent log. Agent figures move on a state machine — idle → walking_out → at_zone → walking_back — animated smoothly between desk and hub. The dashboard detects "started working" via session file growth (polled from `/api/agent-sessions` every 3.5s) or pipeline stage changes, and detects "finished" via new rows in the `agent_logs` table. Includes fallbacks: 5-minute timeout if the completion signal is missed, and a quick out-and-back flash for tasks too fast to catch the start. Notifications fire on every transition.
On the Agent Dashboard, inside the Agents tab, there is a subsection called "The Office." I want this section to show a visual representation of my agents so I can clearly see how they are working in real time.Here is how the Office visualization on the Agents tab works. Read this carefully before making any changes — it has multiple moving parts that work together.
THE LAYOUT
The Office is an SVG with a fixed viewBox. Each agent has a "desk" — a small workstation drawn at a fixed position. In the centre of the SVG is the "Working Hub" — a shared area where agents move to when they are actively working. Each agent has a reserved seat inside the hub so they don't overlap.
DESK STATES
Each desk has a data-state attribute that controls its visual appearance. The state is set by renderOffice() based on how recently that agent logged activity:
- "live" → logged something in the last 5 minutes. Full glow, bright monitor screen, lit status dot.
- "active" → last log was 5–60 minutes ago. Moderate glow, dimmer screen.
- "recent" → last log was 1–24 hours ago. Subtle glow, faint screen.
- "offline" → no log in 24+ hours, or no logs at all. Avatar faded, no glow.
renderOffice() runs on every data refresh. It looks at ALL log entries, finds the most recent created_at timestamp for each agent, and compares that to right now to decide the state.
THE MOVEMENT LIFECYCLE
An agent's figure has a position state machine with 4 states: idle → walking_out → at_zone → walking_back → idle.
Here is what happens step by step:
1. AGENT STARTS WORKING — the dashboard detects this in one of two ways:
a. Session size growth: The dashboard polls /api/agent-sessions every 3.5 seconds. Each agent has a session file size (total_size_kb). If the size grows since the last poll, that agent just started working. The figure walks from its desk to the Working Hub.
b. Pipeline stage change: If you have a content pipeline, when the pipeline stage transitions to one assigned to an agent, that agent's figure walks to the hub.
2. WALKING OUT — the figure animates from its desk position to its hub seat using a smooth ease-out cubic animation over ~1.2 seconds. While walking, a speech bubble appears saying "Working…"
3. AT THE HUB — the figure sits in the Working Hub with its bubble visible. It stays here until the dashboard detects the agent has finished.
4. AGENT FINISHES WORKING — the dashboard detects this when a NEW row appears in the activity log (agent_logs table). Every time the logs are refreshed, renderOffice() checks for log IDs it hasn't seen before. A new log entry from an agent means that agent just completed a task. The figure walks back from the hub to its desk.
5. WALKING BACK — the figure animates back to its original desk position over ~1 second (slightly faster than walking out). The bubble briefly shows "Done: [task description]" then disappears.
6. BACK AT DESK — the figure returns to idle state. If another task starts, the cycle repeats.
FALLBACK — TIMEOUT
If an agent has been at the hub for more than 5 minutes without a log entry appearing, the dashboard assumes the task is done (or the detection missed it) and walks the agent back automatically. This prevents figures from getting stuck in the hub forever.
FALLBACK — QUICK FLASH
If a new log entry appears for an agent that is already at its desk (the dashboard didn't catch them walking out — this happens for very fast tasks), the figure does a quick out-and-back cycle: walks to the hub, pauses briefly, then walks back. This way every task completion is visible even if the "start" was missed.
HOW THE DASHBOARD KNOWS AN AGENT IS WORKING
The key signals, in order of reliability:
1. Session file growth (polled every 3.5 seconds from /api/agent-sessions) — most reliable. When an agent's OpenClaw session files grow, they are actively processing a message.
2. Pipeline stage transitions (polled every 3.5 seconds from /api/pipeline/current) — catches cron-triggered agent work that doesn't grow the session immediately.
3. Activity log entries — these confirm task COMPLETION, not start. A new row in agent_logs means the agent just finished something.
HOW THE DASHBOARD KNOWS AN AGENT IS DONE
There is only one signal: a new row in the agent_logs table. When the agent logs "completed" or "failed" after finishing a task, the dashboard sees the new row on its next poll and triggers the walk-back animation.
This is why the logging rule is critical. If an agent doesn't log after finishing a task, the dashboard won't know they're done, and the figure will stay in the hub until the 5-minute timeout kicks in.
NOTIFICATIONS
Every state transition also triggers a visual notification (a toast-like popup):
- "Start" notification when the figure walks out: "[Agent] started working"
- "Complete" notification when the figure walks back: "[Agent] completed: [task description]"
These appear regardless of which tab you're on — they're global.
WIRING IT UP
For the Office to work, the server needs to provide two things:
1. /api/agent-sessions — returns per-agent data including a total_size_kb field (session file size). The dashboard polls this every 3.5 seconds to detect when agents start working. If you don't have session files, you can derive "working" status from activity timestamps instead — any agent with a log entry less than 2 minutes old counts as currently working.
2. Activity log entries — the agent_logs table with id, agent_name, task_description, status, and created_at. The dashboard polls these and uses new IDs it hasn't seen before to trigger walk-back animations.
The SVG desk elements are already in the HTML — each one has a data-office-agent attribute matching the agent's lowercase id. The JavaScript expects DESK_POS (desk coordinates), HUB_SEATS (hub seat coordinates), and AGENT_META (agent letter, colour, label) to be defined for each agent.
Correct the Office's idle behavior
A correctional follow-up. The first build had agents auto-walking on tab load and triggering on the wrong signal. This prompt restates the correct behavior in plain terms: agents start at their desks. Walk to hub fires only when the session file actually grows (real evidence the agent is thinking). Walk back fires only on a new row in the agent logs (real evidence the agent finished). Bumps the timeout fallback from 5 to 10 minutes for missed completion signals. Short, blunt, and unambiguous — it exists to overwrite a subtly wrong implementation.
This is not how it should work the agents tab should load with the agents at their desk. This is how it should work as a tip:
Walk to hub → triggered by session size growing (agent started writing/thinking). The agent's context file size grows — we poll /api/agent-sessions every 3.5 seconds and if the file size increased since last check, that means the agent is actively writing/thinking, so they walk to the hub
Walk back → triggered by a new row appearing in agent logs in the agents database logging system — when an agent logs a completed task, that new log entry is what triggers the walk back and fires the completion notification. Safety fallback — if an agent has been at the hub for more than 10 minutes with no update, they automatically walk back (catches cases where the completion signal was missed)
Add the Model Assignment card
Adds a per-agent model picker as the last section on the Agents tab — primary model + optional fallback, one row per agent, with a status badge that flips from Saving → Saved → Default/Custom. Backed by two endpoints: `GET /api/config` returns available models, the system default, and each agent's current selection; `POST /api/agent-model` updates the agent's model in `~/.openclaw/openclaw.json` (rotating a `.bak` before every write — important because that file is the canonical agent config). Empty model means delete the override and fall back to `agents.defaults.model.primary`. Available models per agent come from each agent's own `models.json`, walked and built into `provider/model-id` strings. Replaces hand-editing JSON with a UI control while keeping JSON as the source of truth.
Add a **Model Assignment** card to my OpenClaw agent dashboard so I can pick which AI model each agent uses (plus an optional fallback) from the UI instead of editing JSON by hand. We can add this as the last section on the same agents tab
The dashboard lives at `~/.openclaw/workspace/agent-dashboard/` — one `index.html` and one `server.py` (plain Python `http.server`). Back both files up to `.bak` before you edit them.
Agent config is in `/root/.openclaw/openclaw.json`. Each agent in `agents.list` can have an optional `model` key like `{ "primary": "provider/model-id", "fallbacks": ["provider/model-id"] }`. If the key is missing, the agent uses `agents.defaults.model.primary`. Per-agent available models come from `{agentDir}/models.json` — walk each provider and build IDs as `"{provider}/{model.id}"`.
What to build:
1. **Server**: add `GET /api/config` (returns the list of available models, the default model, and each agent's current selection) and `POST /api/agent-model` (body: `{agent_id, model_id, fallbacks}`). Empty/`"default"` model_id means delete the agent's `model` key. Rotate a `.bak` of `openclaw.json` before every write.
2. **UI**: one card in the existing Monitor/Settings tab, one row per agent, with a Primary select, a Fallback select, and a status badge that flips Saving → Saved → Default/Custom on change. Match the existing dashboard styling (premium card, no motion). Use the page's `AGENTS` constant for names/emoji/color — don't hardcode.
Watch out: `AGENTS` uses capitalized ids (`Scout`), `openclaw.json` uses lowercase (`scout`) — lowercase before lookup and before sending to the server.
When you're done, show me a curl round-trip proving a change persists to `openclaw.json` and survives a page reload. Ship it — don't check in on the approach, just flag real conflicts (e.g. the JSON doesn't match this shape).
Set up Tailscale for secure remote access
Closes off the public internet exposure problem. Tailscale gets installed on the VPS, the auth flow kicks off and produces a login link you approve from your account, and after authentication the VPS is on your private Tailnet. From then on, the dashboard is reachable from your laptop or phone via the VPS's Tailscale IP — but only from devices already on your Tailnet. The prompt also asks for explicit confirmation that the dashboard isn't unnecessarily exposed publicly, which is the whole point: you keep convenience without leaving the dashboard open to the world.
Set up Tailscale on this VPS so I can securely access the Mission Control dashboard from anywhere, both on my PC and on my mobile device.
Please install and configure Tailscale on the VPS, then start the Tailscale authentication process and provide me with the login/authentication link so I can approve and connect the VPS to my Tailscale account.
After authentication, please verify that the VPS is connected to my Tailnet and confirm the Tailscale IP address. Then explain how I can use that Tailscale IP to access the Mission Control dashboard remotely from my PC or phone.
Also make sure the dashboard remains secure and is not unnecessarily exposed to the public internet.
Mobile-optimize the entire dashboard
Now that you can hit the dashboard from your phone via Tailscale, this prompt makes sure it actually looks right there. Claude Code is told to install a browser, walk every page, every tab, every subpage at small screen sizes, and fix the layout — clean spacing, readable text, properly stacked sections, usable buttons, no overflow. The non-negotiable is in the last paragraph: do not regress the desktop layout. The desktop version stays exactly as polished while the mobile version becomes fully usable.
I just realized the dashboard looks terrible on mobile, so please optimize the entire layout for mobile responsiveness. Go through every page, every tab, and every subpage of the dashboard, and make sure the layout works properly on smaller screens.
You can install and use a browser yourself to test the dashboard across different mobile screen sizes. After your review and fixes, I expect the dashboard to be fully functional and mobile-compatible, with clean spacing, readable text, properly stacked sections, usable buttons, and no broken or overflowing elements.
Very important: do not break or negatively affect the existing desktop version. The desktop layout should remain exactly as polished as it is now while the mobile version becomes fully optimized.
// You're Done
Forty-two prompts, one full AgentOS. An Orchestrator on Telegram, five persistent specialists on Discord, a live dashboard, document storage, and remote access.
If something didn't click, drop a comment on the video — or book a session and we'll walk through it together.