Architecture
How Suitcase works under the hood.
High-Level Overview
┌──────────────────────────────────────────────────────────────┐
│ Docker Host │
│ │
│ ┌──────────┐ ┌──────────┐ ┌─────────────────────────┐ │
│ │ Browser │ │ Discord │ │ LLM Endpoint │ │
│ │ (React) │ │ Bot │ │ (OpenAI / local / ...) │ │
│ └────┬─────┘ └────┬─────┘ └───────────┬─────────────┘ │
│ │ │ │ │
│ ▼ ▼ │ │
│ ┌──────────────────────────────┐ │ │
│ │ suitcase-web (Docker) │──────────┘ │
│ │ FastAPI, port 8000 │ │
│ │ │ │
│ │ ┌────────────────────────┐ │ │
│ │ │ Synax Bridge (Node.js)│ │ ◄── Subprocess bridge │
│ │ │ bashEnabled: true │ │ with IPC tool exec │
│ │ └────────────────────────┘ │ │
│ └──────────────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │suitcase- │ │suitcase- │ │ Installed │ │
│ │ data │ │ world │ │ CLIs │ │
│ │ (volume) │ │ (volume) │ │ gh, ffmpeg.. │ │
│ └──────────┘ └──────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────────────┘How the agent works
The Synax agent has native bash access (bashEnabled: true). It reads SKILL.md files as world context for guidance on how to use each installed CLI. There is no Python middleware between the agent and its tools — the agent calls CLIs directly via bash.
Career tools (build_evidence, collect_leads, triage_leads, generate_application, etc.) are exposed via the bridge's IPC mechanism. These are domain logic tools that bash can't handle — they talk to the SQLite database, career evidence graph, and job board APIs.
Powers System
Powers are CLIs and API integrations that can be toggled from the Setup dashboard (/setup). Each power:
- Checks for installed binaries via
which - Checks for required env vars
- Auto-installs missing packages via
apt-getwhen toggled ON - Shows inline input fields for token-requiring powers
27 powers in 11 categories. Managed at /api/powers.
Containers
suitcase-web (FastAPI + React)
The control plane. Handles:
- REST API for the React frontend
- Career profile and evidence management
- LLM configuration and verification
- Channel gateways (Discord, Telegram, web chat)
- Setup dashboard and power management
- Synax bridge (spawns Node.js subprocess for agent execution)
Built from the web target in Dockerfile. Includes all CLIs except Playwright.
suitcase-pulse
Same suitcase-web image. Wakes every SUITCASE_PULSE_INTERVAL seconds to run autonomous checks.
suitcase-runtime [profile]
Heavier container with Playwright/Chromium. Used for browser automation. Start with docker compose --profile runtime up.
State Isolation
All mutable state lives in named Docker volumes:
| Volume | Container Path | Contents |
|---|---|---|
suitcase-data | /data | SQLite DB, user profile, secrets |
suitcase-world | /suitcase_world | World files, reports, artifacts, memory, command logs |
suitcase-logs | /logs | Web and pulse logs |
Write Confinement
All writes must resolve inside suitcase_world/. Symlink escapes and parent-directory traversal are blocked.
Synax Bridge
The bridge (bridge/synax_bridge.js) is a Node.js subprocess spawned by Python:
- Receives a JSON task envelope via stdin (model config, task, context, tools)
- Instantiates a SynaxRuntime with
bashEnabled: true - Executes the task, streaming events to stderr
- For IPC tool calls, sends requests to stdout → Python executes → returns via stdin
- Writes final result as a JSON line to stdout
World System
Suitcase maintains a living world directory (Docker volume):
| File | Purpose |
|---|---|
WORLD.md | World laws — sandbox boundaries, safety rules |
SOUL.md | Voice, personality, boundaries, trust principles |
SELF.md | Mutable self-model — operating style, capabilities |
USER.md | What Suitcase knows about you |
These files are seeded on first boot, loaded as runtime context, and evolved through use. See World & Self Model.
Model Choice & Security
Default: OpenAI with gpt-4o (chat/trusted/vision) and gpt-4o-mini (fast). Compatible modes work with any OpenAI-compatible endpoint.
See Sandboxing & Security for details.