fabro/docs/public/core-concepts/agents.mdx
Bryan Helmkamp 234bd5663e
Add ACP backend support (#237)
## Summary
Implemented ACP support as a first-class Fabro backend alongside `api`
and `cli`. This adds a new `fabro-acp` crate using the official ACP Rust
crates, routes `backend=\"acp\"` for agent and prompt nodes, adds
sandbox stdio support for local/Docker/test-support paths, emits ACP
workflow events/projections, updates server steerability handling,
validation, documentation, and black-box CLI coverage.

## Test Plan
Passed strict non-live verification:
- `ulimit -n 4096 && cargo nextest run -p fabro-workflow --run-ignored
all --no-fail-fast` — 1162 passed, 0 skipped.
- `ulimit -n 4096 && cargo nextest run -p fabro-acp -p fabro-sandbox -p
fabro-workflow -p fabro-validate -p fabro-store -p fabro-server -p
fabro-cli --run-ignored all --no-fail-fast -E 'not
test(daytona_streaming_live_smoke)'` — 3125 passed.
- `cargo build --workspace` — passed.
- `ulimit -n 4096 && cargo nextest run --workspace --run-ignored all
--no-fail-fast -E 'not test(daytona_streaming_live_smoke)'` — 5666
passed.
- `cargo +nightly-2026-04-14 fmt --check --all` — passed.
- `cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D
warnings` — passed.

Live-environment tests skipped/excluded under explicit user override:
- `daytona_streaming_live_smoke` was excluded from final nextest runs
because it requires live Daytona infrastructure and `DAYTONA_API_KEY`.
- Confirmed with `env -u DAYTONA_API_KEY cargo test -p fabro-sandbox
--features daytona --test daytona_streaming_live
daytona_streaming_live::daytona_streaming_live_smoke -- --ignored
--exact --nocapture`: failed fast with `DAYTONA_API_KEY must be set to
run this live smoke test`.
2026-05-11 23:39:43 -04:00

159 lines
7.4 KiB
Text

---
title: "Agents"
description: "Core agent concepts in Fabro"
---
An agent in Fabro is an LLM session with access to tools. When a workflow reaches an agent node, Fabro creates a session, sends the prompt and prior context to the model, and lets the agent work autonomously — reading files, running commands, editing code, spawning sub-agents — until it decides the task is complete.
## The agent loop
Each agent turn follows the same cycle:
1. **Send** — Fabro sends the conversation history (system prompt, prior messages, tool results) to the LLM
2. **Receive** — The model responds with text, tool calls, or both
3. **Execute** — Fabro executes any tool calls in the sandbox and appends the results to the conversation
4. **Repeat** — If the model made tool calls, go back to step 1. If it responded with only text, the agent is done.
This loop continues until the model stops calling tools, indicating it considers the task complete. Fabro also enforces guardrails: token budgets, turn limits, and loop detection to prevent runaway agents.
## Backends
Every agent and prompt node uses a **backend** that determines how Fabro interacts with the LLM. There are three options:
### API backend (default)
Fabro manages the agent loop directly — it calls the LLM provider's API, executes built-in tools in the sandbox, and tracks file changes via tool call events. This is the default and supports the full feature set:
- [Session caching](/execution/context) via `fidelity="full"` + `thread_id`
- [Sub-agents](/agents/subagents)
- Provider failover
- All [built-in tools](/agents/tools) and [MCP](/agents/mcp) integrations
### CLI backend
Fabro delegates execution to a legacy external coding assistant CLI. The CLI tool manages its own tool loop internally — Fabro sends the prompt, waits for the CLI to finish, and tracks file changes via `git diff` before and after execution.
The CLI is selected automatically based on the node's provider:
| Provider | CLI tool |
|---|---|
| Anthropic | `claude` |
| OpenAI | `codex` |
| Gemini | `gemini` |
Fabro does not install these CLIs at runtime. Install the selected CLI in the sandbox image or run setup steps before the workflow reaches a `backend="cli"` node.
Set the CLI backend on a node with `backend="cli"` or via a [model stylesheet](/workflows/stylesheets):
```dot
implement [label="Implement", backend="cli"]
```
```
// Stylesheet
* { backend: cli; }
```
### ACP backend
Fabro can also run Agent Client Protocol (ACP) stdio agents with `backend="acp"`. ACP agents run inside the active Fabro sandbox, so local and Docker runs keep the same workspace isolation, secret forwarding, cancellation, and file-change tracking behavior as other agent stages.
Set ACP on a node with `backend="acp"` and an explicit `acp_command`:
```dot
implement [label="Implement", backend="acp", acp_command="python3 tools/fake_acp_agent.py"]
```
Fabro does not install ACP agents, Node.js, npm, or `npx` at runtime. The command must already be available in the sandbox image, repository, or setup steps. You can use `npx ...@latest` as an explicit `acp_command` if that is the behavior you want, but Fabro will treat it like any other user-supplied command.
ACP v1 does not have a portable model-selection request. Fabro records the selected provider and model in events and run projections, but model-specific ACP behavior must be encoded in the chosen command for now. ACP is supported with local and Docker sandboxes; Daytona does not expose bidirectional stdio yet, so ACP nodes fail there with an explicit unsupported-provider error.
### Comparison
| Capability | API backend | CLI backend | ACP backend |
|---|---|---|---|
| Tools | Fabro built-in tools + MCP | CLI's own tool set | ACP agent's own tool set |
| Session caching | Supported (`fidelity` + `thread_id`) | Not supported | Agent-dependent |
| Sub-agents | Supported | Not supported | Not supported through Fabro tools |
| Provider failover | Supported | Not supported | Not supported |
| File tracking | Tool call events | `git diff` before/after | `git diff` before/after |
### When to use the CLI backend
- **CLI-specific tools** — leverage tool implementations built into a specific CLI (e.g. Claude Code's computer use, Codex's sandboxed execution)
- **CLI-only models** — use models that are only available through a CLI tool, not via API
- **Existing workflows** — integrate a CLI tool you already depend on without rewriting its configuration
### When to use the ACP backend
- **Protocol adapters** — run ACP-compatible coding agents through a stable stdio protocol
- **Sandbox parity** — keep agent process execution inside Fabro's local or Docker sandbox
- **Custom agents** — use `acp_command` for a checked-in or preinstalled ACP adapter
## Tools
Agents have access to a set of built-in tools for interacting with the codebase and environment:
| Tool | Description |
|---|---|
| `shell` | Run shell commands (bash) |
| `read_file` | Read file contents with optional offset and limit |
| `write_file` | Create or overwrite a file |
| `edit_file` | Make targeted edits to an existing file |
| `grep` | Search file contents with regex patterns |
| `glob` | Find files by name pattern |
| `web_search` | Search the web |
| `web_fetch` | Fetch and summarize a URL |
Additional tools can be added via [MCP servers](/agents/mcp) for integrations like databases, APIs, or custom services.
See [Tools](/agents/tools) for the full reference.
## Prompts
The agent's behavior is shaped by its prompt — the task instructions set in the `prompt` attribute of the workflow node. Prompts can be inline strings or references to external Markdown files:
```dot
// Inline prompt
plan [label="Plan", prompt="Analyze the codebase and write a step-by-step plan."]
// External file reference
simplify [label="Simplify", prompt="@prompts/simplify.md"]
```
Fabro also injects a system prompt with context about the workflow goal, prior stage outputs, available tools, and the agent's role. See [Prompts](/agents/prompts) for details.
## Sub-agents
An agent can spawn **sub-agents** to delegate subtasks. Sub-agents run in their own session with their own tool access, and return results to the parent. This is useful for parallelizing research, isolating risky operations, or breaking complex tasks into manageable pieces.
See [Sub-agents](/agents/subagents) for details.
## Skills
Skills are reusable prompt templates that extend an agent's capabilities for common tasks — code review, test writing, refactoring, and more. They're discovered automatically from the project and can be invoked by the agent during its session.
See [Skills](/agents/skills) for details.
## Hooks
Hooks are shell commands that run in response to agent lifecycle events (e.g. before a tool executes, after a stage completes). They enable custom validation, notifications, and guardrails without modifying the workflow graph.
See [Hooks](/agents/hooks) for details.
## Further reading
<Columns cols={2}>
<Card title="Prompts" icon="message" href="/agents/prompts">
How prompts are constructed and injected.
</Card>
<Card title="Tools" icon="wrench" href="/agents/tools">
Built-in tools and custom tool registration.
</Card>
<Card title="MCP" icon="plug" href="/agents/mcp">
Extend agents with Model Context Protocol servers.
</Card>
<Card title="Sub-agents" icon="users" href="/agents/subagents">
Delegate subtasks to child agent sessions.
</Card>
</Columns>