往期推荐:
1. OpenManus架构解析
2. OpenManus代码详解(一):app/agent
3. OpenManus代码详解(二):app/flow
4. OpenManus代码详解(三):app/tool
5. OpenManus代码详解(四):app/schema.py
6. OpenManus代码详解(五):app/tool/planning.py
7. OpenManus代码详解(六):代码调用流程
官方地址:https://github.com/mannaandpoem/OpenManus
1. PlanningTool 类定义
class PlanningTool(BaseTool):
"""计划管理工具"""
name: str = "planning"
description: str = "用于创建和管理任务计划"
plans: Dict[str, Dict] = Field(default_factory=dict) # 存储所有计划
parameters: dict = {
"type": "object",
"properties": {
"command": {
"type": "string",
"enum": ["create", "get", "mark_step", "update"]
},
"plan_id": {"type": "string"},
"title": {"type": "string"},
"steps": {"type": "array", "items": {"type": "string"}},
"step_index": {"type": "integer"},
"step_status": {"type": "string"}
},
"required": ["command", "plan_id"]
}
2. 主要命令实现
2.1 创建计划
async def _create_plan(self, plan_id: str, title: str, steps: List[str]) -> Dict:
"""创建新计划"""
plan = {
"id": plan_id,
"title": title,
"steps": steps,
"step_statuses": ["not_started"] * len(steps),
"created_at": time.time()
}
self.plans[plan_id] = plan
return plan
2.2 获取计划
async def _get_plan(self, plan_id: str) -> Dict:
"""获取计划详情"""
if plan_id not in self.plans:
raise ValueError(f"Plan {plan_id} not found")
return self.plans[plan_id]
2.3 更新步骤状态
async def _mark_step(self, plan_id: str, step_index: int, step_status: str) -> Dict:
"""更新步骤状态"""
plan = await self._get_plan(plan_id)
if step_index >= len(plan["steps"]):
raise ValueError(f"Step index {step_index} out of range")
plan["step_statuses"][step_index] = step_status
return plan
3. 执行流程
- 初始化流程:
# 创建工具实例
planning_tool = PlanningTool()
# 添加到工具集合
tools = ToolCollection(planning_tool, ...)
- 创建计划流程:
# 代理调用工具创建计划
await planning_tool.execute(
command="create",
plan_id="plan_123",
title="示例计划",
steps=["步骤1", "步骤2", "步骤3"]
)
- 执行计划流程:
# 1. 获取计划
plan = await planning_tool.execute(
command="get",
plan_id="plan_123"
)
# 2. 更新步骤状态
for step_index in range(len(plan["steps"])):
# 标记步骤为进行中
await planning_tool.execute(
command="mark_step",
plan_id="plan_123",
step_index=step_index,
step_status="in_progress"
)
# 执行步骤...
# 标记步骤完成
await planning_tool.execute(
command="mark_step",
plan_id="plan_123",
step_index=step_index,
step_status="completed"
)
4. 完整调用示例
async def example_planning_flow():
# 1. 创建计划工具
planning_tool = PlanningTool()
# 2. 创建新计划
plan = await planning_tool.execute(
command="create",
plan_id="task_001",
title="开发新功能",
steps=[
"分析需求",
"设计架构",
"编写代码",
"测试验证"
]
)
# 3. 获取计划详情
current_plan = await planning_tool.execute(
command="get",
plan_id="task_001"
)
# 4. 更新第一个步骤状态
await planning_tool.execute(
command="mark_step",
plan_id="task_001",
step_index=0,
step_status="in_progress"
)
# 5. 完成第一个步骤
await planning_tool.execute(
command="mark_step",
plan_id="task_001",
step_index=0,
step_status="completed"
)
5. 状态流转
计划步骤状态的流转:
not_started -> in_progress -> completed
^ |
| v
+---- blocked ----+
6. 错误处理
async def execute(self, **kwargs) -> Any:
try:
command = kwargs.get("command")
plan_id = kwargs.get("plan_id")
if not command or not plan_id:
raise ValueError("Missing required parameters")
if command == "create":
return await self._create_plan(
plan_id=plan_id,
title=kwargs.get("title", "Untitled Plan"),
steps=kwargs.get("steps", [])
)
elif command == "get":
return await self._get_plan(plan_id)
# ... 其他命令处理
except Exception as e:
logger.error(f"Error in PlanningTool: {str(e)}")
raise
7. 与其他组件的交互
- 与 PlanningFlow 的交互:
class PlanningFlow(BaseFlow):
planning_tool: PlanningTool = Field(default_factory=PlanningTool)
async def execute(self, input_text: str) -> str:
# 创建初始计划
await self.planning_tool.execute(...)
# 执行计划步骤
while True:
step_info = await self._get_current_step_info()
if not step_info:
break
# 执行步骤
await self._execute_step(...)
- 与 Memory 的集成:
# 记录计划相关的消息
self.memory.add_message(
Message.tool_message(
content=f"Created plan: {plan['title']}",
name="planning",
tool_call_id="..."
)
)
工具提供了完整的计划管理功能,包括创建、查询、更新计划,以及跟踪每个步骤的执行状态。它与代理系统紧密集成,支持复杂任务的分解和执行跟踪。