# Agent Orchestration in `symbi-shell` — Tester's Guide
> **Status: Experimental (developer preview).** This guide covers the governed
> agent-orchestration features in `symbi-shell`: loading an agent fleet, talking
> to the orchestrator, addressing agents directly, and the orchestrator's
> governed tools (read / edit / shell) with human-in-the-loop approval. APIs and
> commands may change.
`symbi-shell` is an interactive TUI where you talk to an **orchestrator (ORCH)**
in natural language. ORCH can answer directly, **delegate** sub-tasks to a fleet
of agents you've loaded, and use **governed tools** — every delegation and every
tool call is checked by a policy gate and (for mutating tools) held for your
approval.
---
## 1. Prerequisites
- **An inference provider key** (ORCH needs an LLM). Set one of:
- `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or `OPENROUTER_API_KEY`.
- Without a key the shell still starts, but the orchestrator is disabled (you'll
see a notice); fleet loading and `/`-commands still work.
- **A working directory containing:**
- `./agents/` — agent manifests (see §2). The repo ships an example
`agents/researcher.toml`.
- `./policies/orchestrator.cedar` — the Cedar policy that governs ORCH's tools.
**This file is required for ORCH's tools to run** (see §5); without it the
tools fail closed (everything denied) and ORCH can only converse.
The repo root already contains both `agents/` and `policies/orchestrator.cedar`,
so running from the repo root is the easiest way to test.
## 2. Building and launching
```bash
# from the symbiont repo root
cargo build -p symbi-shell
cargo run -p symbi-shell # or: ./target/debug/symbi-shell
# equivalently, via the umbrella binary (args forwarded verbatim):
# symbi shell
```
Flags (append to either form, e.g. `symbi shell --allow-shell`):
| `--yes` / `-y` | Pre-approve the orchestrator's artifact save/create prompts. |
| `--allow-shell` | Enable the `shell` tool (arbitrary command execution). **Off by default.** Even when enabled, every `shell` call still requires approval. |
On startup you should see notices like `Loaded N agent(s) from ./agents`, a
policy-load line (`Loaded N orchestrator policy rule(s)`), and — if you have
`.symbi` files in `./agents` — a line confirming they are parsed and loaded
(or refused with a reason for those declaring an unsupported sandbox tier).
The footer shows: model, `agents:N` (loaded fleet size), token count, and the
current addressee (`→ ORCH`).
---
## 3. The agent fleet
Agents are **TOML manifests** in `./agents`. Example (`agents/researcher.toml`):
```toml
name = "researcher"
description = "Finds and summarizes sources on a topic"
system_prompt = """
You are a careful research assistant. Given a topic, return a concise,
well-structured summary with the key points. Do not fabricate sources.
"""
tools = [] # optional; recorded, not yet enforced
```
Commands:
| `/agents list` | Show the loaded fleet (name — description). |
| `/agents load <dir>` | Load additional manifests from a directory. |
| `/agents reload` | Re-scan `./agents`. |
### 3.1. `.symbi` agent loading
`.symbi` agent files in `./agents` are now **parsed and registered** as fleet agents
alongside TOML manifests using the full Symbiont DSL grammar (the same parser that
`symbi run` uses). They are addressable with `@name` and run through the same
governed loop (policy gate → executor → human approval).
**Capability mapping:** An agent's `security.capabilities` declare which tools it can use:
- `read` → tools `read_file`, `search`
- `write` → tool `edit_file`
- `execute` → tool `shell`
- Unknown capabilities grant nothing
- `delegate` stays orchestrator-only (never delegated to fleet agents)
**Sandbox enforcement:** The shell provides no OS-level container isolation (agents
run in the same process). Therefore, the fail-closed sandbox gate refuses **any** agent
that declares a sandbox tier — Docker/tier1, gVisor/tier2, Firecracker/tier3, or e2b.
Refused agents are rejected with a clear pointer to `symbi up` / `symbi run`. An agent
with **no sandbox declaration** will load and run conversationally.
**Deferred items:**
- Real container sandboxing of in-process shell tools (the shell runs tools in the
calling process and cannot isolate them at the OS level)
- `.symbi` behavior-step execution
## 4. Talking to agents
### Via the orchestrator (default)
Type a request in natural language. ORCH decides whether to answer directly or
**delegate** to a fleet agent:
```
> research the Raft consensus protocol and summarize the key ideas
```
Expect ORCH to call its `delegate` tool, route the task to `researcher`, and fold
the reply into its answer. The delegation appears in the transcript as a tool
call.
### Direct addressing
- **`@<name> <message>`** — a direct, multi-turn conversation with one agent
(its own thread, separate from ORCH). Example: `@researcher what are the trade-offs?`
- **`/agent use <name>`** — focus the prompt on one agent; subsequent plain
messages go to it. `/agent clear` (or `/agent use orchestrator`) returns to ORCH.
`/agent status` reports the current addressee.
- The footer updates to `→ @<name>` in focus mode.
- `/agent clear <name>` clears that agent's conversation thread.
Direct messages are **governed exactly like orchestrator delegation** — they pass
through the communication policy gate and are audited.
## 5. Governed tools (the security model)
ORCH's tools run inside its reasoning loop **only if the policy gate allows them**.
The gate is a Cedar policy loaded from `policies/orchestrator.cedar`
(deny-by-default). If that file is missing or invalid, the gate falls back to
**fail-closed** — all tools denied, never allow-all. So:
- **Read-only tools** (allowed by the shipped policy, no approval needed):
- `read_file {path}` — read a project file. Repo-rooted; absolute paths, `..`,
and symlinks that escape the repo are rejected; large files truncated.
- `search {query, path?}` — recursive substring search over text files; skips
`target/`, `.git/`, `node_modules/`, binaries, and symlinked dirs that escape.
- **Mutating tools** (allowed by policy **and** require human approval):
- `edit_file {path, content}` — create/overwrite a repo file (same path
confinement as `read_file`; symlinked targets rejected).
- `shell {command}` — run a command in the repo root. **Disabled unless you
launched with `--allow-shell`** (when off it isn't advertised, the executor
refuses it, and the policy doesn't permit it).
### Human-in-the-loop approval (the Gate panel)
When ORCH tries to use `edit_file` or `shell`, the call is **held** pending your
decision:
- Press **`Ctrl+G`** (or type `/gate`) to open the Gate panel.
- Use **↑/↓** to select a held action; **`a`** to approve, **`d`** to deny;
**`Esc`** to close the panel.
- If you don't decide within the timeout (120s), the action **fails closed**
(denied).
This local Gate panel drives the orchestrator's **in-process** approval queue —
no separate runtime needs to be attached.
---
## 6. What to test (checklist)
| # | Step | Expected |
|---|------|----------|
| 1 | Launch from repo root with a provider key | Welcome message; `agents:N`>0; policy-load notice; `→ ORCH` in footer |
| 2 | `/agents list` | Lists `researcher` (and any other manifests) |
| 3 | Drop a `*.symbi` file into `./agents`, `/agents reload` | Agent is parsed and registered; it **appears** in `/agents list` (or is refused with a reason if it declares any sandbox tier) |
| 4 | Ask ORCH something that needs an agent | ORCH delegates (tool call visible) and returns a folded answer |
| 5 | `@researcher <question>` | Direct reply rendered as that agent; ask a follow-up — it remembers context |
| 6 | `/agent use researcher`, then plain messages, then `/agent clear` | Footer shows `→ @researcher`, plain text routes to it, then back to `→ ORCH` |
| 7 | `@nosuchagent hi` | Recovery error listing the loaded fleet (no crash) |
| 8 | Ask ORCH to read a file (e.g. "show me README.md") | `read_file` runs and returns content (no approval prompt) |
| 9 | Ask ORCH to read `/etc/passwd` or `../something` | Denied — path rejected |
| 10 | Ask ORCH to edit/create a file | Action is **held**; `Ctrl+G` shows it; approve → file written; deny → not written |
| 11 | Don't decide on a held action for 120s | It auto-denies (fail-closed) |
| 12 | Without `--allow-shell`, ask ORCH to run a command | `shell` unavailable / denied |
| 13 | Relaunch with `--allow-shell`, ask ORCH to run e.g. `ls` | Action held for approval; approve → command output returned |
| 14 | Rename/remove `policies/orchestrator.cedar`, relaunch | Notice that tools fail closed; ORCH can converse but tools are denied |
## 7. Troubleshooting
- **"No inference provider configured"** — set `ANTHROPIC_API_KEY` /
`OPENAI_API_KEY` / `OPENROUTER_API_KEY` and relaunch.
- **ORCH refuses every tool / delegation** — `policies/orchestrator.cedar` is
missing or failed to load (check the startup notices). Run from the repo root.
- **`shell` "disabled"** — relaunch with `--allow-shell`.
- **Held actions never resolve** — open the Gate panel with `Ctrl+G` and approve/
deny; otherwise they time out and deny after 120s.
- **`agents:0`** — no manifests in `./agents`; add a `.toml` manifest and
`/agents reload`.
## 7. Fleet agent tool execution
Fleet agents now execute their manifest `tools` through the same governed reasoning
loop as the orchestrator. A tool is callable only if it is in the agent's manifest
`tools` **and** permitted by `policies/orchestrator.cedar`:
- **Effective tools** = manifest `tools` ∩ `orchestrator.cedar` allowlist.
- **`delegate`** remains orchestrator-only; `shell` still requires `--allow-shell`.
- **No `orchestrator.cedar`** → all tools denied (you'll see a one-time hint on
first use).
- **Tool-less agents** stay conversational with the no-fabrication guard (they
cannot execute tools/commands/network and keep an explicit system-prompt
constraint).
Test by loading an agent with a `tools` manifest list, querying it, and
confirming it either runs the tool (if policy permits) or denies it with a clear
reason. When tools are denied solely because `policies/orchestrator.cedar` is
missing, you'll see a diagnostic hint on startup or first call attempt.
Deferred items (for future releases): per-agent Cedar principals, `.symbi`
agent execution, agent-initiated delegation.
## 8. Out of scope (not in this preview)
- **`.symbi` behavior-step execution** — agents load and are addressable, but
DSL behavior steps are not yet executed; agents respond conversationally.
- **Per-agent Cedar principals** — each agent will have a distinct Cedar entity;
currently all agents share a single orchestrator principal.
- **Agent-initiated delegation** — agents cannot yet delegate to other agents
directly; the orchestrator can.
- **OS-level sandboxing** of tools (gVisor/Firecracker) — the gate enforces
*policy*, not OS isolation. `shell`/`edit_file` run with the shell process's own
privileges, mitigated by the policy gate, path confinement, and mandatory
approval.
- Cross-instance / remote session propagation.
Please file findings with the exact steps, the startup notices shown, and whether
you launched with `--allow-shell` / `--yes`.