Files
zclaw_openfang/docs/references/deerflow-toolcall-reference.md
iven c12b64150b
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
fix(runtime): 工具调用 P0 修复 — after_tool_call 接入 + stream_errored 工具抢救
P0-1: after_tool_call 中间件从未被调用
- 流式模式(run_streaming)和非流式模式(run)均添加 middleware_chain.run_after_tool_call()
- ToolErrorMiddleware 错误计数恢复逻辑现在生效
- ToolOutputGuardMiddleware 敏感信息检测现在生效

P0-2: stream_errored 跳过所有工具执行
- 新增 completed_tool_ids 跟踪哪些工具已收到完整 ToolUseEnd
- 流式错误时区分完整工具和不完整工具
- 完整工具照常执行(产物创建等不受影响)
- 不完整工具发送取消 ToolEnd 事件(前端不再卡"执行中")
- 工具执行后若 stream_errored,break outer 阻止无效 LLM 循环

参考文档:
- docs/references/zclaw-toolcall-issues.md (10项问题分析)
- docs/references/deerflow-toolcall-reference.md (DeerFlow工具调用完整参考)
2026-04-24 12:20:14 +08:00

213 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DeerFlow 工具调用系统参考文档
> 调研 DeerFlow 的工具调用完整流程,为 ZCLAW 工具调用问题排查提供参考。
> 分析日期2026-04-24
---
## 一、端到端数据流
```
用户消息
→ FastAPI Gateway (/api/threads/{id}/runs/stream)
→ services.start_run() → asyncio.create_task(run_agent(...))
→ LangGraph Agent Graph (create_agent)
→ LLM Model (ChatOpenAI / Claude)
→ AIMessage (含 tool_calls 列表)
→ 14 层 Middleware 链处理
→ ToolNode (LangGraph 内置, 按 tool_call.name 路由)
→ ToolMessage (执行结果)
→ 再次调用 LLM (带着 ToolMessage 继续)
→ StreamBridge.publish() → asyncio.Queue
→ SSE → 前端 useStream hook
→ React 组件渲染
```
## 二、工具注册与执行
### 2.1 注册入口
**文件**: `G:/deerflow/backend/packages/harness/deerflow/tools/tools.py``get_available_tools()`
工具来自四个来源:
| 来源 | 加载方式 | 示例 |
|------|----------|------|
| Config 工具 | YAML 配置 + 反射导入 (`module:variable`) | `deerflow.sandbox.tools:bash_tool` |
| Builtin 工具 | 硬编码导入 | `present_file_tool`, `ask_clarification_tool` |
| MCP 工具 | `MultiServerMCPClient` 从 MCP 服务器缓存获取 | 第三方 MCP 工具 |
| ACP 工具 | `build_invoke_acp_agent_tool()` 动态构建 | 外部 agent 调用 |
### 2.2 Sandbox 工具清单
**文件**: `G:/deerflow/backend/packages/harness/deerflow/sandbox/tools.py`
| 工具名 | 功能 |
|--------|------|
| `bash` | 沙箱中执行命令 |
| `ls` | 列出目录 |
| `read_file` | 读取文件 |
| `write_file` | 写入文件(触发产物面板自动打开) |
| `str_replace` | 字符串替换(触发产物面板自动打开) |
### 2.3 Builtin 工具
**文件**: `G:/deerflow/backend/packages/harness/deerflow/tools/builtins/`
| 工具 | 功能 |
|------|------|
| `ask_clarification` | 向用户提问澄清(中断执行等待回复) |
| `present_file` | 展示文件给用户(触发产物卡片) |
| `setup_agent` | 自定义 agent 创建 |
| `task_tool` | 子 agent 任务委派 |
| `view_image` | 图片查看(仅视觉模型) |
| `tool_search` | 延迟工具搜索MCP 工具按需暴露) |
## 三、中间件链14 层)
**文件**: `G:/deerflow/backend/packages/harness/deerflow/agents/lead_agent/agent.py``_build_middlewares()`
与工具调用相关的关键中间件:
### 3.1 DanglingToolCallMiddleware
**文件**: `dangling_tool_call_middleware.py`
`wrap_model_call` 中检测消息历史中缺失 ToolMessage 的 AIMessage自动注入占位 ToolMessage
```python
ToolMessage(
content="[Tool call was interrupted and did not return a result.]",
tool_call_id=tc_id,
name=tc.get("name", "unknown"),
status="error",
)
```
### 3.2 ToolErrorHandlingMiddleware
**文件**: `tool_error_handling_middleware.py`
`wrap_tool_call` 中捕获工具执行异常,转换为错误 ToolMessage 而非让整个 run 崩溃。
### 3.3 LoopDetectionMiddleware
**文件**: `loop_detection_middleware.py`
`after_model` 中检测重复工具调用:
- 阈值 3 次 → 注入警告 HumanMessage
- 阈值 5 次 → 直接清空 tool_calls强制 LLM 产出文本回答
### 3.4 DeferredToolFilterMiddleware
**文件**: `deferred_tool_filter_middleware.py`
`wrap_model_call` 中过滤延迟注册的 MCP 工具 schema仅在 LLM 通过 `tool_search` 发现后才暴露。
### 3.5 ClarificationMiddleware
拦截 `ask_clarification` 工具调用,中断执行等待用户回复。
### 3.6 SubagentLimitMiddleware
截断过多的并行子 agent 调用。
## 四、工具结果回传
### 4.1 格式
LangChain 的 `ToolMessage`,包含:
- `content`: 执行结果文本
- `tool_call_id`: 匹配 AIMessage 中的 tool_call ID
- `name`: 工具名称
- `status`: `"error"` 或省略
### 4.2 特殊工具
`present_file_tool` 返回 `Command` 而非纯字符串,同时更新 `artifacts``messages` 两个 state channel。
## 五、前端工具调用展示
### 5.1 消息分组
**文件**: `G:/deerflow/frontend/src/core/messages/utils.ts``groupMessages()`
| 分组类型 | 触发条件 | 展示 |
|----------|----------|------|
| `assistant:processing` | AI 消息含 tool_calls 或 reasoning | MessageGroup (折叠) |
| `assistant` | AI 消息有文本无 tool_calls | MessageListItem (气泡) |
| `assistant:present-files` | 含 present_files tool call | ArtifactFileList |
| `assistant:clarification` | ask_clarification 结果 | MarkdownContent |
| `assistant:subagent` | 含 task tool call | SubtaskCard |
### 5.2 工具状态推断
前端**没有显式状态机**。通过消息序列推断:
- AI 消息含 tool_calls 但无对应 ToolMessage → 正在执行
- ToolMessage 出现 → 执行完成
- `assistant:processing` 组由 `ChainOfThought` 折叠组件包裹
### 5.3 工具调用 UI
**文件**: `message-group.tsx` 第 186-423 行
按工具名渲染不同图标和内容:
- `bash` → 终端图标 + 命令代码块
- `read_file`/`write_file`/`str_replace` → 文件图标 + 路径链接(点击打开产物面板)
- `web_search` → 搜索图标 + 结果链接
- 默认 → 扳手图标 + 工具名
## 六、流式处理中的工具调用
### 6.1 架构
```
agent.astream(stream_mode=["values"])
→ StreamBridge (asyncio.Queue per run, maxsize=256)
→ sse_consumer() → SSE frames → 前端
```
### 6.2 关键特征
- 工具调用**不中断**流。LangGraph 自动在 agent_node 和 tool_node 之间路由
- 每次状态变更产出完整的 `values` 快照,前端通过 `seen_ids` 去重
- 15 秒心跳包保持 SSE 连接
### 6.3 前端看到的事件序列
1. `values` 事件: 含 `tool_calls` 的 AIMessage
2. `values` 事件: ToolMessage工具结果
3. `values` 事件: LLM 基于工具结果的最终回答
整个过程连续,不中断 SSE 连接。
## 七、与 ZCLAW 对比(工具调用)
| 维度 | DeerFlow | ZCLAW |
|------|----------|-------|
| 框架 | LangGraph (graph-based) | 自研 loop_runner (循环) |
| 工具生命周期 | LangGraph ToolNode 自动管理 | 手动 ToolRegistry + loop_runner |
| after_tool_call 中间件 | ✅ wrap_tool_call 钩子完整 | ❌ 流式和非流式模式均未调用 |
| 并行工具执行 | LangGraph 自动处理 | 非流式有 JoinSet流式全串行 |
| 悬挂修复 | DanglingToolCallMiddleware | DanglingToolMiddleware (有) |
| 错误恢复 | ToolErrorHandlingMiddleware (异常→ToolMessage) | ToolErrorMiddleware (计数器) |
| 循环检测 | LoopDetectionMiddleware (3次警告/5次强停) | LoopGuardMiddleware (有) |
| 前端状态 | 消息序列推断 | 显式 ToolCallStep 状态机 |
| MCP 工具 | 延迟注册 + tool_search 按需暴露 | 全量注册 |
## 八、关键文件索引
| 功能 | DeerFlow 文件 |
|------|-------------|
| Agent 工厂 | `backend/packages/harness/deerflow/agents/lead_agent/agent.py` |
| 中间件组装 | `backend/packages/harness/deerflow/agents/factory.py` |
| 工具注册 | `backend/packages/harness/deerflow/tools/tools.py` |
| Sandbox 工具 | `backend/packages/harness/deerflow/sandbox/tools.py` |
| Builtin 工具 | `backend/packages/harness/deerflow/tools/builtins/` |
| 错误处理中间件 | `agents/middlewares/tool_error_handling_middleware.py` |
| 悬挂修复中间件 | `agents/middlewares/dangling_tool_call_middleware.py` |
| 循环检测中间件 | `agents/middlewares/loop_detection_middleware.py` |
| 延迟过滤中间件 | `agents/middlewares/deferred_tool_filter_middleware.py` |
| 流式 Bridge | `runtime/stream_bridge/memory.py` |
| 前端消息分组 | `frontend/src/core/messages/utils.ts` |
| 前端工具调用组件 | `frontend/src/components/workspace/messages/message-group.tsx` |