A workflow can pull in anotherDocumentation Index
Fetch the complete documentation index at: https://docs.fabro.sh/llms.txt
Use this file to discover all available pages before exploring further.
.fabro file as a reusable subgraph. Use imports to factor a common pattern — a review loop, a validation pipeline, a deploy sequence — into its own file and splice it into many parent workflows.
Imports are resolved at parse time: the imported graph is merged into the parent’s graph, with node IDs prefixed to avoid collisions. There is no runtime “sub-workflow” boundary; once merged, an imported node behaves like any other node in the run.
Basic example
Place a node in the parent graph with animport attribute pointing at the file to splice in:
deploy.fabro
validate.fabro
start → validate.lint → validate.test → deploy → exit. The validate placeholder is removed and its incoming/outgoing edges are rewired to the imported subgraph’s entry and exit.
Node ID prefixing
Imported nodes are renamed with the placeholder ID as a prefix, joined by a dot:| Imported node | Becomes |
|---|---|
lint | validate.lint |
test | validate.test |
start and exit sentinels are discarded — only the body is spliced in.
Contract for imported files
An imported file must define a clean entry and exit so Fabro knows where to rewire edges:- Exactly one start node (
shape=Mdiamond, or IDstart/Start) with exactly one outgoing edge. - Exactly one exit node (
shape=Msquare, or IDexit/Exit/end/End) with exactly one incoming edge. - The boundary edges (start → entry, predecessor → exit) must carry no semantic attributes (no
condition,label,weight,fidelity,thread_id,loop_restart, orfreeform).
import attribute is replaced with import_error, and fabro validate reports the failure as a graph error.
Placeholder attributes
A small set of attributes on the placeholder node propagate as defaults to every imported node. The imported node’s own value wins when both are set.| Attribute |
|---|
model |
provider |
reasoning_effort |
speed |
backend |
acp.command |
acp.config |
fidelity |
max_retries |
thread_id |
validate.fabro inherits model="haiku" and reasoning_effort="low" unless it sets its own value. Any attribute outside this list (other than class, see below) causes a poisoned placeholder.
Class propagation
Classes on the placeholder are unioned into every imported node’s class list, in addition to a class derived from the placeholder ID itself (lowercased, non-alphanumeric stripped). This lets stylesheets target imported subgraphs as a group.fast, shared, and validate.
Retry targets
retry_target and fallback_retry_target inside an imported file are rewritten to match the prefixed IDs:
validate.fabro
validate, validate.lint’s retry target becomes validate.test automatically.
Templating
Imported files are parsed as static DOT before template expansion. The import path and graph structure must be literal, but templates remain supported inside final string attributes such asprompt, script, and label:
shared/lint.fabro
import paths, node IDs, edge definitions, or other structural references. See Variables for the rendering pipeline.
Nested imports
An imported file can itself containimport= nodes. Relative paths resolve from the importing file’s directory, so a shared library can reference its own siblings without knowing where it’s loaded from:
shared/review.fabro
Empty imports as bypass
If the imported graph contains onlystart and exit (no body), the placeholder is removed and each incoming edge is cross-wired to each outgoing edge. This is useful for stubbing out an optional step:
noop.fabro
Error handling
When an import fails to resolve or violates the contract, Fabro does not abort parsing. Instead it leaves the placeholder node in place with animport_error attribute describing the failure. The import_error lint rule then surfaces this as a validation error from fabro validate and from run startup.
Common failure messages:
file not found: <path>— the path does not resolve under the parent file’s directory or the project fallback.circular import detected: <chain>— an import cycle was detected during expansion.imported workflow must have exactly one start node, found <n>— the contract above is violated.import placeholder '<id>' has unsupported attribute '<key>'— the placeholder uses an attribute that does not propagate.empty import '<id>' cannot bypass semantic edges— a body-less import sits between edges that carry conditions or labels.