Skip to main content
Server mode is in private early access. Contact bryan@qlty.sh if you’re interested in trying it.
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

StandaloneServer
Commandfabro run workflow.fabrofabro serve
Best forLocal development, one-off runs, CI/CDProduction, team use, running at scale
ExecutionSynchronous, one run per processAsynchronous, queued with configurable concurrency
Human-in-the-loopTerminal promptsWeb UI or HTTP endpoints
EventsPrinted to stderrStreamed via SSE
PersistenceCheckpoint files onlySQLite database + checkpoint files
Web UINot availableFull React interface
AuthenticationNoneJWT and/or mTLS

Starting the server

fabro serve
This starts the API on 127.0.0.1:3000 by default. To also run the web UI:
fabro serve                        # API on port 3000
cd apps/fabro-web && bun run dev   # Web UI on port 5173
Common flags:
FlagDefaultDescription
--port3000Port to listen on
--host127.0.0.1Host address to bind to
--modelOverride default LLM model
--sandboxOverride default sandbox provider
--max-concurrent-runs5Maximum concurrent run executions
See 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:
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. SubmitPOST /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
Fabro web UI Runs board with Working, Pending, Verify, and Merge columns
Fabro web UI run detail showing stages and workflow graph

Event streaming

The API streams run events via Server-Sent Events (SSE). 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 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 for token format.
  • mTLS — Mutual TLS with client certificates. Used for service-to-service communication. See API Overview 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 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:
cli.toml
mode = "server"

[server]
base_url = "https://fabro.example.com:3000"
Or use the --mode flag:
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 for the full options including mTLS setup.

Next steps