5.8 KiB
English | 日本語
Architecture Overview
MAESTRO is an agent orchestrator that runs the tasks a user submits with LLM-driven workflows (Pieces). For a code map aimed at contributors, see also ../AGENTS.md.
Execution flow
UI (POST /api/local/tasks)
→ bridge/server.ts (Express API)
→ Repository (SQLite: enqueue into the jobs table)
→ Worker.poll() picks up queued jobs
→ piece-classifier.ts: the LLM classifies the task and selects a Piece
→ piece-runner.ts: reads pieces/*.yaml and runs the movements in order
→ agent-loop.ts: the ReAct loop for one movement (LLM ↔ tool calls)
├─ intermediate transition: the transition tool
└─ termination: the complete tool (success / aborted / needs_user_input)
→ job complete: update DB + post a progress comment. Deliverables go to workspace/output/
- API intake —
bridge/server.tsreceives the task and registers it in thejobstable asqueuedvia theRepository. - Worker —
worker.tspolls the DB and picks up jobs matching itsprofiles/task_classes(multiple workers run in parallel). - Classification —
piece-classifier.tspasses the task body and the descriptions of all Pieces to the LLM and chooses the best-fit Piece. - Piece execution —
piece-runner.tsiterates through the Piece's movements in order. Feedback from a verify movement is carried over to the next execute, and lessons between movements accumulate viatransition.lessons. - ReAct loop —
agent-loop.tsshuttles between the LLM and tools within one movement.ContextManagertracks token usage from the LLM'susageand fires warn / prompt / force_transition at thresholds (70/85/95%).
Piece and Movement
- Piece =
pieces/*.yaml. Composed of amovementsarray. - Each Movement has
allowed_tools(the tools presented to the LLM),edit(whether Write/Edit is allowed), andrules(transition conditions). Tools outsideallowed_toolsare invisible to the LLM. - Transitions: an intermediate hop uses
transition(only the destinations listed inrules[].nextare selectable); termination usescomplete.complete.resultis the only final output visible to the user. default_nextis an engine-internal sentinel (forced transition on context overflow, fallback at the ASK limit).- Progressive pressure: as consecutive revisits to the same movement increase, warnings are injected, and exceeding the threshold triggers ABORT.
Tool runtime
Tools are a set of modules in src/engine/tools/*.ts. tools/index.ts loads and dispatches them dynamically. Each tool has a one-line description (kept concise because it rides on every LLM call), and detailed instructions live in docs/tools/<name>.md (fetched with ReadToolDoc). For the main modules, see the list in ../AGENTS.md.
Read-type tools run in parallel. Write/Edit is only presented when the movement has edit: true, and writes are mostly limited to workspace/output/.
Bash sandbox
The agent's Bash execution is isolated with the bwrap sandbox when available:
- Filesystem: only the task's workspace is rw-bound,
/usretc. are ro, and other tasks' workspaces and the host/homeare invisible. - Environment variables:
--clearenv+ injecting only a minimal allowlist (secret env vars are invisible from inside the sandbox). - Network: blocked with
--unshare-net(outbound communication is consolidated into WebFetch/MCP with SSRF guards). - Each Bash call gets an independent sandbox (volatile
/tmp, a fresh namespace each time). Only the workspace persists.
safety.bash_sandbox selects the mode (auto/always/off). When bwrap is absent, it falls back to a hardened fallback (an exec with a command allowlist + path-scope checks + env scrubbing). Runtime pip/npm install are rejected in all modes, and Python packages are pre-baked from runtime/python-requirements.txt. For details, see operations/bash-sandbox-provisioning.md.
Workspace structure (during job execution)
{worktree_dir}/local/{taskId}/
input/ where uploads and DownloadFile saves go
output/ deliverables (the main place where Write/Edit is allowed)
logs/ activity.log / various histories
subtasks/ results from SpawnSubTask
skills/ skill files materialized by ReadSkill
Database
SQLite (better-sqlite3). db/schema.sql is the initial schema. Additional columns are applied idempotently in db/migrate.ts
with the pattern PRAGMA table_info → existence check → ALTER TABLE ADD COLUMN
(no version-management table is used). Main tables: jobs / local_tasks /
local_task_comments / audit_log, and others.
Job lifecycle
queued → dispatching → running → succeeded / failed / waiting_human (waiting for an ASK answer) / waiting_subtasks (waiting for parallel subtasks). On failure, retry re-queues it (up to retry.max_attempts times).
Optional subsystems
- LLM Gateway (
src/gateway/) — exposes MAESTRO itself as an OpenAI-compatible LLM proxy (virtual keys, budgets, Prometheus metrics). For sharing across multiple GPUs/teams. Its env vars and connection type use the historicalAAO_*/aao_gatewayprefixes. - MCP — Model Context Protocol server integration (
MCP_ENCRYPTION_KEYrequired). - Reflection — the LLM automatically updates user memory after each job completes (OFF by default, revertible).
- Authentication — Google/Gitea OAuth via Passport (optional). A
private/org/publicvisibility model. - Scheduler — cron-expression scheduled tasks.
Frontend
React + Vite + TailwindCSS + @tanstack/react-query. ui/src/App.tsx is the root. A two-column (list + detail) layout handles the task list, schedule, settings, and skill/Piece management.