-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Parent: #204 | Phase 1
⚠️ This is the single highest-priority remaining issue. Without tools, the Mayor is a chatbot that can't do anything. The entire chat-first product vision depends on the Mayor being able to delegate work viagt_sling. Until this lands, the product doesn't function.
Goal
Give the Mayor agent tools to delegate work across rigs. Without tools, the mayor is just a chatbot. With tools, it becomes the town coordinator described in the Gastown spec.
Tools
| Tool | Description | Proxies to |
|---|---|---|
gt_sling |
Sling a task to a polecat in a specific rig | RigDO.slingBead(rigId, ...) |
gt_list_rigs |
List all rigs in the town | GastownUserDO.listRigs(townId) |
gt_list_beads |
List beads in a rig (filterable by status) | RigDO.listBeads(filter) |
gt_list_agents |
List agents in a rig | RigDO.listAgents(filter) |
gt_mail_send |
Send mail to an agent in any rig | RigDO.sendMail(...) |
(gt_convoy_create deferred until convoy system lands in #220)
Implementation
The Mayor runs as a kilo serve session in the container. It needs the Gastown plugin loaded with mayor-specific tools. Two approaches:
Option A: Extend the existing plugin (Recommended)
The Gastown plugin at container/plugin/ already loads for all agents. Add mayor-specific tools that are only registered when GASTOWN_AGENT_ROLE=mayor env var is set. The tools call the Gastown worker API using the Mayor's JWT (which has townId scope, not rigId scope).
Option B: Separate mayor plugin
A second plugin loaded only for the mayor. More isolation but more packaging complexity.
Worker-side: Mayor tool routes
New handler file src/handlers/mayor-tools.handler.ts:
POST /api/mayor/:townId/tools/sling → creates bead in target rig, assigns polecat
GET /api/mayor/:townId/tools/rigs → lists all rigs in the town
GET /api/mayor/:townId/tools/beads → lists beads (cross-rig fan-out)
GET /api/mayor/:townId/tools/agents → lists agents (cross-rig fan-out)
POST /api/mayor/:townId/tools/mail → sends mail to agent in any rig
Auth: Mayor JWT validated by townId match. No rigId constraint (mayor is cross-rig).
Mayor System Prompt
The system prompt must:
- Describe the mayor's role as town coordinator (reference Gastown architecture)
- List available rigs, their repos, and their purposes
- Describe each tool with input/output schemas and when to use it
- Explain the conversational model: respond directly for questions, delegate via
gt_slingfor work - Instruct non-blocking delegation: when slinging work, respond immediately to the user ("I've assigned Toast to work on that") — don't wait for the polecat to finish
- Follow the Propulsion Principle (GUPP)
Dependencies
- [Gastown] PR 8: MayorDO — Town-Level Conversational Agent #338 (MayorDO — town-level conversational agent) ✅
Acceptance Criteria
- Mayor-specific tools in the Gastown plugin (gt_sling, gt_list_rigs, gt_list_beads, gt_list_agents, gt_mail_send)
- Worker routes for mayor tool endpoints with cross-rig fan-out
- Mayor system prompt with tool descriptions and delegation instructions
- Mayor JWT auth scoped to townId (no rigId restriction)
- End-to-end: user sends message → Mayor calls gt_sling → polecat dispatched → user sees result in dashboard
- Mayor responds conversationally about delegation (non-blocking UX)