分享|Agent 流式输出时,工具能立刻执行吗?
159
发布于 北京

1784552261-EcyNJv-1000091501.gif

很多人会答:

模型都已经开始输出 tool call 了,当然一边收一边执行,速度更快。

不够。

因为模型流式吐出来的,可能只是半截参数。

比如它最终想读一个文件,过程中可能先吐:

{"pa

然后才陆续补上:

th":"firstcoder/agent/loop.py"}

如果你一边收到,一边解析、一边执行:

• 参数可能还没收全

• tool name 和 call id 可能还没到

• 流中断了,也不知道这次调用到底完整没有

• 更糟的是,半截请求可能已经产生副作用

🎯 这题为什么容易翻车?

因为很多人把两件事混在一起了:

• 文本回答可以渐进展示

• 工具调用必须完整后再执行

前者是用户体验问题。

后者是执行正确性问题。

模型说一句话,说到一半停了,最多是回答没显示完。

但模型调用一个工具,参数说到一半就执行,可能就是读错文件、发错请求,甚至执行错命令。

💡 怎么处理?

不让 TUI 直接处理不同模型厂商返回的原始流。

而是先统一成内部事件:

message_started

→ reasoning_delta

→ text_delta

→ tool_call_started

→ tool_call_delta

→ tool_call_completed

→ message_completed

这样 UI 可以实时显示:

• 模型正在输出什么

• 是否正在思考

• 是否正在组装工具调用

但“看得到工具调用片段”,不等于“现在就去执行”。

真正的链路是:

Provider 原始流

→ 按 tool call 的 index 累积分片

→ 收集 id、name、arguments

→ 等流结束

→ 确认 finish_reason 是 tool_calls

→ 校验 arguments 是完整 JSON

→ 生成完整 ToolCall

→ 再进入权限和执行链

关键点:

只有到了 tool_call_completed,才是一个能执行的工具调用。

🛡 不完整的调用怎么处理?

FirstCoder 这里走的是保守策略:

• 少了 id、name 或 arguments:整组丢弃

• arguments 不是合法 JSON object:丢弃

• 最后不是以 tool_calls 结束:前面收到的工具片段也丢弃

• 只有完整 ToolCall,才会继续走 Permission 和 executor

这比“尽量解析一下,能执行就执行”慢一点。

但 agent 这种会产生副作用的系统,宁可少执行,也不能错执行。

📚 一句话总结

流式输出可以边到边展示。

但工具调用必须:收齐、校验、确认结束,再执行。

🔗 开源地址

https://github.com/KomorGiaoGiao/FirstCoder

欢迎 star⭐和提issue,一起把项目做得更好!

评论 (0)