mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
docs: sync public docs to recent runtime changes
Reflect Docker as the default sandbox provider, add `skip_clone` for clone-based providers, document the `[run.sandbox.docker]` config table, and update tutorial command lines from `files-internal/...` to `docs/internal/...`. Bump the docs skill watermark to the latest synced commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d92ee47fe3
commit
157ec03a18
18 changed files with 111 additions and 56 deletions
|
|
@ -1 +1 @@
|
|||
d2cc37c615894d56ef672d00004ce13ce3b328c2
|
||||
c8185eaee6797e5f48963fcfff688838c5ff497d
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Fabro supports three sandbox providers: `local` (no isolation), `docker` (contai
|
|||
|
||||
## Network access control
|
||||
|
||||
For cloud sandboxes (Daytona), you can control outbound network access with the `network` field in `[sandbox.daytona]`. Three modes are available: `"allow_all"` (default), `"block"`, and `{ allow_list = ["..."] }` for CIDR-based egress filtering.
|
||||
For cloud sandboxes (Daytona), you can control outbound network access with the `network` field in `[run.sandbox.daytona]`. Three modes are available: `"allow_all"` (default), `"block"`, and `{ allow_list = ["..."] }` for CIDR-based egress filtering.
|
||||
|
||||
Server defaults in `settings.toml` apply when a run config doesn't specify `network`. Individual run configs can override the server default.
|
||||
|
||||
|
|
|
|||
|
|
@ -67,12 +67,12 @@ When the engine hits a [parallel fan-out node](/workflows/stages-and-nodes#paral
|
|||
|
||||
## Sandboxes
|
||||
|
||||
Node handlers execute tools (bash commands, file edits) inside a **sandbox**. Fabro supports six sandbox providers:
|
||||
Node handlers execute tools (bash commands, file edits) inside a **sandbox**. Fabro supports three sandbox providers:
|
||||
|
||||
| Sandbox | Description |
|
||||
|---|---|
|
||||
| `local` | Tools run directly on the host machine (default) |
|
||||
| `docker` | Tools run inside a Docker container |
|
||||
| `docker` | Tools run inside a Docker container (default) |
|
||||
| `local` | Tools run directly on the host machine |
|
||||
| `daytona` | Tools run in a cloud VM with SSH access |
|
||||
|
||||
The sandbox is configured per-run via CLI flags (`--sandbox docker`) or the run config TOML. See [Environments](/execution/environments) for details on each provider.
|
||||
|
|
|
|||
|
|
@ -81,8 +81,8 @@ Model stylesheets set per-node models inside the workflow graph, but you can als
|
|||
Pass `--model` and optionally `--provider` to `fabro run`:
|
||||
|
||||
```bash
|
||||
fabro run files-internal/demo/01-hello.fabro --model claude-opus-4-6
|
||||
fabro run files-internal/demo/04-pipeline.fabro --model gemini-3.1-pro-preview
|
||||
fabro run docs/internal/demo/01-hello.fabro --model claude-opus-4-6
|
||||
fabro run docs/internal/demo/04-pipeline.fabro --model gemini-3.1-pro-preview
|
||||
```
|
||||
|
||||
These flags set the default model for all nodes that don't have an explicit model assigned via a stylesheet. The provider is automatically inferred from the model catalog — you only need `--provider` for models not in the catalog or to force a specific provider.
|
||||
|
|
|
|||
|
|
@ -255,28 +255,30 @@ This is more reliable than a single "implement everything" node because:
|
|||
Pair the workflow with a run config for repeatable execution:
|
||||
|
||||
```toml title="run.toml"
|
||||
version = 1
|
||||
goal = "Build a terminal-based solitaire (Klondike) game in Python"
|
||||
_version = 1
|
||||
|
||||
[workflow]
|
||||
graph = "build-solitaire.fabro"
|
||||
|
||||
[llm]
|
||||
model = "claude-sonnet-4-5"
|
||||
[run]
|
||||
goal = "Build a terminal-based solitaire (Klondike) game in Python"
|
||||
|
||||
[run.model]
|
||||
name = "claude-sonnet-4-5"
|
||||
provider = "anthropic"
|
||||
fallbacks = ["openai", "gemini"]
|
||||
|
||||
[llm.fallbacks]
|
||||
anthropic = ["openai", "gemini"]
|
||||
[[run.prepare.steps]]
|
||||
script = "python3 -m venv .venv && . .venv/bin/activate && pip install pytest curses"
|
||||
|
||||
[setup]
|
||||
commands = ["python3 -m venv .venv && . .venv/bin/activate && pip install pytest curses"]
|
||||
|
||||
[sandbox]
|
||||
[run.sandbox]
|
||||
provider = "daytona"
|
||||
|
||||
[sandbox.daytona.snapshot]
|
||||
[run.sandbox.daytona.snapshot]
|
||||
name = "python-dev"
|
||||
cpu = 4
|
||||
memory = 8
|
||||
disk = 20
|
||||
memory = "8GB"
|
||||
disk = "20GB"
|
||||
dockerfile = "FROM python:3.12-slim\nRUN apt-get update && apt-get install -y git libncurses-dev"
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ The run branch is a regular Git branch that grows one commit per completed node.
|
|||
|
||||
### Run branch commits
|
||||
|
||||
After each node finishes, Fabro stages file changes and creates a commit on the run branch. Files matching `[checkpoint] exclude_globs` patterns (configured in [run.toml](/execution/run-configuration#checkpoint) or [settings.toml](/administration/server-configuration#checkpoint-section)) are excluded from staging:
|
||||
After each node finishes, Fabro stages file changes and creates a commit on the run branch. Files matching `[run.checkpoint] exclude_globs` patterns (configured in [run.toml](/execution/run-configuration#runcheckpoint) or [settings.toml](/administration/server-configuration#runcheckpoint-section)) are excluded from staging:
|
||||
|
||||
```
|
||||
fabro(01JKXYZ...): plan (success)
|
||||
fabro(01JKXYZ...): plan (succeeded)
|
||||
|
||||
Fabro-Run: 01JKXYZ...
|
||||
Fabro-Completed: 2
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ Fabro looks for `.devcontainer/devcontainer.json` in the repository root. If fou
|
|||
| `onCreateCommand` | Runs inside the sandbox after it's created |
|
||||
| `postCreateCommand` | Runs after `onCreateCommand` completes |
|
||||
| `postStartCommand` | Runs after the sandbox starts |
|
||||
| `containerEnv` | Merged into sandbox environment variables (TOML `[sandbox.env]` values take precedence on key collisions) |
|
||||
| `containerEnv` | Merged into sandbox environment variables (TOML `[run.sandbox.env]` values take precedence on key collisions) |
|
||||
|
||||
Lifecycle commands (`onCreateCommand`, `postCreateCommand`, `postStartCommand`) execute sequentially inside the sandbox. If any command fails, the run aborts before the workflow starts.
|
||||
|
||||
|
|
@ -40,6 +40,6 @@ Fabro detects and reports unsupported `COPY` and `ADD` instructions in devcontai
|
|||
|
||||
## Interaction with other sandbox settings
|
||||
|
||||
When `devcontainer = true`, the devcontainer Dockerfile overrides any `snapshot.dockerfile` setting in `[sandbox.daytona]`. Other Daytona settings (`cpu`, `memory`, `disk`, `auto_stop_interval`, `labels`) still apply.
|
||||
When `devcontainer = true`, the devcontainer Dockerfile overrides any `snapshot.dockerfile` setting in `[run.sandbox.daytona]`. Other Daytona settings (`cpu`, `memory`, `disk`, `auto_stop_interval`, `labels`) still apply.
|
||||
|
||||
Environment variables from `containerEnv` in the devcontainer config are merged with `[sandbox.env]` from the TOML config. On key collisions, the TOML config wins.
|
||||
Environment variables from `containerEnv` in the devcontainer config are merged with `[run.sandbox.env]` from the TOML config. On key collisions, the TOML config wins.
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@ fabro run workflow.fabro --sandbox daytona
|
|||
provider = "daytona"
|
||||
```
|
||||
|
||||
The precedence order is: CLI flag > run config TOML > server defaults > built-in default (`local`).
|
||||
The precedence order is: CLI flag > run config TOML > server defaults > built-in default (`docker`).
|
||||
|
||||
## Local
|
||||
|
||||
The local sandbox runs all tool operations directly on the host machine. It's the default and the simplest option — no setup required beyond the Fabro binary itself.
|
||||
The local sandbox runs all tool operations directly on the host machine. Use it for trusted workflows, local development, or runs that must operate directly on the current working tree.
|
||||
|
||||
### How it works
|
||||
|
||||
|
|
@ -53,33 +53,48 @@ The local sandbox offers no isolation. Agents can read and modify any file on th
|
|||
|
||||
## Docker
|
||||
|
||||
The Docker sandbox runs all tool operations inside a Docker container. Docker runs use a provider-owned workspace in the container; when the run has a GitHub origin, Fabro clones that repository into the workspace.
|
||||
The Docker sandbox runs all tool operations inside a Docker container. Docker is the built-in default runtime provider. Docker runs use a provider-owned workspace in the container; when the run has a GitHub origin, Fabro clones that repository into the workspace.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker Engine running on the host
|
||||
- The configured image available locally (or `auto_pull` enabled)
|
||||
- The configured image available locally, or a Docker client that can pull it
|
||||
- GitHub credentials configured when cloning private repositories
|
||||
|
||||
### How it works
|
||||
|
||||
- **Container lifecycle** — On `initialize()`, Fabro pulls the image (if needed), creates a container with `sleep infinity`, and starts it. On `cleanup()`, Fabro stops and removes the container.
|
||||
- **Working directory** — Docker runs use a provider-owned workspace inside the container. When a run has a GitHub origin, Fabro clones that repository into the workspace instead of bind-mounting the host source tree.
|
||||
- **Git clone** — Docker and Daytona accept GitHub origins for automatic cloning. If the run has a present non-GitHub origin, set `skip_clone = true` or switch to `local`.
|
||||
- **Commands** — Executed via `docker exec` with `/bin/bash -c` inside the container. Timeout and cancellation are supported.
|
||||
- **File writes** — Use the Docker API's tar upload to avoid shell escaping issues with special characters.
|
||||
- **Platform detection** — The container's `uname -r` is cached at startup.
|
||||
|
||||
### Configuration
|
||||
|
||||
The Docker sandbox is configured through the `DockerSandboxConfig`:
|
||||
Configure Docker through `[run.sandbox.docker]`:
|
||||
|
||||
```toml title="run.toml"
|
||||
[run.sandbox]
|
||||
provider = "docker"
|
||||
|
||||
[run.sandbox.docker]
|
||||
image = "buildpack-deps:noble"
|
||||
network_mode = "bridge"
|
||||
memory_limit = "4GB"
|
||||
cpu_quota = 200000
|
||||
skip_clone = false
|
||||
```
|
||||
|
||||
| Setting | Default | Description |
|
||||
|---|---|---|
|
||||
| `image` | `fabro-agent:latest` | Docker image to use |
|
||||
| `image` | `buildpack-deps:noble` | Docker image to use |
|
||||
| `network_mode` | `bridge` | Docker network mode |
|
||||
| `memory_limit` | unlimited | Memory limit in bytes |
|
||||
| `cpu_quota` | unlimited | CPU quota (microseconds per 100ms period) |
|
||||
| `auto_pull` | `true` | Pull the image if not found locally |
|
||||
| `env_vars` | `[]` | Additional `KEY=VALUE` environment variables |
|
||||
| `memory_limit` | `4GB` | Memory limit |
|
||||
| `cpu_quota` | `200000` | CPU quota (microseconds per 100ms period) |
|
||||
| `skip_clone` | `false` | Create an empty workspace instead of cloning the run's GitHub origin |
|
||||
|
||||
When `skip_clone = true`, the sandbox starts with an empty provider workspace. Use [prepare steps](/execution/run-configuration#runprepare) to clone or create any files the workflow needs.
|
||||
|
||||
### Preserving the container
|
||||
|
||||
|
|
@ -106,13 +121,13 @@ The Daytona sandbox runs all tool operations inside a cloud-hosted VM managed by
|
|||
### Prerequisites
|
||||
|
||||
- A `DAYTONA_API_KEY` environment variable
|
||||
- A GitHub App configured via `fabro install` (for private repository cloning)
|
||||
- GitHub access configured via `fabro install` or `gh auth login` (for private repository cloning)
|
||||
|
||||
### How it works
|
||||
|
||||
- **Sandbox lifecycle** — On `initialize()`, Fabro creates a Daytona sandbox (from an image or a snapshot), clones the current git repository into it, and waits until it's ready. On `cleanup()`, the sandbox is deleted.
|
||||
- **Working directory** — Fixed at `/home/daytona/workspace`. The current repository is cloned there automatically.
|
||||
- **Git clone** — Fabro detects the local `origin` remote URL and current branch, converts SSH URLs to HTTPS, and clones into the sandbox. For private repositories, Fabro uses a GitHub App Installation Access Token scoped to `contents: read` on the specific repository. Public repositories are cloned without credentials. If no git repo is detected, the working directory is created empty.
|
||||
- **Sandbox lifecycle** — On `initialize()`, Fabro creates a Daytona sandbox (from an image or a snapshot), clones the run's GitHub origin into it when one is available, and waits until it's ready. On `cleanup()`, the sandbox is deleted.
|
||||
- **Working directory** — Fixed at `/home/daytona/workspace`. GitHub-origin runs clone the repository there automatically.
|
||||
- **Git clone** — Fabro detects the run manifest's GitHub origin URL and branch, converts SSH URLs to HTTPS, and clones into the sandbox. For private repositories, Fabro uses a GitHub App Installation Access Token scoped to the specific repository. Public repositories are cloned without credentials. Set `skip_clone = true` to create an empty workspace instead.
|
||||
- **Commands** — Executed via the Daytona process API. Commands are base64-encoded and piped through `sh` to support pipes, environment variables, and other shell features.
|
||||
- **Ephemeral** — Sandboxes are created with `ephemeral: true` and a unique timestamped name (e.g. `fabro-20260305-142301-a3f2`).
|
||||
|
||||
|
|
@ -126,6 +141,7 @@ provider = "daytona"
|
|||
|
||||
[run.sandbox.daytona]
|
||||
auto_stop_interval = 60
|
||||
skip_clone = false
|
||||
|
||||
[run.sandbox.daytona.snapshot]
|
||||
name = "rust-dev"
|
||||
|
|
|
|||
|
|
@ -165,10 +165,35 @@ preserve = true
|
|||
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| `provider` | Sandbox mode: `local` (default), `docker`, or `daytona`. |
|
||||
| `provider` | Sandbox mode: `docker` (default), `local`, or `daytona`. |
|
||||
| `preserve` | When `true`, keep the sandbox alive after the run finishes. Useful for debugging. |
|
||||
| `devcontainer` | When `true`, use the repo's `devcontainer.json` to configure the sandbox. See [Devcontainers](/execution/devcontainers). |
|
||||
|
||||
#### `[run.sandbox.docker]`
|
||||
|
||||
Additional settings when using the Docker sandbox:
|
||||
|
||||
```toml title="run.toml"
|
||||
[run.sandbox]
|
||||
provider = "docker"
|
||||
|
||||
[run.sandbox.docker]
|
||||
image = "buildpack-deps:noble"
|
||||
network_mode = "bridge"
|
||||
memory_limit = "4GB"
|
||||
cpu_quota = 200000
|
||||
skip_clone = false
|
||||
```
|
||||
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| `image` | Docker image used for the run container. Defaults to `buildpack-deps:noble`. |
|
||||
| `network_mode` | Docker network mode. Defaults to `bridge`. |
|
||||
| `memory_limit` | Memory limit using human-readable units such as `"4GB"` or `"512MiB"`. |
|
||||
| `cpu_quota` | Docker CPU quota in microseconds per 100ms period. Defaults to `200000`. |
|
||||
| `env_vars` | Provider-level environment variables passed to the Docker container. For workflow tool execution, prefer `[run.sandbox.env]`. |
|
||||
| `skip_clone` | When `true`, start with an empty container workspace instead of cloning the run's GitHub origin. |
|
||||
|
||||
#### `[run.sandbox.daytona]`
|
||||
|
||||
Additional settings when using the Daytona cloud sandbox:
|
||||
|
|
@ -201,6 +226,7 @@ dockerfile = "FROM rust:1.85-slim-bookworm\nRUN apt-get update"
|
|||
| `snapshot.disk` | Disk size using the same units as `memory`. |
|
||||
| `snapshot.dockerfile` | Dockerfile content (inline string) or path (`{ path = "..." }`) for building the snapshot image. Paths are resolved relative to the TOML file's directory. |
|
||||
| `network` | Network access mode: `"allow_all"` (default), `"block"`, or `{ allow_list = ["..."] }`. See [Sandboxing](/administration/sandboxing#network-access-control). |
|
||||
| `skip_clone` | When `true`, start with an empty Daytona workspace instead of cloning the run's GitHub origin. |
|
||||
|
||||
#### `[run.sandbox.local]`
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ preserve = false
|
|||
|
||||
[run.sandbox.daytona]
|
||||
auto_stop_interval = 60
|
||||
skip_clone = false
|
||||
|
||||
[run.sandbox.daytona.labels]
|
||||
project = "fabro"
|
||||
|
|
@ -83,7 +84,7 @@ Use `"block"` or a CIDR allow list when running untrusted or generated code to p
|
|||
Snapshots let you pre-build an environment image so each run starts with dependencies already installed rather than installing them in setup commands every time.
|
||||
|
||||
```toml title="run.toml"
|
||||
[sandbox.daytona.snapshot]
|
||||
[run.sandbox.daytona.snapshot]
|
||||
name = "my-snapshot"
|
||||
cpu = 4
|
||||
memory = 8
|
||||
|
|
@ -99,7 +100,17 @@ If a snapshot is configured by name but doesn't exist and no `dockerfile` is pro
|
|||
|
||||
## Private repositories
|
||||
|
||||
Fabro automatically clones the current repository into the sandbox at `/home/daytona/workspace`. Public repositories work without extra configuration. Private repositories require GitHub access. In `token` mode, Fabro uses the stored token directly. In `app` mode, Fabro uses short-lived Installation Access Tokens scoped to the specific repository.
|
||||
Fabro automatically clones the run's GitHub origin into the sandbox at `/home/daytona/workspace`. Public repositories work without extra configuration. Private repositories require GitHub access. In `token` mode, Fabro uses the stored token directly. In `app` mode, Fabro uses short-lived Installation Access Tokens scoped to the specific repository.
|
||||
|
||||
Set `skip_clone = true` in `[run.sandbox.daytona]` when a workflow should start with an empty Daytona workspace instead of cloning the run origin:
|
||||
|
||||
```toml title="run.toml"
|
||||
[run.sandbox]
|
||||
provider = "daytona"
|
||||
|
||||
[run.sandbox.daytona]
|
||||
skip_clone = true
|
||||
```
|
||||
|
||||
If the clone fails without GitHub access configured, Fabro suggests running the setup flow:
|
||||
|
||||
|
|
@ -167,7 +178,7 @@ The `DAYTONA_API_KEY` environment variable is missing or invalid. Store it with
|
|||
|
||||
### "Snapshot does not exist and no dockerfile provided"
|
||||
|
||||
The run config references a snapshot name that doesn't exist on Daytona, and no `dockerfile` is provided to create it. Either create the snapshot manually in the Daytona dashboard or add a `dockerfile` field to `[sandbox.daytona.snapshot]`.
|
||||
The run config references a snapshot name that doesn't exist on Daytona, and no `dockerfile` is provided to create it. Either create the snapshot manually in the Daytona dashboard or add a `dockerfile` field to `[run.sandbox.daytona.snapshot]`.
|
||||
|
||||
### "Timed out waiting for snapshot to become active"
|
||||
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ gate -> slow_path
|
|||
Instead of inlining long prompts, reference an external file:
|
||||
|
||||
```dot
|
||||
simplify [label="Simplify", prompt="@files-internal/prompts/simplify.md"]
|
||||
simplify [label="Simplify", prompt="@prompts/simplify.md"]
|
||||
```
|
||||
|
||||
The `@` prefix tells Fabro to load the prompt from a file path relative to the workflow file. Paths support `~` (home directory) and `..` (parent directory):
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ digraph BranchLoop {
|
|||
```
|
||||
|
||||
```bash
|
||||
fabro run files-internal/demo/05-branch-loop.fabro
|
||||
fabro run docs/internal/demo/05-branch-loop.fabro
|
||||
```
|
||||
|
||||
## Command nodes
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ digraph Ensemble {
|
|||
```
|
||||
|
||||
```bash
|
||||
fabro run files-internal/demo/11-ensemble.fabro
|
||||
fabro run docs/internal/demo/11-ensemble.fabro
|
||||
```
|
||||
|
||||
<Note>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ digraph Hello {
|
|||
Run it:
|
||||
|
||||
```bash
|
||||
fabro run files-internal/demo/01-hello.fabro
|
||||
fabro run docs/internal/demo/01-hello.fabro
|
||||
```
|
||||
|
||||
### What's happening
|
||||
|
|
@ -68,7 +68,7 @@ digraph ToolUse {
|
|||
```
|
||||
|
||||
```bash
|
||||
fabro run files-internal/demo/02-tool-use.fabro
|
||||
fabro run docs/internal/demo/02-tool-use.fabro
|
||||
```
|
||||
|
||||
### What's happening
|
||||
|
|
@ -108,7 +108,7 @@ digraph SubAgent {
|
|||
```
|
||||
|
||||
```bash
|
||||
fabro run files-internal/demo/03-subagent.fabro
|
||||
fabro run docs/internal/demo/03-subagent.fabro
|
||||
```
|
||||
|
||||
### What's happening
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ digraph MultiModel {
|
|||
```
|
||||
|
||||
```bash
|
||||
fabro run files-internal/demo/08-multi-model.fabro
|
||||
fabro run docs/internal/demo/08-multi-model.fabro
|
||||
```
|
||||
|
||||
## Model stylesheets
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ digraph Parallel {
|
|||
```
|
||||
|
||||
```bash
|
||||
fabro run files-internal/demo/06-parallel.fabro
|
||||
fabro run docs/internal/demo/06-parallel.fabro
|
||||
```
|
||||
|
||||
## Fan-out with the fork node
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ digraph PlanImplement {
|
|||
plan [label="Plan", prompt="Analyze the goal and codebase. Write a clear, step-by-step implementation plan to a Markdown file called plan.md. Include what files will change and why.", reasoning_effort="high"]
|
||||
approve [shape=hexagon, label="Approve Plan"]
|
||||
implement [label="Implement", prompt="Read plan.md and implement every step. Make all the code changes described in the plan."]
|
||||
simplify [label="Simplify", prompt="@files-internal/prompts/simplify.md"]
|
||||
simplify [label="Simplify", prompt="@prompts/simplify.md"]
|
||||
|
||||
start -> plan -> approve
|
||||
approve -> implement [label="[A] Approve"]
|
||||
|
|
@ -32,7 +32,7 @@ digraph PlanImplement {
|
|||
```
|
||||
|
||||
```bash
|
||||
fabro run files-internal/demo/10-plan-implement.fabro
|
||||
fabro run docs/internal/demo/10-plan-implement.fabro
|
||||
```
|
||||
|
||||
## Human gates
|
||||
|
|
@ -77,10 +77,10 @@ The `plan` node sets `reasoning_effort="high"`. This tells the model to think ha
|
|||
|
||||
## Prompt file references
|
||||
|
||||
The `simplify` node uses `@files-internal/prompts/simplify.md` instead of an inline prompt string:
|
||||
The `simplify` node uses `@prompts/simplify.md` instead of an inline prompt string:
|
||||
|
||||
```dot
|
||||
simplify [label="Simplify", prompt="@files-internal/prompts/simplify.md"]
|
||||
simplify [label="Simplify", prompt="@prompts/simplify.md"]
|
||||
```
|
||||
|
||||
The `@` prefix tells Fabro to load the prompt from a Markdown file, resolved relative to the Graphviz file's location. This keeps Graphviz files concise and lets you version prompts as standalone files. See [Prompts](/agents/prompts) for details.
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ digraph SubWorkflow {
|
|||
```
|
||||
|
||||
```bash
|
||||
fabro run files-internal/demo/12-sub-workflow.fabro
|
||||
fabro run docs/internal/demo/12-sub-workflow.fabro
|
||||
```
|
||||
|
||||
## The house node
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue