Keep nodes focused
Each node should have one responsibility. A node that explores AND plans AND implements is impossible to iterate on. Split into three nodes.
A pipeline is a directed acyclic graph written in DOT format. The dot-graph
resolver reads the pipeline, executes each node as an isolated Amplifier session,
and passes outputs between nodes as context accumulates through the graph.
Pipelines are the primary way to express multi-phase autonomous workflows in Resolve — where each node is an agent with its own instructions, tools, and context, all coordinated by the graph structure.
digraph build_feature { rankdir=LR;
Align [session="@bundle:align" label="Align\nIntent"]; Plan [session="@bundle:plan" label="Plan\nWork"]; Implement[session="@bundle:impl" label="Implement"]; Verify [session="@bundle:verify" label="Verify\nResult"]; Deliver [session="@bundle:deliver" label="Create\nPR"];
Align -> Plan -> Implement -> Verify -> Deliver;}The dot-graph resolver executes this graph left-to-right:
Align sessionPlanDeliver completesEach node in the graph is an Amplifier agent session. The node’s DOT attributes control how it runs.
NodeName [ session = "@mybundle:path/to/prompt" // required: which bundle/prompt drives this node label = "Human Label\nShown in UI" // optional: display name in viewport timeout = "1800" // optional: seconds before watchdog kills node retries = "2" // optional: retry count on failure tier = "blocking" // optional: execution tier];session — the agent bundle (required)The session attribute specifies which Amplifier bundle runs for this node. It uses
the same @bundle:path format as load_skill.
Plan [session="@mybundle:prompts/plan"];The bundle’s context files and instructions define what the agent does, what tools it has, and what output it produces.
label — display nameShown in the dot-graph viewport as the node’s title. Use \n for line breaks.
Implement [session="@mybundle:impl" label="Implement\nFeature"];Edges define both execution order and context flow. When node A completes, its output is passed into node B’s context before B runs.
A -> B; // A must complete before B starts; A's output feeds into BA -> B -> C; // chainA -> {B, C}; // B and C run in parallel (both receive A's output){B, C} -> D; // D waits for both B and C; receives both outputsParallelism: Nodes with no dependency on each other run in parallel. The runtime extracts the maximum parallelism from the graph structure automatically.
Context accumulation: Each node receives the outputs of all its upstream nodes accumulated into its initial context. A node with two parents gets both parents’ outputs as context before it runs.
The simplest pattern — one phase feeds the next:
digraph linear { rankdir=LR; Explore [session="@bundle:explore" label="Explore\nCodebase"]; Plan [session="@bundle:plan" label="Plan\nApproach"]; Build [session="@bundle:build" label="Build\nSolution"]; Review [session="@bundle:review" label="Review\nResult"]; Deliver [session="@bundle:deliver" label="Create PR"];
Explore -> Plan -> Build -> Review -> Deliver;}Explore multiple angles in parallel, then synthesize:
digraph parallel_explore { rankdir=LR; Start [session="@bundle:start" label="Parse\nSpec"]; ExploreA [session="@bundle:explore-a" label="Frontend\nAnalysis"]; ExploreB [session="@bundle:explore-b" label="Backend\nAnalysis"]; ExploreC [session="@bundle:explore-c" label="Test\nAnalysis"]; Synthesize[session="@bundle:synthesize" label="Synthesize"]; Plan [session="@bundle:plan" label="Plan"];
Start -> {ExploreA, ExploreB, ExploreC}; {ExploreA, ExploreB, ExploreC} -> Synthesize; Synthesize -> Plan;}ExploreA, ExploreB, and ExploreC all run in parallel. Synthesize receives all three outputs before running.
Pipelines can trigger reality checks by routing through a verify node that invokes the SDK capability:
digraph with_reality_check { rankdir=LR; Implement [session="@bundle:implement" label="Implement"]; RealityCheck[session="@bundle:reality-check-node" label="Reality\nCheck"]; Deliver [session="@bundle:deliver" label="Deliver\n(on pass)"];
Implement -> RealityCheck -> Deliver;}The @bundle:reality-check-node session runs the SDK’s start_reality_check() +
wait_for_reality_check() and emits the verdict as an artifact. If the verdict is
fail, the node can loop back or escalate.
The dot-graph resolver looks for pipeline files relative to the instance’s working
directory inside the container:
/project/.resolve/pipelines/├── main.dot # default pipeline├── quick.dot # pipeline variant└── deep.dot # another variantThe pipeline to run is typically selected via the instance’s input.pipeline field,
which maps to a file in this directory.
# Create an instance targeting the dot-graph resolver with a specific pipelinecurl -X POST "$RESOLVE_URL/api/instances" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "resolver": "dot-graph", "input": { "spec": "Add a GET /api/ping endpoint that returns {\"pong\": true}", "repo": "myorg/myrepo", "pipeline": "standard" } }'The dot-graph resolver schema — use GET /resolvers/dot-graph/schema to see the
exact input fields for the registered version.
Keep nodes focused
Each node should have one responsibility. A node that explores AND plans AND implements is impossible to iterate on. Split into three nodes.
Use fan-out for independent exploration
If two analyses don’t depend on each other, run them in parallel. The runtime handles parallelism automatically from graph structure.
Context accumulates — be intentional
Every upstream node’s output becomes context for downstream nodes. If an upstream node is verbose, downstream nodes get a lot of context. Design node outputs to be summaries, not raw dumps.
Reality check at the right gate
Put a reality-check node after implementation, before delivery. A reality-check before implementation only tells you the repo is broken before you touched it.