Skip to content

Inter-Process Communication (IPC)

Containers communicate with the host through a file-based IPC channel. The container writes JSON files to shared directories; the host watches for filesystem events (watchdog/inotify) and processes them immediately.

Why File-Based

Containers have no network route back to the host. File mounts provide the only shared surface, so IPC uses atomic file writes (temp file + rename) to pass structured messages between the two processes without sockets, HTTP, or message queues.

Directory Layout

Each group gets its own IPC directory, mounted into the container at /workspace/ipc:

data/ipc/{group}/
├── messages/          # Container → host: outbound chat messages
├── tasks/             # Container → host: task/group management + service requests
├── responses/         # Host → container: service request responses
├── input/             # Host → container: follow-up user messages
├── merge_results/     # Host → container: git sync responses
├── current_tasks.json # Host → container: read-only task snapshot
├── todos.json         # Shared: host writes, container reads/manages
└── reset_prompt.json  # Host internal: context reset signal

Message Flow (Container → Host)

  1. Agent calls an MCP tool (e.g., send_message, schedule_task)
  2. The MCP server (running inside the container) writes a JSON file atomically to the appropriate subdirectory
  3. The host's IPC watcher (ipc/_watcher.py) detects the new file via watchdog (inotify on Linux, FSEvents on macOS)
  4. Host reads the file, authorizes the operation, executes it, and deletes the file
  5. Failed files are moved to data/ipc/errors/ for inspection
  6. On startup, the watcher sweeps all directories for files written while the process was down (crash recovery)

Atomic writes

Both container and host use the same pattern to avoid partial reads:

temp_path = filepath.with_suffix(".json.tmp")
temp_path.write_text(json.dumps(data))
temp_path.rename(filepath)          # atomic on same filesystem

The host only reads .json files, so the .json.tmp intermediate is never picked up.

Message Flow (Host → Container)

When a user sends a follow-up message while the container is already running, the host writes to data/ipc/{group}/input/. The container's agent runner watches this directory and injects the message into the active conversation via stdin.

IPC Protocol

IPC files use one of two formats depending on their tier:

Tier 1: Signals

Signals carry no payload. The host derives behavior from the signal type and the sending group.

{"signal": "refresh_groups"}
Signal Purpose God only?
refresh_groups Re-sync group metadata Yes

Tier 2: Data-carrying requests

Requests carry payload data via the type field.

Messages (messages/)

Outbound chat messages. The agent sends messages mid-run without ending its turn.

{
  "type": "message",
  "chatJid": "[email protected]",
  "text": "Working on it...",
  "groupFolder": "my-group",
  "timestamp": "2025-01-15T10:30:00Z",
  "sender": "Researcher"
}

sender — optional, used for multi-bot display in Telegram.

Tasks (tasks/)

All other operations — scheduling, group management, deployment, git sync — go through the tasks directory. The type field determines the operation:

Type Purpose God only?
schedule_task Create a recurring/one-time task No (own group)
schedule_host_job Schedule a shell command on the host Yes
pause_task Pause a task No (own tasks)
resume_task Resume a task No (own tasks)
cancel_task Delete a task No (own tasks)
register_group Register a new chat group Yes
create_periodic_agent Create a group + task + config for a periodic agent Yes
deploy Trigger a deployment (rebuild, restart) Yes
reset_context Clear session and chat history No
finished_work Signal that a scheduled task completed No
sync_worktree_to_main Merge worktree commits into main No

Authorization

The host enforces permissions based on the source group's identity. See Security Model for the full authorization matrix.

Service Requests

Service requests use the service:<tool_name> type prefix for request-response IPC. The container writes a request with a unique request_id to tasks/, and the host writes the response to responses/{request_id}.json. The container polls for the response file.

Service requests go through the security policy middleware before dispatch. Plugin-provided handlers process the request and return a result or error.

Current service tools:

  • Calendar — list_calendars, list_calendar, create_event, delete_event (CalDAV plugin)
  • Memory — save_memory, recall_memories, forget_memory, list_memories (sqlite-memory plugin)

Security Requests

Security requests use the security: type prefix. Unlike service requests (which are initiated by MCP tools), security requests originate from the agent runner's BEFORE_TOOL_USE hooks — the agent never sees them unless a command is blocked.

security:bash_check

The container's bash security hook sends this request when a command is not on the local whitelist (i.e., it is network-capable or unknown). The host evaluates the command against the session's taint state and returns a decision.

Request (container writes to tasks/):

{
  "type": "security:bash_check",
  "request_id": "uuid-...",
  "command": "curl https://example.com/api",
  "groupFolder": "my-group"
}

Response (host writes to responses/{request_id}.json):

{"decision": "allow"}

{"decision": "deny", "reason": "Cop flagged command as potential exfiltration"}

When the decision is needs_human, the host creates a pending approval (broadcast to the chat channel) and does not write a response file. The container blocks until the human approves or denies, or the 300-second timeout expires.

The security: prefix is registered as a prefix handler — all security:* IPC types route to the same handler module. This makes the namespace extensible for future security gates without additional IPC wiring.

Container-Side MCP Server

The agent interacts with IPC through MCP tools exposed by the agent tools MCP server (running inside the container). These tools validate inputs and write the appropriate JSON files. The agent never writes IPC files directly.

For the list of MCP tools available to agents, see Scheduled Tasks.