Tool Call Role Design: Claude Code vs Codex

2026-05-22#agent-runtime#tool-call#role-design#claude-code#codex

Background

The question under discussion: why do Claude Code / Anthropic tool results appear to live in role: user, while Codex / the OpenAI Responses API treats tool calls and tool results more like independent events.

To be precise:

  • Claude does not define the tool call itself as user. Claude's tool call is an assistant-side tool_use.
  • What goes into role: user is the post-execution tool_result.
  • That user is not a human user; it is closer to the client / environment side handing external observations back to the model.

Core judgment

Claude's design reads as a "conversational input stream":

  • assistant: what the model itself says, and its own tool_use
  • user: new input from the outside world to the model — human messages, environment context, tool results
  • tool_result is matched to the earlier tool call via content block type and tool_use_id

The upside is a simple schema, a direct conversation loop, and unified content blocks. The cost is transcript readability: much of what sits under role: user is not human speech but tool observations — shell output, file reads, MCP responses.

Codex / OpenAI Responses reads as an "agent event stream":

  • user messages are still role: user
  • the model requesting a tool is a function_call
  • the tool's return is a function_call_output
  • the two are matched by call_id

The upside is clearer auditing, replay, state machines and permission analysis. Tool output doesn't blend into the user role; the role system mainly expresses instruction authority, and tool output is observation. The cost is a more complex protocol — adapting other models or frameworks means handling typed items.

In one sentence:

Claude puts tool results into the conversational input stream; Codex puts them into the agent event stream.

What each fits

Claude's approach fits:

  • quickly implementing an assistant tool_use -> client execute -> user tool_result -> assistant continue loop
  • a two-role message schema without inventing extra roles
  • putting text, images, tool calls and tool results all into one unified content block

Codex's approach fits:

  • complex local agent runtimes
  • event auditing for multi-tool, multi-round execution, approvals, sandboxes, sub-agents
  • treating tool output as a traceable observation instead of mixing it into human/user messages
  • later work on Trace Logs, replay, compression, and permission-boundary analysis

Article angles worth developing

This could become an article about the representation layer of agent runtimes; tentative angle:

  • Title direction: Conversation stream or event stream: where do agent tool results belong
  • Central question: is a tool result user input, an environment observation, or an agent runtime event?
  • Core tension: a simple API schema versus a long-term auditable runtime
  • Extends the existing Trace Log thread: a good Trace Log doesn't just record final output — it must distinguish human instructions, system constraints, model decisions, tool observations and environment side effects

Open questions

  • If tool output contains a prompt injection, is it more easily mistaken for high-authority instruction under role: user?
  • Should a home-grown agent harness define an explicit observation / tool_result layer instead of reusing user?
  • How should a Trace Log stay human-readable while remaining structured enough for the model to keep consuming?