The Leash and the Wolf: Why Every AI Agent Needs an Orchestrator

Published on 16 February 2026
20 min read
agent-orchestration
The Leash and the Wolf: Why Every AI Agent Needs an Orchestrator

The Leash and the Wolf: Why Every AI Agent Needs an Orchestrator

Deep agents are powerful. But without a state machine holding the leash, they will loop, skip, waste, and crash. Here is the case for deterministic orchestration, told through Goose, mini-swe-agent, Stripe Minions, and OpenClaw.

Table of Contents

  1. The $1 Trillion Loop
  2. What Is a Deep Agent?
  3. The Five Problems: When the Wolf Runs Free
  4. Case Study: Goose (Block)
  5. Case Study: mini-swe-agent
  6. Case Study: Stripe Minions
  7. Case Study: OpenClaw as Orchestrator
  8. The Hybrid Architecture: The Winning Pattern
  9. Context Management: The Hidden Challenge
  10. Control Is Not the Enemy of Creativity

The $1 Trillion Loop

In February 2026, Stripe published a blog post that quietly revealed something remarkable. Over a thousand pull requests merge every week at Stripe with zero human-written code. Fully unattended coding agents, called “Minions,” produce production code for a system that moves over $1 trillion in payment volume per year.

The sentence that caught my attention was this:

“The core agent loop runs on a fork of Block’s coding agent goose, one of the first widely used coding agents, which we forked early on. We’ve customized the orchestration flow in an opinionated way to interleave agent loops and deterministic code, for git operations, linters, testing, and so on, so that minion runs mix the creativity of an agent with the assurance that they’ll always complete Stripe-required steps like linters.”

Stripe Engineering Blog: Minions

Read that again. Stripe did not build a smarter model. They did not give the agent more tools. They built an orchestrator that wraps the agent, forces it through mandatory checkpoints, and guarantees that certain steps always execute regardless of what the LLM decides.

This is the pattern hiding in plain sight across every successful production agent deployment. And it starts with understanding what a “deep agent” actually is, and why it is not enough.


What Is a Deep Agent?

A deep agent is not just “an LLM that can call tools.” It is an execution system that can:

  • Sustain multi-step goals over long horizons
  • Maintain and evolve state across turns
  • Decompose tasks into subgoals
  • Call tools iteratively
  • Recover from failure with structured feedback
  • Converge under explicit stopping criteria

A useful mental model breaks this into four loops:

  • Reasoning loop: propose next action based on current state
  • Action loop: execute tool calls and external operations
  • Learning loop: consume results, detect failures, revise plan
  • Control loop: enforce budgets, gates, retries, and completion policy

Most agent implementations over-index on the first two loops and under-build the fourth. That is where things break.

The ReAct Foundation

Every deep agent builds on the ReAct (Reasoning + Acting) pattern:

Thought: I need to find the bug in the authentication code
Action: grep -r "authenticate" src/
Observation: Found 3 files with authentication logic
Thought: The error message mentions line 45 of auth.py
Action: cat src/auth.py | head -60
Observation: [file contents]
Thought: I see the bug - missing null check on line 45
Action: [edit file]

In code, it looks deceptively simple:

while not done:
    thought = llm.think(context)
    action = llm.decide_action(thought)
    observation = env.execute(action)
    context.append(thought, action, observation)

The key insight of a deep agent is that the context window IS the state. The agent’s “understanding” emerges from the accumulated history of thoughts, actions, and observations. After 50 steps, the LLM sees the entire trajectory when making decisions, not just the current state.

This is powerful. It is also dangerous.


The Five Problems: When the Wolf Runs Free

A pure deep agent loop gives the LLM total control:

# Pure agent loop - LLM controls everything
while True:
    action = llm.decide(context)
    result = env.execute(action)
    context.append(result)
    if llm.thinks_done(context):
        break

This creates five fundamental problems:

Problem What Happens Real Example
No Guarantees LLM might skip required steps Forgets to run tests before submitting
Unbounded Behavior Can loop indefinitely Keeps trying the same failing approach 30 times
No Checkpoints Cannot resume from failure Crashes after 50 steps, loses everything
Resource Waste May use expensive operations when cheap ones suffice Uses GPT-4 for simple linting tasks
Non-determinism Unpredictable execution paths Sometimes runs tests, sometimes does not

These are not theoretical concerns. They are the reason Stripe built an orchestrator. The reason Goose needs a state machine. The reason OpenClaw’s Gateway is more than a chat wrapper.

A powerful deep agent is still insufficient for production workflows because it cannot guarantee hard invariants by itself. “Always run lint before marking task complete.” “Never push if required tests fail.” “At most N expensive CI rounds.” These are not suggestions. They are policies. And LLM behavior is stochastic; compliance invariants are not.

So you need something else: an external state machine or graph orchestrator to govern run phases, enforce transitions, and handle failure deterministically.


Case Study: Goose (Block)

Goose is Block’s open-source AI agent (30.5k stars on GitHub). Written in Rust, it is the foundation that Stripe forked for Minions. Goose already has a strong inner loop, but examining its architecture reveals exactly where orchestration is missing and where it needs to be added.

The Deep Agent Core

Goose’s operational core lives in Agent::reply_internal. Conceptually, the loop does:

  1. Check cancellation, max turns, final-output condition
  2. Build contextualized conversation and stream model response
  3. Emit assistant text and tool requests
  4. Route tool calls through inspection, approval, and execution
  5. Append tool responses and messages to conversation
  6. Optionally compact context and apply retry logic
  7. Exit or continue

This is a strong deep agent. But look at where the deterministic logic currently lives. It is scattered across three separate layers:

  • Deep-agent loop (inner): Agent::reply_internal in crates/goose/src/agents/agent.rs
  • Execution runners (outer): CLI runtime stream handling in crates/goose-cli/src/session/mod.rs, plus scheduled automation lifecycle in crates/goose/src/scheduler.rs
  • Deterministic validators: Retry checks and on_failure hooks in crates/goose/src/agents/retry.rs

Goose is already close to a formal graph architecture. The missing piece is making run phases explicit and policy-driven instead of implicit across scattered handlers.

The Proposed State Machine

Here is what an explicit orchestration layer looks like for Goose. This comes from a formal RFC proposing a RunState enum and transition function:

pub enum RunState {
    PrepareContext,
    AgentPass,
    DeterministicChecks,
    RepairPass,
    Finalize,
    Abort,
}

pub enum TerminalReason {
    Success,
    Cancelled,
    BudgetExceeded,
    PolicyViolation,
    UnrecoverableError,
}

And a durable execution context to carry state across transitions:

pub struct RunContext {
    pub session_id: String,
    pub schedule_id: Option<String>,
    pub max_agent_passes: u32,
    pub max_repair_rounds: u32,
    pub deterministic_check_round: u32,
    pub repair_round: u32,
    pub last_failure_summary: Option<String>,
    pub terminal_reason: Option<TerminalReason>,
}

Transition Semantics

The state machine follows clear, deterministic transitions:

PrepareContext -> AgentPass
AgentPass -> DeterministicChecks
DeterministicChecks:
    if pass -> Finalize
    if fail and repair budget remains -> RepairPass
    else -> Abort
RepairPass -> AgentPass
Finalize and Abort are terminal.

The Deterministic Checks Contract

Checks run in orchestrator state, not as optional model behavior:

pub struct CheckReport {
    pub passed: bool,
    pub summary: String,
    pub failures: Vec<CheckFailure>,
}

pub struct CheckFailure {
    pub check_name: String,
    pub command: String,
    pub exit_code: Option<i32>,
    pub stderr_excerpt: String,
}

A compact CheckReport is injected into the next AgentPass as structured feedback when repair is needed. The agent does not decide whether to run checks. The orchestrator decides. The agent only decides how to fix what the checks found.

An Example Execution Trace

PrepareContext
 -> AgentPass (produces candidate changes)
 -> DeterministicChecks (lint fails)
 -> RepairPass (inject check report)
 -> AgentPass (fixes lint)
 -> DeterministicChecks (pass)
 -> Finalize (terminal: Success)

This is the difference between “the agent might run lint” and “lint will always run.” That difference is everything in production.


Case Study: mini-swe-agent

On the opposite end of the complexity spectrum, mini-swe-agent from the Princeton and Stanford team behind SWE-bench proves that orchestration patterns work even in ~100 lines of Python. It scores over 74% on SWE-bench verified, making it one of the most efficient agent implementations per line of code.

The Deep Agent Core

mini-swe-agent’s context accumulates in self.messages, making it a textbook deep agent:

class DefaultAgent:
    def __init__(self, model: Model, env: Environment, ...):
        self.messages: list[dict] = []  # THE DEEP STATE
        self.model = model
        self.env = env
        self.cost = 0.0
        self.n_calls = 0

    def step(self) -> list[dict]:
        """Query the LM, execute actions."""
        return self.execute_actions(self.query())

    def query(self) -> dict:
        """Query the model and return model messages."""
        message = self.model.query(self.messages)  # Full history passed!
        self.add_messages(message)
        return message

    def execute_actions(self, message: dict) -> list[dict]:
        """Execute actions in message, add observation messages."""
        outputs = [self.env.execute(action) for action in
                   message.get("extra", {}).get("actions", [])]
        return self.add_messages(
            *self.model.format_observation_messages(message, outputs, ...))

Exception-Based Control Flow: A Lightweight State Machine

Here is where mini-swe-agent gets clever. Instead of a formal state machine, it uses Python’s exception hierarchy as a lightweight control flow mechanism:

class InterruptAgentFlow(Exception):
    """Base class - carries messages to inject into context."""
    def __init__(self, *messages: dict):
        self.messages = messages

class Submitted(InterruptAgentFlow):
    """Agent completed its task successfully."""

class LimitsExceeded(InterruptAgentFlow):
    """Hit cost or step limit."""

class FormatError(InterruptAgentFlow):
    """LLM output malformed."""

class UserInterruption(InterruptAgentFlow):
    """Human interrupted the agent."""

These exceptions can be raised from anywhere in the call stack and are caught in the main loop:

def run(self, task: str = "", **kwargs) -> dict:
    """Run step() until agent is finished."""
    self.messages = []
    self.add_messages(system_message, user_message)

    while True:
        try:
            self.step()
        except InterruptAgentFlow as e:
            self.add_messages(*e.messages)
        except Exception as e:
            self.handle_uncaught_exception(e)
            raise
        finally:
            self.save(self.config.output_path)

        if self.messages[-1].get("role") == "exit":
            break

    return self.messages[-1].get("extra", {})

This is not a full graph orchestrator, but it is not a pure deep agent either. The exceptions create deterministic exit points that the LLM cannot skip. Cost limits are enforced. Format errors are caught. Submission goes through a defined path.

Three Levels of Hybrid Architecture

mini-swe-agent’s simplicity makes it an ideal canvas for showing how to progressively add orchestration.

Level 1: Inject Deterministic Checkpoints into step()

class AgentWithAutoLint(DefaultAgent):
    def step(self) -> list[dict]:
        result = super().step()  # Normal LLM step

        # DETERMINISTIC: After file edits, always lint
        last_actions = self.messages[-2].get("extra", {}).get("actions", [])
        for action in last_actions:
            if self._is_file_edit(action.get("command", "")):
                lint_output = self._run_lint()
                self.add_messages({
                    "role": "user",
                    "content": f"[SYSTEM] Automatic lint result:\n{lint_output}"
                })
                break

        return result

Level 2: Multi-Phase Orchestration by overriding run()

class PhasedAgent(DefaultAgent):
    def run(self, task: str = "", **kwargs) -> dict:
        self.messages = []

        # PHASE 1: Understanding (bounded, 3 steps max)
        self._run_phase(
            "Analyze the task and identify what files need to change. "
            "Do NOT make any changes yet.",
            max_steps=3
        )

        # DETERMINISTIC: Create branch
        subprocess.run(["git", "checkout", "-b", f"agent-fix-{int(time.time())}"])

        # PHASE 2: Implementation (more steps allowed)
        self._run_phase("Now implement your planned changes.", max_steps=20)

        # DETERMINISTIC: Always lint and autofix
        subprocess.run(["ruff", "check", "--fix", "."])
        subprocess.run(["git", "add", "-A"])

        # PHASE 3: Testing (bounded, with CI feedback)
        for ci_round in range(2):  # Max 2 CI rounds like Stripe
            test_result = subprocess.run(["pytest", "-x"], capture_output=True)
            if test_result.returncode == 0:
                break
            self._run_phase(
                f"Tests failed. Fix these errors:\n{test_result.stdout.decode()}",
                max_steps=10
            )

        # DETERMINISTIC: Commit and prepare PR
        subprocess.run(["git", "commit", "-m", "Agent fix"])
        return {"status": "completed", "phases": 3}

Level 3: Full Graph-Based Orchestration

@dataclass
class GraphNode:
    name: str
    execute: Callable
    next_nodes: dict[str, str]  # condition -> next_node_name

class GraphOrchestrator:
    def __init__(self, agent: DefaultAgent):
        self.agent = agent
        self.nodes: dict[str, GraphNode] = {}
        self.state: dict = {}

    def add_node(self, node: GraphNode):
        self.nodes[node.name] = node

    def run(self, start_node: str, task: str):
        self.state["task"] = task
        current = start_node

        while current != "END":
            node = self.nodes[current]
            result = node.execute(self.agent, self.state)
            self.state[f"{current}_result"] = result

            for condition, next_node in node.next_nodes.items():
                if condition == "default" or self._check_condition(condition, result):
                    current = next_node
                    break

        return self.state

# Build the graph
orchestrator = GraphOrchestrator(agent)
orchestrator.add_node(GraphNode("plan", plan_node, {"default": "implement"}))
orchestrator.add_node(GraphNode("implement", implement_node, {"default": "test"}))
orchestrator.add_node(GraphNode("test", test_node,
                                {"success": "END", "failure": "fix"}))
orchestrator.add_node(GraphNode("fix", fix_node, {"default": "test"}))

orchestrator.run("plan", "Fix the authentication bug")

The progression is clear: from hooks, to phases, to a full graph. Each level adds more guarantees while preserving the agent’s creative freedom within bounded steps.


Case Study: Stripe Minions

Stripe’s Minions represent the gold standard for production agent orchestration. They are fully unattended, built to one-shot tasks, and produce code for a system handling over $1 trillion in payment volume. Understanding how they work reveals the orchestration pattern at its most refined.

The Architecture

Minions start in an isolated developer environment (a “devbox”), which is the same type of machine that Stripe engineers write code on. Devboxes are pre-warmed so one can be spun up in 10 seconds, with Stripe code and services pre-loaded. They are isolated from production resources and the internet.

The core agent loop runs on a fork of Goose. But here is what matters: Stripe did not just run Goose. They wrapped it in an opinionated orchestration flow.

The Interleaving Pattern

The Stripe flow interleaves agent creativity with deterministic guarantees:

  1. Deterministic: Spin up devbox, hydrate context by running MCP tools on relevant links before the agent starts
  2. Agent: The LLM reads coding rules (conditionally applied per subdirectory) and produces code changes
  3. Deterministic: Local executable runs heuristic-selected lints on each git push (less than 5 seconds)
  4. Agent (conditional): If local checks fail, the agent receives structured feedback and fixes
  5. Deterministic: CI selectively runs tests from Stripe’s battery of 3+ million tests
  6. Agent (conditional): If CI fails and this is round 1, the agent gets one more attempt
  7. Deterministic: Apply any available autofixes for test failures
  8. Deterministic: Create branch, push, prepare PR following Stripe’s PR template

The “At Most Two” Rule

This is a critical design choice worth highlighting:

“Since CI runs cost tokens, compute, and time, we only have at most two rounds of CI. If tests fail after an initial push, we prompt the minion to fix failing tests and push a second time, but are then done.”

An unbounded agent might try 10 rounds of CI. The orchestrator says: two, maximum. This is a policy constraint that no amount of prompt engineering can reliably enforce. Only a state machine can guarantee it.

Shift Feedback Left

Stripe’s philosophy is “shift feedback left” for developer productivity:

“It’s best for humans and agents if any lint step that would fail in CI is enforced in the IDE or on a git push, and presented to the engineer immediately.”

Cheap, fast checks run first (local lint in under 5 seconds). Expensive checks run later (CI). The orchestrator controls this ordering. The agent does not get to choose “I’ll skip local lint and go straight to CI.” That path does not exist in the state machine.

MCP as Deterministic Context Hydration

Before the agent loop even starts, Minions deterministically run relevant MCP tools over likely-looking links to hydrate the context:

“We deterministically run relevant MCP tools over likely-looking links before a minion run even starts, to better hydrate the context.”

This is PrepareContext in the state machine model. It is not optional. It is not “the agent might decide to look up documentation.” It always happens.


Case Study: OpenClaw as Orchestrator

OpenClaw (formerly Clawdbot/Moltbot) is the fastest-growing open-source AI project in GitHub history (201k stars). Most people describe it as a “personal AI assistant.” But if you look at the architecture, OpenClaw is better understood as an orchestrator that happens to have an agent inside it.

Nathan Flurry, who runs the actor runtime Rivet, put it best in his analysis on OpenClaw as an agent orchestrator:

“What makes OpenClaw a great orchestrator is its ability to handoff tasks to background sessions then notify you when it’s finished.”

The Gateway: Five Subsystems, One Process

When you run openclaw gateway, you start a single long-lived Node.js process. That process is the entire system. Inside it run five subsystems:

  1. Channel adapters - one per platform (Baileys for WhatsApp, grammY for Telegram, etc.). Normalize inbound messages into a common format; serialize replies back out.
  2. Session manager - resolves sender identity and conversation context. DMs collapse into a main session; group chats get their own.
  3. Queue - serializes runs per session. If a message arrives mid-run, it holds, injects, or collects it for a follow-up turn.
  4. Agent runtime - assembles context (AGENTS.md, SOUL.md, TOOLS.md, MEMORY.md, daily log, conversation history), then runs the agent loop: call model, execute tool calls, feed results back, repeat until done.
  5. Control plane - WebSocket API on :18789. The CLI, macOS app, web UI, and iOS/Android nodes all connect here.

This is not “an LLM with tools.” This is a control plane with an LLM inside it. The Gateway owns session lifecycle, message routing, tool governance, and execution policy. The LLM is one component.

The Planner/Worker Pattern

Nathan Flurry’s key insight is that OpenClaw naturally acts as a planner orchestrating multiple workers:

user: a user is having a bug in project X <screenshot>
openclaw: i'll start an agent to fix that
<few minutes later>
openclaw: the bug is now fixed
user: make sure there are tests to cover this
openclaw: sends new message to background agent
<few minutes later>
openclaw: 8 tests written and passing
user: push a pr
<a few seconds later>
openclaw: here is your pr link

OpenClaw uses session_spawn to delegate coding work to background sessions. But the critical realization is that OpenClaw itself should not be the coding agent. It should delegate to proper coding harnesses (Claude Code, Codex CLI, or similar) that have better context management, compaction, and subagent support.

As Flurry notes:

“The harness matters almost as much as the model. Without a good harness, you’re missing out on better context management, better compaction, subagents, and fine-tuned system prompts.”

This is the planner/worker swarm architecture. OpenClaw is the planner and orchestrator. Coding CLIs are the workers. The orchestrator controls what gets delegated, when, and to whom. The workers control how the actual coding gets done within their bounded sessions.

The Heartbeat: Autonomous Orchestration

OpenClaw adds a dimension that other agents lack: a heartbeat scheduler. Every 30 minutes (configurable), the agent wakes up, reads a checklist from HEARTBEAT.md, and decides whether any item requires action. This is autonomous orchestration on a timer, not just reactive tool use.

The Milvus guide on OpenClaw describes it clearly:

“The Gateway runs as a background daemon with a configurable heartbeat. On each heartbeat, the agent reads a checklist from HEARTBEAT.md in the workspace, decides whether any item requires action, and either messages you or responds HEARTBEAT_OK.”

This is a cron-triggered state machine with the agent as one node in the graph.

Kimi Claw: When the Orchestrator Goes Cloud

Kimi Claw is OpenClaw running in the cloud via kimi.com, accessible through a browser tab. One-click deployment, no server setup. It demonstrates that the orchestrator pattern is portable: the same Gateway architecture that runs on your Mac Mini can run in the cloud, with the same session management, skill system, and control plane.

The Security Lesson

OpenClaw’s architecture also illustrates why orchestrator control matters for safety. The Gateway controls:

  • Which tools the agent can access
  • Which actions require human approval
  • Spending limits per provider
  • Sandbox boundaries for non-main sessions
  • DM pairing policies for channels

Without the orchestrator layer, a pure deep agent with shell access, browser control, and email sending capability is a liability. With it, you have configurable policy gates. The orchestrator is the blast radius controller.


The Hybrid Architecture: The Winning Pattern

By now the pattern should be clear across every case study. Let me state the thesis explicitly:

Deep Agents and Orchestration are not opposites. They are complementary.

  • Deep Agent: Provides creative problem-solving within the context window
  • Orchestration: Provides structure, guarantees, and bounded phases

The most effective systems use orchestration to control WHEN the deep agent runs, while letting the deep agent control WHAT it does within those bounded phases.

The Architecture Spectrum

PURE STATE MACHINE                    HYBRID                         PURE DEEP AGENT
       |                                |                                  |
       v                                v                                  v
+------------------+          +------------------+           +------------------+
| Explicit states  |          | Orchestrator     |           | while True:      |
| Fixed transitions|          | + Deep Agent     |           |   step()         |
| No LLM autonomy |          | phases           |           | LLM decides all  |
+------------------+          +------------------+           +------------------+
       |                                |                                  |
 Predictable but              Best of both:                    Flexible but
 inflexible                   Creative + Reliable              unreliable

The Winning Code Pattern

# The winning pattern:
def run(self, task):
    # Orchestrator controls the "when"
    for phase in ["understand", "plan", "implement", "test", "submit"]:
        # Deep agent controls the "how" (within bounds)
        self._run_bounded_agent_phase(phase, max_steps=...)
        # Deterministic steps between phases
        self._run_deterministic_checkpoint(phase)

When to Use Each Approach

Approach Best For Implementation
Pure Deep Agent Exploratory tasks, research, open-ended work DefaultAgent.run() as-is
Checkpointed Agent Tasks needing validation after edits Override step() with hooks
Multi-Phase Agent Tasks with distinct stages (plan/code/test) Override run() with phases
Graph Orchestrator Complex workflows with branches and retries Custom orchestrator class

The LangGraph Parallel

This hybrid pattern maps directly to how LangGraph’s Open Deep Research works. In LangGraph-style designs, the graph is the first-class runtime:

  • Typed state object that flows between nodes
  • Node functions that transform state (some LLM-powered, some deterministic)
  • Conditional edges for branching
  • Persistence and checkpointing at state boundaries
  • Human interrupts as explicit transitions

That model maps naturally to the Goose/mini-swe-agent world:

  • Session config + session DB = graph state substrate
  • Agent::reply_internal or DefaultAgent.step() = high-entropy node
  • Scheduler/CLI handlers = graph runners
  • Retry/checks = deterministic guard edges

Even if you never use LangGraph itself, adopting these graph-runtime principles in your own agent system yields the same reliability gains.


Context Management: The Hidden Challenge

There is a practical reason why orchestration matters beyond just guarantees: context window management. Deep agents accumulate context with every step:

# After 50 steps, messages might contain:
# - 1 system message
# - 1 task message
# - 50 assistant responses (with reasoning)
# - 50 observations (with command outputs)
# Total: 100+ messages, potentially 50,000+ tokens

This creates cost pressure and can exceed model context limits. Orchestration provides natural solutions:

Phase boundaries are natural compaction points. When transitioning from “understand” to “implement,” the orchestrator can summarize the understanding phase into a compact message, discarding the raw exploration steps. The agent in the “implement” phase gets a clean, focused context.

Bounded phases limit context growth. A 3-step understanding phase adds at most 6 messages. A 20-step implementation phase adds at most 40. The orchestrator controls the budget per phase rather than letting context grow unbounded.

Different phases can use different models. Stripe alludes to this. You do not need GPT-4 to run linting. The orchestrator can route cheap tasks to cheap models and reserve expensive models for creative coding. This is trivial in a state machine; it is nearly impossible to enforce in a pure agent loop.


Control Is Not the Enemy of Creativity

Let me close with the core argument of this entire post.

The next leverage point for AI agents is not a smarter model. It is not a bigger context window. It is not more tools.

The next leverage point is formalizing the outer orchestrator graph.

Goose already has a strong deep-agent core. The proposed RFC adds explicit RunState transitions and CheckReport contracts. mini-swe-agent has exception-based control flow ready to be extended into phased or graph-based orchestration. Stripe Minions proved the pattern works at the highest stakes. OpenClaw demonstrated that the pattern works as a personal AI assistant orchestrating multiple coding agents.

The pattern is the same everywhere:

  1. Orchestrator owns workflow truth: what phases run, in what order, with what budgets
  2. Deep agent owns creative problem-solving: how to understand, plan, code, and fix within bounded phases
  3. Deterministic checkpoints bridge them: lint, test, git operations that always execute, regardless of what the LLM thinks

You do not need a smarter wolf. You need a better leash.

Whether you are extending Goose with a RunState enum, building on mini-swe-agent with phased run() overrides, deploying OpenClaw as your personal orchestrator, or studying how Stripe Minions ship a thousand PRs a week, the conclusion is the same:

Give the agent freedom to think. Give the orchestrator authority to decide.


References


If you found this useful, share it with someone building agents who has not yet built the orchestrator around them.