Module: Tools::ResponseTruncator
- Defined in:
- lib/tools/response_truncator.rb
Overview
Truncates oversized tool results to protect the agent’s context window.
When a tool returns more characters than the configured threshold, saves the full output to a temp file and returns a truncated version: first 10 lines + notice + last 10 lines. The agent can use the read_file tool with offset/limit to inspect the full output.
Two thresholds exist:
-
**Tool threshold** (~3000 chars) — for raw tool output (bash, web, etc.)
-
**Sub-agent threshold** (~24000 chars) — for curated sub-agent results
Constant Summary collapse
- HEAD_LINES =
10- TAIL_LINES =
10- ATTRIBUTION_FORMAT =
Attribution prefix for messages routed from sub-agent to parent. Shared by Events::Subscribers::SubagentMessageRouter and MarkGoalCompleted to keep formatting consistent.
"[sub-agent @%s]: %s"- NOTICE =
<<~NOTICE.strip --- ⚠️ Response truncated (%<total>d lines total%<reason>s). Full output saved to: %<path>s Use `read_file` tool with offset/limit to inspect specific sections. --- NOTICE
Class Method Summary collapse
-
.save_full_output(content) ⇒ String
Saves full content to a temp file that persists until system cleanup.
-
.truncate(content, threshold:, reason: nil) ⇒ Object
Truncates content that exceeds the character threshold.
Class Method Details
.save_full_output(content) ⇒ String
Saves full content to a temp file that persists until system cleanup.
63 64 65 66 67 68 |
# File 'lib/tools/response_truncator.rb', line 63 def self.save_full_output(content) file = Tempfile.create(["tool_result_", ".txt"]) file.write(content) file.close file.path end |
.truncate(content, threshold:, reason: nil) ⇒ Object
Truncates content that exceeds the character threshold.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/tools/response_truncator.rb', line 42 def self.truncate(content, threshold:, reason: nil) return content unless content.is_a?(String) return content if content.length <= threshold lines = content.lines total = lines.size return content if total <= HEAD_LINES + TAIL_LINES path = save_full_output(content) head = lines.first(HEAD_LINES).join tail = lines.last(TAIL_LINES).join reason_text = reason ? " — #{reason}" : "" notice = format(NOTICE, total: total, path: path, reason: reason_text) "#{head}\n#{notice}\n\n#{tail}" end |