Architecture
Core owns coordination. Containers run turns.
Suzumio separates orchestration from execution. The core process owns project truth and scheduling; the Docker runner performs one isolated turn and exits.
Layer Map
CLI / HTTP / WebUI
|
v
Suzumio Core
Config loader
SQLite store
Message router
Artifact registry
ToolHost
Non-preemptive scheduler
|
v
Docker backend
Creates turn input JSON
Starts one container per turn
Monitors container exit
|
v
Container runner
Reads /turn/input.json
Runs mock or AI mode
Calls Suzumio /tool for project tools
Writes /turn/output.json
Core Process
The core process is the authority for project-level records. If data should be visible in CLI, HTTP, WebUI, or audit logs, it belongs in SQLite through the core store.
| Module | Responsibility |
|---|---|
config.ts | Loads YAML, resolves imports, applies extends, validates config, and renders final YAML. |
store.ts | Creates and queries SQLite tables for projects, agents, messages, reads, turns, events, tool calls, and artifacts. |
scheduler.ts | Implements the nonpreemptive-mailbox scheduling rule. |
tools.ts | Defines core tools and executes ToolHost calls with token and allowlist checks. |
server.ts | HTTP API, SSE stream, ToolHost route, and embedded WebUI. |
backend.ts | Docker container creation, bind mounts, runner input/output, and turn completion. |
runner.ts | Container entrypoint for mock or model-backed turns. |
Runner Contract
The runner receives all context through one input file and reports back through one output file. This keeps execution replaceable without changing project-state semantics.
type RunnerTurnInput = {
project: string
agent: { id: string; role: string; prompt: string; model?: string }
turn: { id: string; prompt: string }
workspace: string
controllerUrl: string
token: string
runner: RunnerConfig
tools: ToolDefinition[]
}
type RunnerTurnOutput = {
text: string
usage?: Record<string, unknown>
}
Docker Isolation
Each turn container receives a small, explicit environment:
- A bind mount for
/turncontaining input and output files. - A bind mount for the agent workspace at
/workspace. - Environment variables for project id, agent id, turn id, token, and configured model-provider key variables.
host.docker.internalmapping so the runner can call the Suzumio ToolHost on the host.
Completed containers are currently kept for early debugging. Cleanup policy should become configurable as the Docker backend hardens.
Tool Flow
Model asks for tool
runner converts model tool call
runner POSTs /tool to Suzumio
ToolHost verifies token and tool allowlist
ToolHost records tool_calls row
core tool runs against SQLite/artifact store
ToolHost records success or failure
runner returns tool output to model
The model does not receive arbitrary host tools by default. Tools are configured per agent and executed by the core ToolHost.
Message Delivery
Agents do not poll for messages. Suzumio renders unread inbound messages into the next turn prompt and records which turn consumed which message. This avoids polling loops and makes scheduling decisions auditable.
SQLite as Project Truth
Each project has one SQLite file. The container runner does not maintain the project database. Durable state must flow through output files or ToolHost calls.
| Table | Purpose |
|---|---|
projects | Project status, task, resolved config JSON, submitted report path. |
agents | Agent roster, prompts, tool allowlists, token, active turn. |
messages | Direct and channel messages. |
message_reads | Which turn consumed which inbound message. |
turns | Turn execution records and output text. |
events | Append-style event timeline. |
tool_calls | Audited tool execution records. |
artifacts | Published file artifacts with hashes and metadata. |
Why the Boundary Matters
Keeping project truth in the core runtime makes agent execution disposable. A runner can fail, be replaced, or be upgraded while the project database, message history, artifacts, and user-control surface remain stable.