Skip to content

feat(gastown): add cloud-native nudge system for reliable agent message delivery#1079

Merged
jrf0110 merged 2 commits intomainfrom
1032-cloud-native-nudge-system
Mar 18, 2026
Merged

feat(gastown): add cloud-native nudge system for reliable agent message delivery#1079
jrf0110 merged 2 commits intomainfrom
1032-cloud-native-nudge-system

Conversation

@jrf0110
Copy link
Copy Markdown
Contributor

@jrf0110 jrf0110 commented Mar 12, 2026

Summary

  • Adds a real-time nudge system for time-sensitive agent-to-agent communication, complementing the existing mail system which is formal and persistent. Nudges support three delivery modes: wait-idle (delivers at next idle moment), immediate (pushes directly via container), and queue (with TTL expiry).
  • Full vertical slice: new agent_nudges SQLite table in TownDO, HTTP endpoints for queueing/fetching/marking nudges, client methods for both polecat and mayor agents, gt_nudge tool for both agent types, and dashboard UI for sending/inspecting nudges.
  • Replaces the patrol system's GUPP violation mail-based warnings with nudges for faster delivery to stuck agents. The process-manager now checks for pending nudges on session.idle events before deciding to exit, with a configurable idle timeout (default 2 min).

Closes #1032

Verification

  • Polecat reports: typecheck passed
  • Polecat reports: prettier passed
  • Polecat reports: eslint passed
  • Refinery code review: architecture, correctness, security, style

Visual Changes

N/A

Reviewer Notes

  • Minor: handleNudgeDelivered in rig-agents.handler.ts uses _params to silence an unused-variable lint warning rather than using the rigId/agentId for authorization. The nudge_id is a UUID so the practical risk is low, but a future improvement could verify the nudge belongs to the requesting agent.
  • Minor: The dashboard sendNudge() function sends a source_agent_id field in the request body that the API schema silently strips — the actual source is derived from the JWT. Cosmetic only.
  • The merge resolved conflicts in 6 files (client.ts, mayor-tools.ts, mayor-tools.test.ts, process-manager.ts, Town.do.ts, gastown.worker.ts). The conflict resolutions kept both sides' additions and are clean.
  • This is the largest change in the batch (13 files, ~892 lines added) — the core behavioral change is in process-manager.ts where session.idle no longer terminates non-mayor agents unconditionally. Agents now stay alive checking for nudges, consuming container resources longer — monitor container memory in production.

Comment thread cloudflare-gastown/src/dos/Town.do.ts Outdated
Comment thread cloudflare-gastown/src/dos/town/patrol.ts Outdated
Comment thread cloudflare-gastown/src/ui/dashboard.ui.ts
@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot Bot commented Mar 12, 2026

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Fix these issues in Kilo Cloud

Overview

Severity Count
CRITICAL 0
WARNING 3
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
cloudflare-gastown/src/handlers/rig-agents.handler.ts 304 handleNudge() accepts any target_agent_id without verifying that the target agent belongs to :rigId, so agents can inject nudges across rigs within the same town.
cloudflare-gastown/src/handlers/rig-agents.handler.ts 327 handleNudgeDelivered() marks rows by nudge_id alone, so an authenticated agent can acknowledge another agent's queued nudge and silently drop it.
cloudflare-gastown/src/ui/dashboard.ui.ts 1007 The Deliver Now button interpolates JSON.stringify(n.message) directly into onclick, producing invalid HTML/JS.
Other Observations (not in diff)

N/A

Files Reviewed (13 files)
  • cloudflare-gastown/container/plugin/client.ts - 0 issues
  • cloudflare-gastown/container/plugin/mayor-tools.test.ts - 0 issues
  • cloudflare-gastown/container/plugin/mayor-tools.ts - 0 issues
  • cloudflare-gastown/container/plugin/tools.ts - 0 issues
  • cloudflare-gastown/container/src/control-server.ts - 0 issues
  • cloudflare-gastown/container/src/process-manager.ts - 0 issues
  • cloudflare-gastown/src/db/tables/agent-nudges.table.ts - 0 issues
  • cloudflare-gastown/src/dos/Town.do.ts - 0 issues
  • cloudflare-gastown/src/dos/town/patrol.ts - 0 issues
  • cloudflare-gastown/src/gastown.worker.ts - 0 issues
  • cloudflare-gastown/src/handlers/mayor-tools.handler.ts - 0 issues
  • cloudflare-gastown/src/handlers/rig-agents.handler.ts - 2 issues
  • cloudflare-gastown/src/ui/dashboard.ui.ts - 1 issue

Reviewed by gpt-5.4-20260305 · 1,084,093 tokens

jrf0110 and others added 2 commits March 18, 2026 16:46
…ge delivery

Replaces fire-and-hope mail push with a nudge queue that guarantees delivery.
Adds agent_nudges table and TownDO nudge queue methods (queueNudge,
getPendingNudges, acknowledgeNudge). Non-mayor agents enter idle-but-available
state on session.idle instead of exiting, checking for pending nudges before
terminating. Adds gt_nudge tool for inter-agent messaging, nudge() client
method, and handleNudge worker endpoint. Patrol functions use queueNudge
instead of sendMail for time-sensitive messages. Dashboard shows pending
nudge counts.

Closes #1032
@kilo-code-bot kilo-code-bot Bot force-pushed the 1032-cloud-native-nudge-system branch from 71682e5 to 2193c27 Compare March 18, 2026 16:59
);
const townId = c.get('townId');
const town = getTownDOStub(c.env, townId);
const nudgeId = await town.queueNudge(parsed.data.target_agent_id, parsed.data.message, {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Cross-rig nudge targeting is not blocked

handleNudge() forwards target_agent_id straight to queueNudge() without checking that the target agent exists in params.rigId. Auth only proves the caller belongs to the source rig, so an agent in rig A can hit /rigs/A/nudge and inject a message into an agent from rig B in the same town. Please load the target agent first and reject the request unless its rig_id matches the route.

}
const townId = c.get('townId');
const town = getTownDOStub(c.env, townId);
await town.markNudgeDelivered(parsed.data.nudge_id);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Any agent can acknowledge another agent's queued nudge

This marks the row delivered by nudge_id alone and ignores params.agentId. An authenticated agent can call its own /agents/:agentId/nudge-delivered route with someone else's nudge_id, which removes that other agent's pending nudge before it is ever injected. Verify that the nudge belongs to params.agentId (and ideally the same rig) before updating it.

@jrf0110 jrf0110 changed the title feat(gastown): add cloud-native nudge system feat(gastown): add cloud-native nudge system for reliable agent message delivery Mar 18, 2026
@jrf0110 jrf0110 merged commit 4903a4b into main Mar 18, 2026
18 checks passed
@jrf0110 jrf0110 deleted the 1032-cloud-native-nudge-system branch March 18, 2026 17:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cloud-native nudge system — reliable real-time message delivery to agents

2 participants