/pattern/plan-and-execute/

01 · Single AgentPlanner-ExecutorPlan then ActTask Planning

Plan-and-Execute.
Einmal planen. Die Liste abarbeiten.

Ein Agent erstellt zunächst einen vollständigen Plan und führt die Schritte anschließend sequenziell oder kontrolliert aus.

Wann man dazu greift

  • Das Gesamtziel sich klar in testbare Teilaufgaben aufgliedern lässt.
  • Die Ausführung nachvollziehbar und zentral steuerbar sein muss.
  • Kosten oder Latenz relevant sind und LLM-Aufrufe minimiert werden sollen.

Wann es nach hinten losgeht

  • Die Umgebung hochdynamisch ist und der Plan sich aufgrund früher Tool-Ergebnisse grundlegend ändern könnte.
  • Die Aufgabe explorativ ist und der nächste Schritt vom vorherigen Ergebnis abhängt.

Die Abwägung

Bessere Struktur und Testbarkeit gegenüber ReAct, aber mit dem Risiko, dass der Agent an veralteten oder ungeeigneten Plänen festhält.

Das mentale Modell

Eine Form, die du auf eine Serviette zeichnen kannst.

Zuerst planen — in einem einzigen LLM-Aufruf — dann die notierten Schritte ausführen. Die Form der Arbeit steht fest, bevor ein Tool läuft.

PLANEXECUTEPlannerExecutorAnswer
Einmal durchspielen

Ein realer Ablauf, Schritt für Schritt.

Aufgabe"Vergleiche die Preise unserer drei größten Konkurrenten und schreibe eine Markdown-Zusammenfassung."
1 / 6
Plan"1. Die drei größten Konkurrenten in unserem Segment identifizieren. 2. Jede Preisseite abrufen. 3. Den Einstiegstarif extrahieren. 4. Einen Markdown-Vergleich erstellen."
Schritt 1market_research(segment="b2b-saas") → ["AcmeCorp", "BetaInc", "GammaCo"]
Schritt 2parallel.fetch_page([acmecorp.com/pricing, beta.com/pricing, gamma.co/pricing])
Schritt 3extract_entry_price(pages) → { Acme: €29, Beta: €35, Gamma: €19 }
Schritt 4render_markdown(prices) → "| Anbieter | Einstiegstarif |..."
AntwortMarkdown-Vergleich geliefert. Gesamt: 1 Planungsaufruf + 4 Tool-Aufrufe + 0 Denkschritte dazwischen.
Im Code

Die Schleife ist schon eingebaut.

LangGraphpython
class State(TypedDict):
    goal: str
    plan: list[str]
    done: list[tuple[str, str]]
    result: str | None

def make_plan(state):
    plan = planner_llm.invoke(state["goal"]).steps
    return {"plan": plan}

def run_step(state):
    step = state["plan"][0]
    output = executor.invoke(step, context=state["done"])
    return {
        "plan": state["plan"][1:],
        "done": state["done"] + [(step, output)],
    }

graph = StateGraph(State)
graph.add_node("planner", make_plan)
graph.add_node("executor", run_step)
graph.add_edge("planner", "executor")
graph.add_conditional_edges(
    "executor",
    lambda s: "executor" if s["plan"] else END,
)
Fallstricke

Drei Wege, wie dieses Pattern Probleme verursachen kann.

Veralteter Plan

Ein früher Schritt liefert etwas zurück, das der Planer nicht vorhergesehen hat — eine leere Liste, ein 404, ein anderes Schema. Der Plan läuft trotzdem weiter, mit falschen Eingaben.

Lösung · Einen Neuplanungs-Trigger einbauen. Die Ausgabe jedes Schritts gegen die Annahme des Planers validieren; bei Ungültigkeit die Kontrolle zurück an den Planer übergeben.

Kaskadierte Fehler

Schritt 2 liest die Ausgabe von Schritt 1 falsch. Schritt 3 baut auf dem Fehler auf. Bei Schritt 4 löst der Agent ein anderes Problem.

Lösung · Pydantic-Schemas an jeder Schrittgrenze. Günstige Validatoren sind mehr wert als teure Neuplanung.

Überambitionierter Planer

Der Planer schreibt einen ambitionierten 12-Schritte-Plan für eine Aufgabe, die wahrscheinlich drei benötigt hätte. Die Ausführungskosten übersteigen die Einsparungen gegenüber ReAct.

Lösung · Die Planlänge im Planer-Prompt begrenzen. Kürze belohnen; spekulative Schritte bestrafen.

Framework-Unterstützung

Wo Plan-and-Execute nativ ist.

LangGraphplan-and-execute prebuiltNativ
CrewAINativ
Microsoft Agent FrameworkNativ
OpenAI Agents SDKals Zwei-Phasen-Agent realisierbarAnpassbar

Suche

Patterns, Frameworks und Seiten durchsuchen.