Note
Go to the end to download the full example code.
Plan¶
The Plan Module enables agents to formally break down complex tasks into manageable sub-tasks and execute them systematically. Key features include:
Support manual plan specification
- Comprehensive plan management capabilities:
Creating, modifying, abandoning, and restoring plans
Switching between multiple plans
Gracefully handling interruptions by temporarily suspending plans to address user queries or urgent tasks
Real-time visualization and monitoring of plan execution
Note
The current plan module has the following limitations, and we are working on improving them:
The subtasks in a plan must be executed sequentially
Specifically, the plan module works by
providing tool functions for plan management
inserting hint messages to guide the ReAct agent to complete the plan
The following figure illustrates how the plan module works with the ReAct agent:

How the plan module works with the ReAct agent¶
import asyncio
import os
from agentscope.agent import ReActAgent
from agentscope.formatter import DashScopeChatFormatter
from agentscope.model import DashScopeChatModel
from agentscope.plan import PlanNotebook, Plan, SubTask
PlanNotebook¶
The PlanNotebook class is the core of the plan module, responsible for providing
plan-related tool functions
hint messages to guide the agent to finish the plan
The PlanNotebook class can be instantiated with the following parameters:
Name |
Type |
Description |
---|---|---|
|
|
The maximum number of subtasks allowed in a plan, infinite if None |
|
|
The function to generate hint message based on the current plan. If not provided, a default DefaultPlanToHint object will be used. |
|
|
The plan storage. If not provided, a default in-memory storage will be used. |
The plan_to_hint
callable object is the most important part of the
PlanNotebook class, also serves as the interface for prompt engineering.
We have built a default DefaultPlanToHint class that can be used directly.
Developers are encouraged to providing their own plan_to_hint
function
for better performance.
The storage
is to store historical plans, allowing agent to
retrieve and restore historical plans. Developers are encouraged to
implement their own plan storage by inheriting the PlanStorageBase
class.
If not provided, a default in-memory storage will be used.
Tip
The PlanStorageBase
class inherits from the StateModule
class, so that the plan storage will also be saved and loaded by the
session management.
The core attributes and methods of the PlanNotebook class are summarized as follows:
Type |
Name |
Description |
---|---|---|
attribute |
|
The current plan that the agent is executing |
|
The storage for historical plans, used for retrieving and restoring historical plans |
|
|
A callable object that takes the current plan as input and generates a hint message to guide the agent to finish the plan |
|
method |
|
List all the tool functions provided by the PlanNotebook class |
|
Get the hint message for the current plan, which will call the |
|
create_plan ,view_subtasks ,revise_current_plan ,update_subtask_state ,finish_subtask ,finish_plan ,view_historical_plans ,recover_historical_plan |
The tool functions that allows the agent to manage the plan and subtasks |
|
|
Register a hook function that will be called when the plan is changed, used to plan visualization and monitoring |
|
|
Remove a registered plan change hook function |
The list_tools
method is a quick way to obtain all tool functions, so that you can register them to the agent’s toolkit.
plan_notebook = PlanNotebook()
async def list_tools() -> None:
"""List the tool functions provided by PlanNotebook."""
print("The tools provided by PlanNotebook:")
for tool in await plan_notebook.list_tools():
print(tool.__name__)
asyncio.run(list_tools())
The tools provided by PlanNotebook:
view_subtasks
update_subtask_state
finish_subtask
create_plan
revise_current_plan
finish_plan
view_historical_plans
recover_historical_plan
Working with ReActAgent¶
The ReActAgent in AgentScope has integrated the plan module by a plan_notebook
parameter in its constructor.
Once provided, the agent will
be equipped with the plan management tool functions, and
be inserted with the hint messages at the beginning of each reasoning step
There are two ways to use the plan module with the ReActAgent:
Manual plan specification: Users can manually create a plan by calling the
create_plan
tool function, and initialize the ReActAgent with the plan notebook.Agent-managed plan execution: The agent will create and manage the plan by itself, by calling the plan management tool functions.
Manual Plan Specification¶
Manually creating a plan is straightforward by calling the create_plan
tool function.
The following is an example of manually creating a plan to conduct a comprehensive research on the LLM-empowered agent.
async def manual_plan_specification() -> None:
"""Manual plan specification example."""
await plan_notebook.create_plan(
name="Research on Agent",
description="Conduct a comprehensive research on the LLM-empowered agent.",
expected_outcome="A Markdown format report answer three questions: 1. What's agent? 2. What's the current state of the art of agent? 3. What's the future trend of agent?",
subtasks=[
SubTask(
name="Search agent-related survey papers",
description=(
"Search for survey parers on multiple sources, including "
"Google Scholar, arXiv, and Semantic Scholar. Must be "
"published after 2021 and have more than 50 citations."
),
expected_outcome="A paper list in Markdown format",
),
SubTask(
name="Read and summarize the papers",
description=(
"Read the papers found in the previous step, and "
"summarize the key points, including the definition, "
"taxonomy, challenges, and key directions."
),
expected_outcome="A summary of the key points in Markdown format",
),
SubTask(
name="Research on recent advances of large company",
description=(
"Research on the recent advances of large companies, "
"including Google, Microsoft, OpenAI, Anthropic, Alibaba "
"and Meta. Find the official blogs or news articles."
),
expected_outcome="A recent advances of large company ",
),
SubTask(
name="Write a report",
description=(
"Write a report based on the previous steps, and answer "
"the three questions in the expected outcome."
),
expected_outcome=(
"A Markdown format report answer three questions: 1. "
"What's agent? 2. What's the current state of the art of "
"agent? 3. What's the future trend of agent?"
),
),
],
)
print("The current hint message:\n")
msg = await plan_notebook.get_current_hint()
print(f"{msg.name}: {msg.content}")
asyncio.run(manual_plan_specification())
The current hint message:
user: <system-hint>The current plan:
```
# Research on Agent
**Description**: Conduct a comprehensive research on the LLM-empowered agent.
**Expected Outcome**: A Markdown format report answer three questions: 1. What's agent? 2. What's the current state of the art of agent? 3. What's the future trend of agent?
**State**: todo
**Created At**: 2025-09-15 07:48:55.020
## Subtasks
- [ ] Search agent-related survey papers
- [ ] Read and summarize the papers
- [ ] Research on recent advances of large company
- [ ] Write a report
```
Your options include:
- Mark the first subtask as 'in_progress' by calling 'update_subtask_state' with subtask_idx=0 and state='in_progress', and start executing it.
- If the first subtask is not executable, analyze why and what you can do to advance the plan, e.g. ask user for more information, revise the plan by calling 'revise_current_plan'.
- If the user asks you to do something unrelated to the plan, prioritize the completion of user's query first, and then return to the plan afterward.
- If the user no longer wants to perform the current plan, confirm with the user and call the 'finish_plan' function.
</system-hint>
After creating the plan, you can initialize the ReActAgent with the plan notebook as follows:
agent = ReActAgent(
name="Friday",
sys_prompt="You are a helpful assistant.",
model=DashScopeChatModel(
model_name="qwen-max",
api_key=os.environ["DASHSCOPE_API_KEY"],
),
formatter=DashScopeChatFormatter(),
plan_notebook=plan_notebook,
)
Agent-Managed Plan Execution¶
Agent can also create and manage the plan by itself, by calling the plan management tool functions. We just need to initialize the ReActAgent with the plan notebook as follows:
agent = ReActAgent(
name="Friday",
sys_prompt="You are a helpful assistant.",
model=DashScopeChatModel(
model_name="qwen-max",
api_key=os.environ["DASHSCOPE_API_KEY"],
),
formatter=DashScopeChatFormatter(),
plan_notebook=PlanNotebook(),
)
After that, we can build a loop to interact with the agent as follows. Once the task is complex, the agent will create a plan by itself and execute the plan step by step.
async def interact_with_agent() -> None:
"""Interact with the plan agent."""
user = UserAgent(name="user")
msg = None
while True:
msg = await user(msg)
if msg.get_text_content() == "exit":
break
msg = await agent(msg)
asyncio.run(interact_with_agent())
Plan Visualization and Monitoring¶
AgentScope supports real-time visualization and monitoring of the plan execution by the plan change hook function.
They will be triggered when the plan is changed by calling the tool functions. A template of the plan change hook function is as follows:
def plan_change_hook_template(self: PlanNotebook, plan: Plan) -> None:
"""A template of the plan change hook function.
Args:
self (`PlanNotebook`):
The PlanNotebook instance.
plan (`Plan`):
The current plan instance (after the change).
"""
# Forward the plan to the frontend for visualization or other processing
Total running time of the script: (0 minutes 0.029 seconds)