Skip to content

工具 Handlers(默认与替换)

适用版本:v4.0.8.2

Tool Loop 的扩展点很少,核心就两个:

  1. plan_analysis_handler
  2. tool_execution_handler

1. 默认 handler 链与可替换点

如何阅读这张图

  • 规划器和执行器是两个明确断点,分别对应“决策”和“副作用”。
  • 结果注入不是第三个可替换 handler,而是框架稳定协议的一部分,所以建议保留默认行为。

架构思路

最重要的边界不是“能不能自定义”,而是“不要把推理逻辑和副作用混在一个 handler 里”。否则后续很难追踪到底是规划错了,还是执行层失控了。

2. plan_analysis_handler

职责:

  • 决定本轮是 execute 还是 response
  • 产出 execution_commands[]

签名:

python
async def custom_plan_handler(
    prompt,
    settings,
    tool_list,
    done_plans,
    last_round_records,
    round_index,
    max_rounds,
    agent_name,
): ...

推荐返回:

python
{
    "next_action": "execute" | "response",
    "execution_commands": [
        {
            "purpose": str,
            "tool_name": str,
            "tool_kwargs": dict,
            "todo_suggestion": str,
        }
    ],
}

3. tool_execution_handler

职责:

  • 执行 execution_commands
  • 返回可审计的执行记录

签名:

python
async def custom_execution_handler(
    tool_commands,
    settings,
    async_call_tool,
    done_plans,
    round_index,
    concurrency,
    agent_name,
): ...

推荐返回:

python
[
    {
        "purpose": str,
        "tool_name": str,
        "kwargs": dict,
        "todo_suggestion": str,
        "success": bool,
        "result": Any,
        "error": str,
    }
]

4. 默认行为有哪些

默认规划器:

  • 使用独立 ModelRequest
  • 监听 instant.next_action
  • next_action=response 时提前短路

默认执行器:

  • 使用 tool.loop.concurrency 做并发控制
  • 逐条调用 async_call_tool(...)
  • 对错误字符串自动标注 success=False

5. 在 Agent 层替换

python
from agently import Agently

agent = Agently.create_agent()

agent.register_tool_plan_analysis_handler(custom_plan_handler)
agent.register_tool_execution_handler(custom_execution_handler)

恢复默认:

python
agent.register_tool_plan_analysis_handler(None)
agent.register_tool_execution_handler(None)

6. 在 Core 层全局替换

python
from agently import Agently

Agently.tool.register_plan_analysis_handler(custom_plan_handler)
Agently.tool.register_tool_execution_handler(custom_execution_handler)

7. 设计建议

  • 规划器只做决策,不直接执行副作用
  • 执行器只做执行,不重复业务推理
  • 统一用 execution_commands 作为主输出协议
  • 返回值尽量保留 purpose/tool_name/result/error
  • todo_suggestion 保持可读,它会影响下一轮规划