Reorganize docs nav: merge Server Mode into Deployment, move Comparison and Dark Factory

- Merge core-concepts/server-mode into administration/deploy-server
- Move Comparison from Getting Started to Reference
- Move Dark Factory from Getting Started to Core Concepts
- Update all internal links to server-mode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-14 15:39:08 -04:00
parent 25ec842a7f
commit 68b088d322
No known key found for this signature in database
6 changed files with 147 additions and 156 deletions

View file

@ -1,8 +1,145 @@
---
title: "Server Deployment"
description: "Deploy the Fabro server to production"
title: "Server Mode"
description: "Run Fabro as an API server with a web UI, concurrent runs, and team access"
---
<Warning>
This guide is coming soon. Deployment guides are currently in development.
Server mode is in private early access. Contact [bryan@qlty.sh](mailto:bryan@qlty.sh) if you're interested in trying it.
</Warning>
Fabro has two modes: **standalone** and **server**. Standalone mode (`fabro run`) executes a single workflow synchronously in your terminal. Server mode (`fabro serve`) starts an HTTP API that queues runs, streams events, and serves a web UI — so you can close your laptop and let workflows run.
Both modes use the same workflow engine, the same DOT files, and the same sandbox providers. The difference is how you interact with them.
## Standalone vs. server mode
| | Standalone | Server |
|---|---|---|
| **Command** | `fabro run workflow.fabro` | `fabro serve` |
| **Best for** | Local development, one-off runs, CI/CD | Production, team use, running at scale |
| **Execution** | Synchronous, one run per process | Asynchronous, queued with configurable concurrency |
| **Human-in-the-loop** | Terminal prompts | Web UI or HTTP endpoints |
| **Events** | Printed to stderr | Streamed via SSE |
| **Persistence** | Checkpoint files only | SQLite database + checkpoint files |
| **Web UI** | Not available | Full React interface |
| **Authentication** | None | JWT and/or mTLS |
## Starting the server
```bash
fabro serve
```
This starts the API on `127.0.0.1:3000` by default. To also run the web UI:
```bash
fabro serve # API on port 3000
cd apps/fabro-web && bun run dev # Web UI on port 5173
```
Common flags:
| Flag | Default | Description |
|---|---|---|
| `--port` | `3000` | Port to listen on |
| `--host` | `127.0.0.1` | Host address to bind to |
| `--model` | — | Override default LLM model |
| `--sandbox` | — | Override default sandbox provider |
| `--max-concurrent-runs` | `5` | Maximum concurrent run executions |
See [Server Configuration](/administration/server-configuration) for the full `server.toml` reference.
## Submitting runs
In server mode, workflows are submitted via the REST API and executed in the background:
```bash
curl -X POST http://localhost:3000/runs \
-H "Content-Type: application/json" \
-d '{"workflow": "implement-feature", "goal": "Add user authentication"}'
```
The server returns immediately with a run ID. A background scheduler promotes queued runs to `Running` in FIFO order, up to the concurrency limit.
## Run lifecycle
1. **Submit** — `POST /runs` creates the run with status `Queued`.
2. **Schedule** — The scheduler picks up queued runs up to `max_concurrent_runs`.
3. **Execute** — The engine walks the graph, streaming events to all subscribers.
4. **Complete** — The run transitions to `Completed`, `Failed`, or `Cancelled`.
## Web UI
The web UI connects to the API server and provides:
- **Runs board** — Monitor all active runs organized by status
- **Run detail** — Real-time stage progress, event stream, diffs, and usage stats
- **Start new run** — Submit workflows from the browser
- **Human-in-the-loop** — Answer agent questions through the web interface
- **Workflows** — Browse available workflows, view their graphs, and see run history
- **Insights** — SQL-based analysis across runs via DuckDB
<Frame caption="The Runs board shows all active runs organized by status.">
<img src="/images/web/runs-board.png" alt="Fabro web UI Runs board with Working, Pending, Verify, and Merge columns" />
</Frame>
<Frame caption="The run detail view shows stage progress alongside the workflow graph.">
<img src="/images/web/run-overview.png" alt="Fabro web UI run detail showing stages and workflow graph" />
</Frame>
## Event streaming
The API streams run events via [Server-Sent Events (SSE)](/api-reference/runs#get-events). Every stage start, LLM call, tool invocation, and edge selection is emitted as a structured JSON event. Any HTTP client that supports SSE can subscribe — the web UI is just one consumer.
## Human-in-the-loop
In server mode, human-in-the-loop questions are served over HTTP instead of terminal prompts. The engine blocks the current stage until an answer is submitted, then continues execution. See the [Human-in-the-Loop API reference](/api-reference/human-in-the-loop) for the polling and answer endpoints.
## Authentication
Server mode supports two authentication strategies, configurable in `server.toml`:
- **JWT** — EdDSA-signed bearer tokens. Used by the web UI. See [API Overview](/api-reference/overview#jwt-bearer-token) for token format.
- **mTLS** — Mutual TLS with client certificates. Used for service-to-service communication. See [API Overview](/api-reference/overview#mtls-mutual-tls) for setup.
Both strategies can be enabled simultaneously — the first successful match wins.
## Demo mode
Send the `X-Fabro-Demo: 1` header on any API request to get static mock data with authentication disabled. The web UI enables this automatically with the `FABRO_DEMO=1` environment variable. This lets you explore the UI without API keys or real workflow execution. See [Demo Mode](/api-reference/demo-mode) for details.
## Pointing the CLI at a server
The CLI can delegate commands to a running Fabro server instead of executing locally. Set `mode = "server"` in `~/.fabro/cli.toml`:
```toml title="cli.toml"
mode = "server"
[server]
base_url = "https://fabro.example.com:3000"
```
Or use the `--mode` flag:
```bash
fabro --mode server --server-url https://fabro.example.com:3000 models list
```
This applies to commands like `fabro models list`, `fabro llm chat`, and `fabro exec`. See [CLI Configuration](/reference/cli-configuration#mode) for the full options including mTLS setup.
## Next steps
<Columns cols={2}>
<Card title="Server Configuration" icon="gear" href="/administration/server-configuration">
Full server.toml reference — authentication, TLS, run defaults, and more.
</Card>
<Card title="Deploy to Railway" icon="train" href="/administration/deploy-railway">
Step-by-step guide for deploying Fabro on Railway.
</Card>
<Card title="API Reference" icon="code" href="/api-reference/overview">
REST API for submitting runs, streaming events, and managing resources.
</Card>
<Card title="How Fabro Works" icon="lightbulb" href="/core-concepts/how-fabro-works">
The workflow engine that powers both modes.
</Card>
</Columns>

View file

@ -16,7 +16,7 @@ Fabro has two interfaces, both backed by the same workflow engine:
- **Standalone mode** (`fabro run`) — Run a single workflow synchronously in your terminal. Best for local development, one-off runs, and CI/CD.
- **Server mode** (`fabro serve`) — Start an HTTP API server with a web UI, concurrent run scheduling, and team access. Best for production use and running at scale.
Both modes parse the same DOT files, use the same execution engine, and support the same sandbox providers. See [Server Mode](/core-concepts/server-mode) for a detailed comparison and setup guide, or [Architecture](/reference/architecture) for internals.
Both modes parse the same DOT files, use the same execution engine, and support the same sandbox providers. See [Server Mode](/administration/deploy-server) for a detailed comparison and setup guide, or [Architecture](/reference/architecture) for internals.
## Author time

View file

@ -1,145 +0,0 @@
---
title: "Server Mode"
description: "Run Fabro as an API server with a web UI, concurrent runs, and team access"
---
<Warning>
Server mode is in private early access. Contact [bryan@qlty.sh](mailto:bryan@qlty.sh) if you're interested in trying it.
</Warning>
Fabro has two modes: **standalone** and **server**. Standalone mode (`fabro run`) executes a single workflow synchronously in your terminal. Server mode (`fabro serve`) starts an HTTP API that queues runs, streams events, and serves a web UI — so you can close your laptop and let workflows run.
Both modes use the same workflow engine, the same DOT files, and the same sandbox providers. The difference is how you interact with them.
## Standalone vs. server mode
| | Standalone | Server |
|---|---|---|
| **Command** | `fabro run workflow.fabro` | `fabro serve` |
| **Best for** | Local development, one-off runs, CI/CD | Production, team use, running at scale |
| **Execution** | Synchronous, one run per process | Asynchronous, queued with configurable concurrency |
| **Human-in-the-loop** | Terminal prompts | Web UI or HTTP endpoints |
| **Events** | Printed to stderr | Streamed via SSE |
| **Persistence** | Checkpoint files only | SQLite database + checkpoint files |
| **Web UI** | Not available | Full React interface |
| **Authentication** | None | JWT and/or mTLS |
## Starting the server
```bash
fabro serve
```
This starts the API on `127.0.0.1:3000` by default. To also run the web UI:
```bash
fabro serve # API on port 3000
cd apps/fabro-web && bun run dev # Web UI on port 5173
```
Common flags:
| Flag | Default | Description |
|---|---|---|
| `--port` | `3000` | Port to listen on |
| `--host` | `127.0.0.1` | Host address to bind to |
| `--model` | — | Override default LLM model |
| `--sandbox` | — | Override default sandbox provider |
| `--max-concurrent-runs` | `5` | Maximum concurrent run executions |
See [Server Configuration](/administration/server-configuration) for the full `server.toml` reference.
## Submitting runs
In server mode, workflows are submitted via the REST API and executed in the background:
```bash
curl -X POST http://localhost:3000/runs \
-H "Content-Type: application/json" \
-d '{"workflow": "implement-feature", "goal": "Add user authentication"}'
```
The server returns immediately with a run ID. A background scheduler promotes queued runs to `Running` in FIFO order, up to the concurrency limit.
## Run lifecycle
1. **Submit** — `POST /runs` creates the run with status `Queued`.
2. **Schedule** — The scheduler picks up queued runs up to `max_concurrent_runs`.
3. **Execute** — The engine walks the graph, streaming events to all subscribers.
4. **Complete** — The run transitions to `Completed`, `Failed`, or `Cancelled`.
## Web UI
The web UI connects to the API server and provides:
- **Runs board** — Monitor all active runs organized by status
- **Run detail** — Real-time stage progress, event stream, diffs, and usage stats
- **Start new run** — Submit workflows from the browser
- **Human-in-the-loop** — Answer agent questions through the web interface
- **Workflows** — Browse available workflows, view their graphs, and see run history
- **Insights** — SQL-based analysis across runs via DuckDB
<Frame caption="The Runs board shows all active runs organized by status.">
<img src="/images/web/runs-board.png" alt="Fabro web UI Runs board with Working, Pending, Verify, and Merge columns" />
</Frame>
<Frame caption="The run detail view shows stage progress alongside the workflow graph.">
<img src="/images/web/run-overview.png" alt="Fabro web UI run detail showing stages and workflow graph" />
</Frame>
## Event streaming
The API streams run events via [Server-Sent Events (SSE)](/api-reference/runs#get-events). Every stage start, LLM call, tool invocation, and edge selection is emitted as a structured JSON event. Any HTTP client that supports SSE can subscribe — the web UI is just one consumer.
## Human-in-the-loop
In server mode, human-in-the-loop questions are served over HTTP instead of terminal prompts. The engine blocks the current stage until an answer is submitted, then continues execution. See the [Human-in-the-Loop API reference](/api-reference/human-in-the-loop) for the polling and answer endpoints.
## Authentication
Server mode supports two authentication strategies, configurable in `server.toml`:
- **JWT** — EdDSA-signed bearer tokens. Used by the web UI. See [API Overview](/api-reference/overview#jwt-bearer-token) for token format.
- **mTLS** — Mutual TLS with client certificates. Used for service-to-service communication. See [API Overview](/api-reference/overview#mtls-mutual-tls) for setup.
Both strategies can be enabled simultaneously — the first successful match wins.
## Demo mode
Send the `X-Fabro-Demo: 1` header on any API request to get static mock data with authentication disabled. The web UI enables this automatically with the `FABRO_DEMO=1` environment variable. This lets you explore the UI without API keys or real workflow execution. See [Demo Mode](/api-reference/demo-mode) for details.
## Pointing the CLI at a server
The CLI can delegate commands to a running Fabro server instead of executing locally. Set `mode = "server"` in `~/.fabro/cli.toml`:
```toml title="cli.toml"
mode = "server"
[server]
base_url = "https://fabro.example.com:3000"
```
Or use the `--mode` flag:
```bash
fabro --mode server --server-url https://fabro.example.com:3000 models list
```
This applies to commands like `fabro models list`, `fabro llm chat`, and `fabro exec`. See [CLI Configuration](/reference/cli-configuration#mode) for the full options including mTLS setup.
## Next steps
<Columns cols={2}>
<Card title="Server Configuration" icon="gear" href="/administration/server-configuration">
Full server.toml reference — authentication, TLS, run defaults, and more.
</Card>
<Card title="Server Deployment" icon="server" href="/administration/deploy-server">
Deploy Fabro to production infrastructure.
</Card>
<Card title="API Reference" icon="code" href="/api-reference/overview">
REST API for submitting runs, streaming events, and managing resources.
</Card>
<Card title="How Fabro Works" icon="lightbulb" href="/core-concepts/how-fabro-works">
The workflow engine that powers both modes.
</Card>
</Columns>

View file

@ -20,9 +20,7 @@
"pages": [
"getting-started/introduction",
"getting-started/why-fabro",
"getting-started/quick-start",
"getting-started/dark-factory",
"getting-started/comparison"
"getting-started/quick-start"
]
},
{
@ -30,10 +28,10 @@
"icon": "lightbulb",
"pages": [
"core-concepts/how-fabro-works",
"getting-started/dark-factory",
"core-concepts/workflows",
"core-concepts/agents",
"core-concepts/models",
"core-concepts/server-mode"
"core-concepts/models"
]
},
{
@ -104,6 +102,7 @@
"group": "Reference",
"icon": "book",
"pages": [
"getting-started/comparison",
"reference/dot-language",
"reference/cli",
"reference/cli-configuration",

View file

@ -7,7 +7,7 @@ description: "Get up and running with Fabro"
Fabro has two modes:
- **Standalone mode** — Run workflows directly from the CLI. This is what the quick start covers below.
- **Server mode** — An API server with a web UI for launching and managing workflow runs at scale. See [Server Mode](/core-concepts/server-mode) for details.
- **Server mode** — An API server with a web UI for launching and managing workflow runs at scale. See [Server Mode](/administration/deploy-server) for details.
</Note>
## Install

View file

@ -89,4 +89,4 @@ The UI provides:
## Comparison
See [Server Mode](/core-concepts/server-mode#standalone-vs-server-mode) for a full feature comparison between standalone and server mode.
See [Server Mode](/administration/deploy-server#standalone-vs-server-mode) for a full feature comparison between standalone and server mode.