Result Summarization
Large tool outputs are stored on disk as recallable artifacts and replaced in the context window with a short stub. When summarization is enabled, the stub’s body is produced by a cheap “summary” model instead of blunt truncation.
Implementation: crates/core/src/tools/summarize.rs (classification,
prompts, request formatting, stubs, fallback truncation) integrated through
harness.rs (handle_command_result) and handlers.rs
(handle_summarization_response).
Threshold
A tool output is summarized when its length exceeds summarize_threshold,
configurable via the summarize_threshold KDL key and defaulting to
DEFAULT_SUMMARIZE_THRESHOLD = 12000 characters. Input sent to the summary
model is capped at MAX_SUMMARIZABLE_LENGTH = 50000 characters. Summarization
can be disabled with summarize_enabled = false.
Summary models
The summary model’s provider is taken from the summary_model config (or a
summary_provider override) and resolved through the shared key chain. Default
model per provider:
| Provider | Default model |
|---|---|
| Anthropic | claude-sonnet-4-20250514 |
| OpenAI | gpt-4.1 |
| OpenRouter | openai/gpt-4.1 |
| Ollama | mistral:7b |
Requests use temperature: 0.3 and max_tokens: 2048 (or the
provider-appropriate completion-tokens parameter for OpenAI-compatible APIs).
Output classification
The tool name determines an output type, which selects a type-specific prompt
and fallback head/tail ratio (ToolOutputType::from_tool_name):
| Type | Tool names | Head ratio |
|---|---|---|
| FileContent | read, cat, __HASHLINE_READ__ | 0.7 |
| SearchResults | grep, rg, search, ast-grep | 0.5 |
| DirectoryListing | ls, find, fd, glob | 0.3 |
| CommandOutput | bash, sh (and any unknown tool) | 0.6 |
| StructuredData | nix-search, gh | 0.5 |
| WebContent | web-search, web-fetch | 0.5 |
Each type has its own prompt: command output preserves errors and exit codes verbatim, search results are grouped by file with line numbers, directory listings are grouped by kind, structured data extracts names and versions, and web content extracts main facts and quotes.
Code-file handling
For FileContent, SummarizationRequest::code_file splits the file into three
parts: a before-section and after-section (summarized) around a relevant range
that is reproduced exactly with hashlines. When no range is supplied the
relevant range defaults to the middle third of the file. The prompt instructs
the model to keep the surrounding summaries to one or two sentences and preserve
the hashline section verbatim.
Pipeline
- A tool result arrives in
handle_command_result. The full output is logged to the session’smessages.jsonlexactly once, regardless of what enters context. - If the output exceeds the threshold and the session is ready, it is stored as a disk artifact and kept in memory for UI expansion.
- If summarization is enabled, a
PendingSummaryis queued, the request is dispatched to the summary model, andset_summarizing(true)gates user input until the response returns. - In
handle_summarization_response, the lock is cleared, the provider-specific response is parsed, and the summary is wrapped in an artifact stub. On a parse failure or non-200 status,fallback_truncateis used instead.
If summarization is disabled, step 3 is skipped and the artifact stub is built
directly from fallback_truncate.
Artifact stubs and recall
format_artifact_stub wraps the summary with a header and a footer noting that
the full output is stored:
[Artifact <call_id> | <tool> | <bytes> bytes, <lines> lines]
<summary>
[Full output stored — use recall_artifact("<call_id>") to search or read more]
The agent retrieves the full output on demand through the recall_artifact
builtin tool (wire name __RECALL_ARTIFACT__), which reads or searches the
stored artifact by call_id.
Fallback truncation
fallback_truncate splits at line boundaries using the type’s head/tail ratio,
operates on character counts to stay UTF-8 safe, and inserts a
[...N chars omitted...] marker between the kept head and tail. It is used
whenever the summary model is disabled, unreachable, or returns an unparseable
response.