-
Notifications
You must be signed in to change notification settings - Fork 7
Closed
Description
Parent: #204 | Phase 1: Single Rig, Single Polecat
Revised: This was previously "Cloud Agent Session Integration." The architecture now uses a single Cloudflare Container per town instead of individual cloud-agent-next sessions per agent.
Goal
A Cloudflare Container per town that runs all agent processes. The container receives commands from the DO (via fetch()) and spawns/manages Kilo CLI processes inside a shared environment. No gt/bd binaries — agents interact with gastown purely through tool calls backed by DO RPCs.
Container Architecture
cloud/cloudflare-gastown/
├── container/
│ ├── Dockerfile # Node/Bun image with Kilo CLI, git, gh CLI, tool plugin
│ ├── src/
│ │ ├── control-server.ts # HTTP server receiving commands from DO
│ │ ├── process-manager.ts # Spawns and supervises Kilo CLI processes
│ │ ├── agent-runner.ts # Configures and starts a single agent process
│ │ ├── git-manager.ts # Git clone, worktree, branch management
│ │ ├── heartbeat.ts # Reports agent health back to DO
│ │ └── types.ts
│ └── package.json
├── src/
│ ├── dos/
│ │ ├── TownContainer.do.ts # Container class extending @cloudflare/containers
│ │ └── ...existing DOs
│ └── ...existing worker code
Container Image (Dockerfile)
Installs:
- Node.js / Bun runtime
@kilocode/cli(Kilo CLI)gitghCLI (GitHub)- The gastown tool plugin (pre-installed, referenced via opencode config)
No gt or bd binaries. No Go code.
TownContainer DO (extends Container)
import { Container } from '@cloudflare/containers';
export class TownContainer extends Container {
defaultPort = 8080;
sleepAfter = '30m';
override onStart() { console.log(`Town container started`); }
override onStop() { console.log(`Town container stopped`); }
override onError(error: unknown) { console.error('Town container error:', error); }
}Control Server (port 8080, inside the container)
Accepts commands from the gastown worker via env.TOWN_CONTAINER.get(townId).fetch():
POST /agents/start — Start a Kilo CLI process for an agent
POST /agents/:agentId/stop — Stop an agent process
POST /agents/:agentId/message — Send a follow-up prompt to an agent
GET /agents/:agentId/status — Check if agent process is alive
GET /health — Container health check
POST /agents/:agentId/stream-ticket — Get a WebSocket stream ticket
Start Agent Request
interface StartAgentRequest {
agentId: string;
rigId: string;
townId: string;
role: 'mayor' | 'polecat' | 'refinery';
name: string;
identity: string;
prompt: string;
model: string;
systemPrompt: string;
gitUrl: string;
branch: string;
defaultBranch: string;
envVars: Record<string, string>;
}Process Manager
- Spawns Kilo CLI as child processes, one per agent
- Tracks process lifecycle (running, exited, killed)
- Wires up heartbeat reporting (periodically calls DO to update
last_activity_at) - Handles graceful shutdown (SIGTERM → wait → SIGKILL)
Git Manager
- Clones each rig's repo once (shared clone per rig)
- Creates isolated git worktrees per agent/branch:
/workspace/rigs/{rigId}/worktrees/{branch} - Branch naming:
polecat/<name>/<bead-id-prefix> - Multiple polecats in the same rig share the git clone but get separate worktrees
Wrangler Config Updates
DO → Container Communication
// In Rig DO or Hono route handler
const container = env.TOWN_CONTAINER.get(env.TOWN_CONTAINER.idFromName(townId));
const response = await container.fetch('http://container/agents/start', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(agentConfig),
});Polecat System Prompt
Port the core of polecat-CLAUDE.md to a system prompt template. The prompt must:
- Establish identity (agent name, rig, role)
- Explain available Gastown tools and when to use each
- Embed the GUPP principle ("work is on your hook — execute immediately, no announcements")
- Instruct on the done flow (push branch →
gt_done) - Instruct on escalation (if stuck →
gt_escalate) - Instruct on frequent commits/pushes (for container resilience)
Dependencies
- PR 1 (Rig DO)
- PR 2 (HTTP API Layer)
- PR 3 (Tool Plugin)
Acceptance Criteria
- Dockerfile with Kilo CLI, git, gh CLI, tool plugin pre-installed
-
TownContainerDO class extendingContainer - Control server with start/stop/status/health endpoints
- Process manager spawning and supervising Kilo CLI processes
- Git manager with shared clones and per-agent worktrees
- Heartbeat reporting from container to DO
- Wrangler config updated with container binding
- Polecat system prompt template
- Environment variables correctly passed to agent processes
- Integration test: DO signals container → container starts agent → agent makes tool call → DO state updates
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
{ "containers": [ { "class_name": "TownContainer", "image": "./container/Dockerfile", "instance_type": "standard-4", "max_instances": 50 } ], "durable_objects": { "bindings": [ // ...existing bindings... { "name": "TOWN_CONTAINER", "class_name": "TownContainer" } ] }, "migrations": [ { "tag": "v1", "new_sqlite_classes": ["RigDO", "TownDO", "AgentIdentityDO"] }, { "tag": "v2", "new_sqlite_classes": ["TownContainer"] } ] }