Skip to main content
Compact tool output lets a tool return a rich full result while the model only sees a short summary — fewer tokens per tool call, no change in default behaviour.

Quick Start

1

@tool decorator — the simplest surface

Pass to_model_output to shrink what the LLM sees.
2

BaseTool subclass — override the hook

Override to_model_output on the class.
3

Return a ToolResult carrying its own compact view

Set model_output on the ToolResult directly.

How It Works

The executor snapshots the full result for tracing and hooks, then swaps in the compact view for the LLM.

Configuration Options

No compact view declared → behaviour is exactly as before. Fully opt-in.

Resolution order

The executor picks the first hit, then falls back to the full string.

Behavioural guarantees

  • Backward compatible. No compact view → str(result) / json.dumps(...) reaches the LLM exactly as before.
  • Full result survives. The compact view swaps in after tracing, the AFTER_TOOL hook, result-aware loop detection, and the loop-guard have all seen the full payload.
  • Annotations preserved. AFTER_TOOL additional_context and loop-guard messages are mirrored onto the compact view so notices always reach the model.
  • Prompt-injection fence still applies. For external tools, wrap_if_external() wraps the compact override too — it never bypasses security markers.
  • Multimodal untouched. If the result has content, the compact view is not resolved — image/file parts flow through unchanged.
  • Overflow spill untouched. _output_overflow (see Tool Output Spill) still works; model_output composes with it.
  • Failure is soft. A raising compact-view builder degrades to the full output — never crashes the tool call.

Common Patterns

Turn a heavy result into a headline the model can plan on.
Opt-out is the default — no hook means the LLM sees the full string, as today.

User-Interaction Flow

  1. A user asks the agent to summarise a large API response.
  2. Without to_model_output: the whole 20 KB JSON enters the LLM context on every turn → token cost and slow re-planning.
  3. With to_model_output: the LLM sees "142 records, 3 anomalies"; the full JSON stays available for the display panel and any downstream tool the agent chains next.
  4. Same answer, a fraction of the tokens, unchanged code elsewhere.

Best Practices

Return the headline the model needs to decide the next step — counts, status, top items — not a raw byte-slice that hides the signal.
The full output still reaches display, hooks, and the next tool. Never fold data the agent chains on into the compact view only.
The hook runs on every call. Keep it fast and side-effect free — a raise falls back to the full output, but that silently loses the token savings.
It has the highest precedence and keeps the compact view next to the data that produced it. Reach for @tool(to_model_output=fn) for plain-return functions.

Tool Output Spill

Persist large execute_command output to disk artifacts

Multimodal Tool Output

Rich image/file parts alongside the text output

Runtime Tool Result Middleware

Cross-cutting transforms on tool results

Tool Output Store

Recover full outputs for arbitrary tool return values