Skip to content

One Pipe: Every Tool Output Is a Conversation

Evidence Level: F (directly proven by source code)
Analysis Baseline: 4f843556


TL;DR

All tool outputs in Clawith flow through a single pipe into messages[], with no distinction between "execution result" and "conversation context." execute_code stdout, read_file contents, web_search results—all injected as role="tool" messages and permanently embedded in the conversation.


1. The Full Path: Tool Output → messages[]

# agent_tools.py — all tool _outcome functions
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))

Output Size Limits

Scenario Backend Limit
execute_code subprocess stdout 1MB / stderr 500KB
execute_code Docker stdout 10K chars / stderr 5K chars
execute_code base._format_result No truncation (subprocess path)
read_file Default 2000 lines, no char limit
jina_read Default 8K, max 20K chars
web_search Max 10 results

No Independent Logging

execute_code stdout/stderr is never persisted to any audit table. It lives only in messages[]. If the conversation is compressed or lost, the execution log is gone forever.


2. Consequences

  1. Noise pollution: pip progress bars, npm dependency trees, git clone logs, AWS s3 cp transfer progress—information worthless to the LLM—crowd the context window
  2. No audit trail: tool execution results have no independent log, no traceability
  3. Death loop: compression loses critical info → LLM re-reads files / re-executes code → expansion again

3. Relationship to AI Coding

  1. "Tool output = conversation" is AI's most natural implementation: no distinction between "result" and "context," because the API only requires returning a string
  2. No audit awareness: AI won't proactively say "this output should also be written to a log table"—that requires an architect's holistic judgment about traceability
  3. Zero processing: _typed_success(full_output) is the simplest possible implementation—no truncation, no summarization, no structuring

Code References

File Lines Key Content
agent_tools.py throughout All _*_outcome return _typed_success(full_output)
caller.py 621-835 api_messages.append(role="tool", content=...)
base.py 117-127 _format_result concatenates stdout/stderr
subprocess_backend.py 16-17 MAX_STDOUT_CAPTURE_BYTES = 1_000_000
docker_backend.py 176-177 stdout[:10000], stderr[:5000]