Overview
ABlueprint is a named sequence of Steps that the BlueprintRunner executes sequentially. Each step can be a shell command or an agent prompt, with conditions that control whether it runs.
Blueprints are Magpie’s answer to the problem of fragmented, non-deterministic agent behavior. Instead of a single “do everything” prompt, tasks are broken into discrete phases with explicit control flow.
Defined in crates/magpie-core/src/blueprint/runner.rs:8-26.
Core Types
Blueprint
Human-readable identifier for the blueprint (e.g.
"magpie-tdd", "magpie-diagnostic", "magpie-fix").Ordered sequence of steps to execute. Steps run sequentially; each step receives the context output from the previous step.
Step
Defined incrates/magpie-core/src/blueprint/step.rs:56-62.
Step identifier for logging and tracing (e.g.
"scan-repo", "plan", "implement").If
true, a failed step (non-zero exit code or error) doesn’t stop the blueprint. If false, the blueprint fails immediately.Default: false (fail fast)Common Use: Set to true for test steps in TDD flow (tests are expected to fail in the red phase).StepKind
Defined incrates/magpie-core/src/blueprint/step.rs:49-53.
Condition
Defined incrates/magpie-core/src/blueprint/step.rs:24-46.
Step always runs.
Step runs only if the previous step’s exit code matches the given value.Example:
IfExitCode(0) → run only if previous step succeeded.Step runs only if the previous step’s exit code does NOT match the given value.Example:
IfExitCodeNot(0) → run only if previous step failed.Step runs only if the previous step’s output (stdout + stderr) contains the given substring.Example:
IfOutputContains("error:") → run only if previous output had an error message.StepContext
Defined incrates/magpie-core/src/blueprint/step.rs:4-22.
Current working directory for step execution. Set once at blueprint start, doesn’t change between steps.
Combined stdout + stderr from the previous step.
None at blueprint start.Exit code from the previous step.
None at blueprint start. Always Some(0) for agent steps (agents don’t fail with exit codes, they error).Key-value store for passing custom data between steps. The pipeline uses this for:
"chat_history"— conversation history from Discord/Teams (injected viaTriggerContext)"trace_dir"— path to JSONL trace directory (injected by pipeline)
AgentStep can reference metadata with with_context_from_metadata(key).ShellStep
Defined incrates/magpie-core/src/blueprint/steps/shell.rs:7-37.
Shell command to execute (e.g.
"echo", "cargo", "ls").Arguments to pass to the command. Empty by default.
Builder API
Execution
Callssandbox.exec(command, args) and captures:
- Exit code →
StepContext.last_exit_code - Stdout + stderr combined →
StepContext.last_output
AgentStep
Defined incrates/magpie-core/src/blueprint/steps/agent.rs:10-120.
The agent’s task prompt. This is the base instruction; additional context can be prepended via builder methods.
Maximum number of agent turns (tool calls). Defaults to 10 if not set.
If
true, prepends the previous step’s output to the prompt with "Previous step output:\n```\n...\n```\n\n".Default: falseIf set, prepends the value of
StepContext.metadata[key] to the prompt with "Context from conversation:\n```\n...\n```\n\n".Common Use: "chat_history" — includes full Discord/Teams conversation so the agent has context.Internal field set by the runner for trace logging. Not used by user code.
Builder API
Execution
Local Sandbox (default):- Runs
MagpieAgent(Goose-based, Tier 2 LLM) with full file/shell tool access - Writes JSONL trace if
trace_diris in metadata - Returns agent’s final response as
StepContext.last_output - Always sets
last_exit_code = Some(0)(agents don’t return exit codes)
- Executes
claude -p <prompt> --max-turns <n>inside the remote sandbox via REST API - Returns stdout as
last_output - Fails if exit code != 0
BlueprintRunner
Defined incrates/magpie-core/src/blueprint/runner.rs:28-106.
Execution Flow
For each step inblueprint.steps:
- Evaluate Condition: If
step.condition.evaluate(&context)returnsfalse, skip the step. - Execute Step: Call
step.kind.execute()(dispatches toShellSteporAgentStep). - Handle Result:
- Success: Update
self.contextwith new output/exit code, continue to next step. - Non-Zero Exit: If
continue_on_errorisfalse, fail the blueprint. Iftrue, log warning and continue with previous context. - Error (exception): If
continue_on_errorisfalse, return error. Iftrue, log warning and continue.
- Success: Update
- Return Final Context: After all steps, return the final
StepContext.
Logging
Runner logs every step:Built-in Blueprints
Magpie has three built-in blueprints, selected by TaskComplexity.Simple Blueprint
Function:build_main_blueprint() in pipeline.rs:251-293.
Use Case: Docs, typos, trivial edits.
Steps:
validate-workspace(Shell:pwd) — sanity checkexecute-task(Agent: single prompt with chat history)
TDD Blueprint
Function:build_tdd_blueprint() in pipeline.rs:348-513.
Use Case: New features, refactors.
Steps:
scan-repo(Shell:find+ exclusions) → get file treeplan(Agent: read tree, create plan) → concise implementation strategywrite-tests(Agent: write test code ONLY, no implementation) → TDD red phaseverify-tests-fail(Shell: run tests,continue_on_error: true) → expect failureimplement(Agent: read test output, implement feature) → TDD green phaserun-tests(Shell: run tests,continue_on_error: true) → verify greenlint-check(Shell: run linter,continue_on_error: true)
Diagnostic Blueprint
Function:build_diagnostic_blueprint() in pipeline.rs:520-724.
Use Case: Bug fixes, regressions.
Steps:
scan-repo(Shell:find+ exclusions)investigate(Agent: read-only, trace root cause, NO file modifications)plan(Agent: create targeted fix plan based on investigation)write-regression-test(Agent: write test that reproduces the bug)verify-test-fails(Shell: run tests, expect failure)implement-fix(Agent: fix the root cause)run-tests(Shell: run all tests)lint-check(Shell: run linter)
Fix Blueprint
Function:build_fix_blueprint() in pipeline.rs:298-342.
Use Case: Retry after CI failure.
Steps:
agent-fix(Agent: receives test failure output, fixes issues)
Usage Example
Custom Blueprint
Running a Blueprint
Conditional Execution
Design Rationale
Why Blueprints?
Early versions of Magpie used a single “implement this task” prompt. Problems:- Agent would skip tests
- Agent would over-optimize or under-optimize
- No control flow for complex tasks (bugs vs features)
- Forcing phases (plan → test → implement)
- Injecting context (previous step output flows automatically)
- Enabling retries (TDD verify-fail step can
continue_on_error) - Reducing prompt complexity (each step has a focused, single-purpose prompt)
Why Sequential Execution?
Steps run one at a time, not in parallel. This is intentional:- Each step depends on the previous step’s output (e.g. “plan” needs file tree from “scan”)
- Agent steps are stateful (file modifications affect future steps)
- Easier to debug (logs are chronological)
Why StepContext?
Context is the “thread” that flows through the blueprint:last_outputlets the next step see what just happenedlast_exit_codeenables conditional executionmetadatalets the pipeline inject external data (chat history, trace config)
Why Two Step Kinds?
Shell: Deterministic, fast, no LLM cost. Use for:- Scanning the repo
- Running tests/lint
- Verifying preconditions
- Planning
- Writing code
- Fixing bugs
Notes
- Not Turing Complete: Blueprints are linear sequences with conditional skips. No loops, no jumps, no recursion.
- No Dynamic Steps: All steps are defined at blueprint creation time. You can’t add steps mid-execution.
- Error Handling: Use
continue_on_error: truefor expected failures (e.g. TDD red phase). Usefalsefor unexpected failures (e.g. agent crashes). - Tracing: Every agent step writes JSONL traces if
trace_diris in metadata.
See Also
- TaskComplexity — Determines which built-in blueprint to use
- PipelineConfig — Configuration passed to blueprint builders
- PipelineResult — Output after blueprint execution