Problem
When sending a message to the mayor (e.g., "update the readme"), the agent completes immediately without calling any tools (gt_sling, gt_list_rigs, etc.). No beads are created, no work is delegated.
Root Cause
The gastown plugin's createMayorClientFromEnv() requires four env vars: GASTOWN_API_URL, GASTOWN_SESSION_TOKEN, GASTOWN_AGENT_ID, GASTOWN_TOWN_ID. If any is missing, it throws, and the plugin fails to register tools entirely.
In local dev, GASTOWN_JWT_SECRET is bound via secrets_store_secrets in wrangler.jsonc. This uses the Cloudflare Secrets Store, which may not be available in local development. When resolveJWTSecret() returns null:
mintMayorToken() returns null
GASTOWN_SESSION_TOKEN is never set in envVars
kilo serve starts without the token in its env
- The gastown plugin calls
createMayorClientFromEnv(), which throws
- The plugin fails to load — zero mayor tools are registered
- The LLM receives a system prompt describing tools that don't exist
- With no tools available, the LLM responds conversationally and completes immediately
Evidence
- Wrangler logs show
POST /mayor/completed arriving seconds after POST /mayor/message
- No
POST /api/rigs/.../sling or tool-related requests from the mayor
- Streamed events show
session.error followed by immediate session.idle and agent.exited
Fix Options
- Add a
.dev.vars file in cloudflare-gastown/ with GASTOWN_JWT_SECRET=<dev-secret> so it's available in local dev
- Add a fallback in
mintMayorToken() that uses a hardcoded dev secret when ENVIRONMENT === 'development'
- Log the error — currently the plugin failure is silent. Add a console.error when
createMayorClientFromEnv() throws so it's obvious in logs
Related
Problem
When sending a message to the mayor (e.g., "update the readme"), the agent completes immediately without calling any tools (gt_sling, gt_list_rigs, etc.). No beads are created, no work is delegated.
Root Cause
The gastown plugin's
createMayorClientFromEnv()requires four env vars:GASTOWN_API_URL,GASTOWN_SESSION_TOKEN,GASTOWN_AGENT_ID,GASTOWN_TOWN_ID. If any is missing, it throws, and the plugin fails to register tools entirely.In local dev,
GASTOWN_JWT_SECRETis bound viasecrets_store_secretsin wrangler.jsonc. This uses the Cloudflare Secrets Store, which may not be available in local development. WhenresolveJWTSecret()returns null:mintMayorToken()returns nullGASTOWN_SESSION_TOKENis never set inenvVarskilo servestarts without the token in its envcreateMayorClientFromEnv(), which throwsEvidence
POST /mayor/completedarriving seconds afterPOST /mayor/messagePOST /api/rigs/.../slingor tool-related requests from the mayorsession.errorfollowed by immediatesession.idleandagent.exitedFix Options
.dev.varsfile incloudflare-gastown/withGASTOWN_JWT_SECRET=<dev-secret>so it's available in local devmintMayorToken()that uses a hardcoded dev secret whenENVIRONMENT === 'development'createMayorClientFromEnv()throws so it's obvious in logsRelated