Steward is designed as a modular, layered system optimized for AI agent coordination.
Steward runs as a standalone Phoenix web application (port 4001). It exposes MCP tools (acs_* prefix) that AI agents call directly. The system uses ETS for fast in-memory caching with a PostgreSQL (production) or SQLite3 (development) database for persistence. A background sweeper handles auto-release of stale tasks and locks. The MCP Gateway routes agent tool calls to internal Elixir handlers or external REST APIs via HTTP bridge.
The outermost layer. All agent interactions flow through the MCP Gateway. Tool definitions are stored as YAML files and can be hot-reloaded without restarting the server. The gateway supports two handler types: internal Elixir modules (compiled) and external REST endpoints (HTTP bridge).
The central coordination logic, built with Elixir OTP. Key subsystems:
Three-tier storage strategy:
The full lifecycle of an agent interaction:
## Agent → ACS tool call flow ##
Agent──acs_create_work──▶MCP Gateway
│
▼
Router (YAML-defined)
│
┌──────────┼──────────┐
▼ ▼ ▼
TaskMgr LockMgr Memory
│ │ │
▼ ▼ ▼
┌─────────────────────────────┐
│ ETS Cache Layer │
└──────────┬──────────────────┘
▼
┌──────────────────────┐
│ PostgreSQL / SQLite │
└──────────────────────┘1. Agent → acs_create_work(agent_id, title, file_paths)
→ Task created with status "todo"
→ Similarity check against existing tasks
→ Returns task_id
2. Agent → acs_claim_work(agent_id, task_id)
→ Task status → "in_progress"
→ locked_by → agent_id
→ auto_release_at → now + 10min
→ Returns task + guidance packet
3. Agent → acs_lock_file(agent_id, task_id, "lib/foo.ex")
→ File lock created (unique constraint)
→ Safe to edit
4. Agent → acs_save_memory(kind, title, content, scope_path)
→ Memory created with status "proposed"
→ Searchable by other agents
5. Agent → acs_release_work(agent_id, task_id)
→ Task status → "done"
→ Locks released for this task
→ Returns feedback prompt
6. Agent → acs_submit_task_feedback(task_id, learned_for_agents)
→ Knowledge memories auto-generated
→ Task lifecycle complete| Layer | Technology | Notes |
|---|---|---|
| Language | Elixir 1.17+ | Functional, fault-tolerant |
| Web framework | Phoenix 1.8.3 | Real-time, productive |
| LiveView | 1.1 | Real-time UI without JS |
| HTTP server | Bandit 1.5 | Fast, modern HTTP server |
| Database (dev) | SQLite3 (ecto_sqlite3 0.22) | Zero-config local dev |
| Database (prod) | PostgreSQL (postgrex 0.19) | Production-grade persistence |
| PubSub | Phoenix PubSub 2.2 | Agent wake/sleep notifications |
| Caching | ETS (Erlang Term Storage) | In-memory, fast lookups |
| LLM client | Req 0.5 + ReqLLM 1.0 | HTTP client for LLM providers |
| YAML parsing | yaml_elixir 2.9 | Tool definitions |
| CSS | Tailwind CSS 3.4.3 | Utility-first CSS |
Steward supports multiple independent clusters. Each cluster is identified by ACS_CLUSTER_NAME and maintains its own isolated task, lock, and memory namespace. This enables separate environments for development, staging, and production — or independent clusters per team within the same organization.
steward_acs/ ├── config/ # Environment configs (dev, prod, test, runtime) ├── lib/ │ ├── acs.ex # Public API module │ ├── acs/ # Core logic: tasks, locks, memory, MCP, cognition │ ├── acs_web/ # Phoenix web layer + LiveView dashboard │ └── mix/tasks/ # Mix tasks (keys, cognition, meta-harness) ├── priv/ │ ├── acs_memory/ # Canonical YAML memory files │ └── repo/migrations/ ├── test/ ├── assets/ ├── Dockerfile ├── docker-compose.yml # Local dev (SQLite, port 4001) ├── docker-compose.remote.yml # Remote prod (PostgreSQL, Caddy TLS) ├── docker-compose.cloudflare.yml # Cloudflare deployment variant ├── .env.example # Dev env template ├── .env.remote # Remote env template ├── Caddyfile # TLS config for remote ├── AGENTS.md # Agent coordination rules ├── AGENTS_STEWARD.md # Agent steward instructions └── mix.exs