Practical SWE Agent Walkthrough (Dynamic Planning + Branch Selection)¶
What this agent is¶
examples/real/swe_agent.py is a minimal “SWE-style” closed loop:
- plan first (numbered plan)
- execute one step at a time
- when uncertain, propose multiple candidates and let search/selection pick one
- always verify via a command before finishing
It uses:
- XML decision protocol (
XmlDecisionParser) Decision.branch(...)to represent multiple action candidatesRepoEnvfor repo/workspace semantics (SWE-style tasks)
Core design choices¶
- Planning is explicit state (
plan_steps,cursor). - Execution is one-action-per-step (strict XML output).
- Robustness comes from candidate sets (LLM + deterministic fallbacks).
- Verification drives termination, not narrative confidence.
Method-by-method design¶
SWEPlanState: plan cursor is the control variable¶
Fields:
plan_steps,cursor: explicit planning statescratchpad: bounded execution trailtarget_file,test_command: stable constraintsreplan_count: tracks instability (useful for eval)
prepare: expose plan cursor and memory view¶
Why:
- the model needs “where am I in the plan”
- the agent should see a bounded memory/debug view
build_system_prompt: XML protocol reduces parser ambiguity¶
Why XML here:
- JSON often breaks under nested quoting in code contexts
- XML is easier to constrain structurally for tool calls
The prompt enforces:
- exactly one
<decision>root mode="act|final|wait"- one tool action per step
prepare: make the plan and constraints legible¶
It includes:
- task + file + verification command
- full plan with a cursor marker
- recent execution trace
Design principle:
- the model should not “reconstruct the plan” from scratch each step.
decide: dynamic planning + candidate branching¶
This method implements three layers:
- If no plan (or plan ended):
_make_or_refresh_plan(...)thenDecision.wait("plan_ready") - Else: build action candidates:
- candidate 1: LLM-proposed action (via
_llm_step_action) - candidate 2+: deterministic fallbacks based on step keywords (inspect/edit/test)
- Return
Decision.branch(candidates=...)so Engine can select
Design principle:
- you want one place to add robustness without rewriting the entire agent.
reduce: advance only on tool evidence¶
Advancement rules:
- on tool
status == "success"=> advance - on verification
returncode == 0=> setfinal_resultand finish - on failed verification => trigger replanning next step
Engine wiring (what makes it “SWE-like”)¶
The example uses:
RepoEnv(...)so file/process ops are scoped to a repo workspaceDynamicTreeSearch(...)(optional) to select branch candidates