Planning Agent Replan
Planning agent replan example.
Planning Agent with failure and replanning scenarios.
Run it
python examples/ai/planning_agent_replan.py
"""
Planning Agent with failure and replanning scenarios.
Demonstrates how an agent handles tool failures, adapts its plan,
and uses dependency results from previous steps.
Key scenarios tested:
- Tool that fails intermittently (simulates API errors)
- Agent replans when a step reveals new information
- Dependency results flow between steps via enriched summaries
Prerequisites:
1. Install Ollama: https://ollama.ai
2. Pull a model: ollama pull qwen3
3. Start Ollama service: ollama serve
Usage:
python examples/ai/planning_agent_replan.py
"""
from __future__ import annotations
from typing import Any
from flux import ExecutionContext, task, workflow
from flux.tasks.ai import agent
# Simulate intermittent failures
_call_count: dict[str, int] = {}
@task
async def search_database(query: str) -> str:
"""Search the internal database for records matching the query."""
_call_count.setdefault("search_database", 0)
_call_count["search_database"] += 1
# Fail on first call to simulate a transient error
if _call_count["search_database"] == 1:
raise ConnectionError(f"Database connection timeout for query: {query}")
return (
f"Database results for '{query}':\n"
f"- Record 1: Product A, revenue $2.3M, growth 15%\n"
f"- Record 2: Product B, revenue $1.8M, growth -3%\n"
f"- Record 3: Product C, revenue $4.1M, growth 22%"
)
@task
async def search_web(query: str) -> str:
"""Search the web for public information about a topic."""
return (
f"Web results for '{query}':\n"
f"- Industry report: Market growing at 18% CAGR\n"
f"- News: Company X acquired Company Y for $500M\n"
f"- Analysis: Top 3 players control 70% market share"
)
@task
async def analyze_data(data: str, focus: str) -> str:
"""Analyze data with a specific focus area and produce insights."""
return (
f"Analysis (focus: {focus}):\n"
f"- Key finding: Strong growth in premium segment\n"
f"- Risk: Product B declining, needs attention\n"
f"- Opportunity: Market consolidation creates acquisition targets\n"
f"- Recommendation: Invest in Product C's growth trajectory"
)
@task
async def generate_report(title: str, sections: str) -> str:
"""Generate a structured report with the given title and section content."""
return (
f"# {title}\n\n"
f"## Key Findings\n{sections}\n\n"
f"## Recommendations\n"
f"1. Accelerate Product C investment\n"
f"2. Review Product B strategy\n"
f"3. Explore acquisition opportunities\n"
)
@workflow
async def planning_agent_replan(ctx: ExecutionContext[dict[str, Any]]):
"""
A planning agent that handles failures and replans.
Input format:
{
"topic": "quarterly business review"
}
"""
_call_count.clear()
input_data = ctx.input or {}
topic = input_data.get("topic", "quarterly business review")
analyst = await agent(
"You are a business analyst. Always use your tools to accomplish tasks. "
"Never describe what you would do — actually do it by calling tools. "
"For multi-step tasks, create a plan first using create_plan, then "
"call start_step before working on each step. Mark steps done with mark_step_done, "
"or mark_step_failed if they cannot be completed. Use get_ready_steps to see what "
"can be started next. If a tool fails, retry it or adjust your plan.",
model="ollama/qwen3",
name="replan-analyst",
tools=[search_database, search_web, analyze_data, generate_report],
planning=True,
max_tool_calls=30,
)
response = await analyst(
f"Prepare a {topic} report. You need to: "
f"1) Gather internal data from the database "
f"2) Gather market data from the web "
f"3) Analyze all gathered data together "
f"4) Generate a final report. "
f"Create a plan with these steps. The analysis step should depend "
f"on both data gathering steps. The report should depend on analysis.",
)
return {
"topic": topic,
"response": response,
"tool_calls": dict(_call_count),
"execution_id": ctx.execution_id,
}
if __name__ == "__main__": # pragma: no cover
topic = "Quarterly Business Review"
try:
print("=" * 80)
print("Planning Agent with Replan Demo")
print(f"Topic: {topic}")
print("=" * 80 + "\n")
print("Running agent (first search_database call will fail)...\n")
result = planning_agent_replan.run({"topic": topic})
if result.has_failed:
raise Exception(f"Workflow failed: {result.output}")
output = result.output
print(f"Topic: {output.get('topic')}")
print(f"Tool calls: {output.get('tool_calls')}")
print(f"Execution ID: {output.get('execution_id')}\n")
print("-" * 80)
print(output.get("response", ""))
print("-" * 80)
except Exception as e:
print(f"Error: {e}")
print("\nMake sure:")
print("1. Ollama is running: ollama serve")
print("2. Model is pulled: ollama pull qwen3")
Last verified against Flux 0.56.0.