一根管道:所有工具输出都是对话¶
证据等级:F(源码直接证明)
分析基线:4f843556
一句话¶
Clawith 的所有工具输出都通过同一根管道注入 messages[],没有"执行结果"和"对话上下文"的区分。execute_code 的 stdout、read_file 的文件内容、web_search 的搜索结果——全部作为 role="tool" 消息永久留在对话里。
1. 工具输出 → messages[] 的完整路径¶
# agent_tools.py — 所有工具 _outcome 函数
result = await backend._format_result(result) # base.py:117-124
return _typed_success(result) # agent_tools.py
# base.py:117-124
def _format_result(self, result):
parts = []
if result.stdout:
parts.append(f"📤 Output:\n{result.stdout}")
if result.stderr:
parts.append(f"\n⚠️ Stderr:\n{result.stderr}")
return "\n".join(parts)
# caller.py:621-835
api_messages.append(LLMMessage(role="tool", content=output))
涉及的输出大小¶
| 场景 | 后端 | 上限 |
|---|---|---|
| execute_code | subprocess | stdout 1MB / stderr 500KB |
| execute_code | Docker | stdout 10K 字符 / stderr 5K 字符 |
| execute_code | base._format_result | 无截断(subprocess 路径) |
| read_file | — | 默认 2000 行,无字符上限 |
| jina_read | — | 默认 8K,最大 20K 字符 |
| web_search | — | 最多 10 条结果 |
无独立日志¶
execute_code 的 stdout/stderr 不持久化到任何审计表。只在 messages[] 里。对话一旦压缩或丢失,执行日志就彻底消失。
2. 后果¶
- 噪音污染:pip 进度条、npm 依赖树、git clone 日志、AWS s3 cp 传输进度——这些对 LLM 毫无价值的信息挤占上下文窗口
- 无审计:工具执行结果没有独立日志,无追溯能力
- 死循环:压缩后关键信息丢失 → LLM 重新 read_file / execute_code → 再次膨胀
3. 与 AI Coding 的关系¶
- "工具输出 = 对话内容"是 AI 最自然的实现:不区分"结果"和"上下文",因为 API 只要求返回字符串
- 无审计意识:AI 不会主动说"这个输出应该同时写入日志表"——这需要架构师对可追溯性的整体判断
- 零加工:
_typed_success(full_output)是最简单的写法——不加截断、不加摘要、不加结构化
代码引用¶
| 文件 | 行号 | 关键内容 |
|---|---|---|
agent_tools.py |
全文件 | 所有 _*_outcome 返回 _typed_success(full_output) |
caller.py |
621-835 | api_messages.append(role="tool", content=...) |
base.py |
117-127 | _format_result 拼接 stdout/stderr |
subprocess_backend.py |
16-17 | MAX_STDOUT_CAPTURE_BYTES = 1_000_000 |
docker_backend.py |
176-177 | stdout[:10000], stderr[:5000] |