PlanningAgent Documentation¶
PlanningAgent generates a structured plan for a user request, optionally reflects on that plan, and regenerates it until the reflection budget is exhausted or the plan is approved.
Use it when you want an ordered, model-generated plan before handing work to another agent such as ExecutionAgent.
Basic usage¶
from langchain.chat_models import init_chat_model
from ursa.agents import PlanningAgent
llm = init_chat_model("openai:gpt-5.4-mini")
agent = PlanningAgent(llm=llm)
state = agent.invoke("Design a workflow to compare two simulation outputs.")
print(agent.format_result(state))
The parsed plan is available as state["plan"].
plan = state["plan"]
for step in plan.steps:
print(step.name, step.requires_code)
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
llm |
BaseChatModel |
required | Language model used for plan generation and reflection. |
max_reflection_steps |
int |
1 |
Maximum number of reflection passes before ending unless the plan is approved sooner. |
**kwargs |
dict |
{} |
Passed to BaseAgent, including workspace, persistence, group, thread/checkpoint, and metrics options. |
Structured output¶
Planning uses structured output with this schema:
class PlanStep(BaseModel):
name: str
description: str
requires_code: bool
expected_outputs: list[str]
success_criteria: list[str]
class Plan(BaseModel):
steps: list[PlanStep]
Plan.__str__() formats the plan as Markdown-like text with each step's title, code requirement, description, expected outputs, and success criteria. agent.format_result(state) returns that formatted string.
Graph behavior¶
The current graph has two nodes:
generate— produces a structuredPlanusing the planner prompt.reflect— critiques the current plan using the reflection prompt.
The workflow is:
generatecreates or regenerates aPlanand stores it instate["plan"].- If
reflection_steps > 0, the graph routes toreflect. reflectreviews the plan and decrementsreflection_steps.- If the reflection text contains
[APPROVED], the graph finishes. - Otherwise, the graph routes back to
generatefor another pass. - When the reflection budget reaches zero, the graph finishes with the latest plan.
If a provider returns an empty reflection message, the implementation treats it as [APPROVED].
State model¶
PlanningState includes:
plan— parsedPlanobject.messages— LangChain message history used by generation/reflection.reflection_steps— remaining reflection passes.
Custom reflection budget¶
from langchain.chat_models import init_chat_model
from ursa.agents import PlanningAgent
llm = init_chat_model("openai:gpt-5.4-mini")
agent = PlanningAgent(llm=llm, max_reflection_steps=3)
state = agent.invoke("Plan a validation study for a new materials model.")
print(agent.format_result(state))
Higher reflection budgets can improve plan quality but increase latency and token usage.