Skip to content

一根管道:所有工具输出都是对话

证据等级: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. 后果

  1. 噪音污染:pip 进度条、npm 依赖树、git clone 日志、AWS s3 cp 传输进度——这些对 LLM 毫无价值的信息挤占上下文窗口
  2. 无审计:工具执行结果没有独立日志,无追溯能力
  3. 死循环:压缩后关键信息丢失 → LLM 重新 read_file / execute_code → 再次膨胀

3. 与 AI Coding 的关系

  1. "工具输出 = 对话内容"是 AI 最自然的实现:不区分"结果"和"上下文",因为 API 只要求返回字符串
  2. 无审计意识:AI 不会主动说"这个输出应该同时写入日志表"——这需要架构师对可追溯性的整体判断
  3. 零加工_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]