Goal
Reduce token waste from stubbed tool results. Currently each stubbed result costs ~18 tokens for text the LLM cannot act on. Replace with compact turn-scoped pointers (~3-5 tokens) and add a system prompt section teaching the LLM how to dereference them.
Context
The assembler's message transform (context/assembler/message-transform.ts) stubs tool results outside the hot window with:
[source: tool:read, tool:grep | Content replaced — available via re-execution]
This is ~18 tokens per stub. In a 300-turn session with ~400 stubbed tool results, that's ~7,200 tokens of dead weight — pointers the LLM cannot dereference.
The bridge already generates locator entries with structured metadata (tool name, file paths, retrieval recipe). The stub text ignores all of this except the tool name.
Current flow
- Bridge observes tool result, creates
MemoryLocatorEntry with key, where, how
- Message transform stubs the result: content replaced with
formatStubText(sourceTags)
- LLM sees dead text it can't use
- Original content still lives in
agent.state.messages — fully recoverable
Proposed flow
- Bridge observes tool result, creates
MemoryLocatorEntry (unchanged)
- Message transform stubs with compact pointer:
[ref:t42:read:src/parser.ts] or similar
- System prompt teaches the LLM: "Stubbed results show as
[ref:tN:tool:path]. To recover content, use the recall tool or re-execute the original tool."
- LLM can now make informed decisions about which stubs to recover
Acceptance Criteria
Technical Notes
Files to modify
packages/coding-agent/src/context/assembler/message-transform.ts — formatStubText(), replaceToolResultContent()
packages/coding-agent/src/context/assembler/message-transform.ts — transformMessages() needs access to bridge locator data to enrich stubs
- System prompt template (likely
prompts/system/ or assembled sections) — add stub pointer documentation
packages/coding-agent/src/context/bridge/bridge.ts — may need to expose locator lookup by tool_use_id
Pointer format options
Minimal: [t42] (~2 tokens) — turn number only, LLM infers tool from conversation structure
Compact: [t42:read:src/parser.ts] (~5 tokens) — turn + tool + primary path
Rich: [t42:read:src/parser.ts:L50-80] (~7 tokens) — includes line range
Recommendation: start with compact. The tool name and path give the LLM enough to decide whether to recover the content without looking at the full result.
Integration with bridge
The message transform currently operates independently of the bridge — it only knows about messages, not locator entries. To produce enriched stubs, the transform needs a lookup function: given a tool_use_id, return the locator entry's metadata. This could be:
- A callback passed via
MessageTransformOptions
- Direct access to the bridge's locator map
- Pre-computed metadata attached to the message during bridge observation
Edge cases
- Tool results without locator entries (tools the bridge doesn't classify) — fall back to current stub format
- Multiple tool results in a single turn — each gets its own pointer
- System prompt token budget — the stub documentation section should be small (<100 tokens)
Trade-offs Accepted
- Compact pointers lose the source provenance tags ("source: tool:read, tool:grep") — acceptable because the pointer encodes more useful info (turn + path)
- Adds coupling between message transform and bridge locator data — acceptable because they're already part of the same assembler subsystem
Goal
Reduce token waste from stubbed tool results. Currently each stubbed result costs ~18 tokens for text the LLM cannot act on. Replace with compact turn-scoped pointers (~3-5 tokens) and add a system prompt section teaching the LLM how to dereference them.
Context
The assembler's message transform (
context/assembler/message-transform.ts) stubs tool results outside the hot window with:This is ~18 tokens per stub. In a 300-turn session with ~400 stubbed tool results, that's ~7,200 tokens of dead weight — pointers the LLM cannot dereference.
The bridge already generates locator entries with structured metadata (tool name, file paths, retrieval recipe). The stub text ignores all of this except the tool name.
Current flow
MemoryLocatorEntrywithkey,where,howformatStubText(sourceTags)agent.state.messages— fully recoverableProposed flow
MemoryLocatorEntry(unchanged)[ref:t42:read:src/parser.ts]or similar[ref:tN:tool:path]. To recover content, use therecalltool or re-execute the original tool."Acceptance Criteria
formatStubTextinmessage-transform.tsupdated to accept locator metadataTechnical Notes
Files to modify
packages/coding-agent/src/context/assembler/message-transform.ts—formatStubText(),replaceToolResultContent()packages/coding-agent/src/context/assembler/message-transform.ts—transformMessages()needs access to bridge locator data to enrich stubsprompts/system/or assembled sections) — add stub pointer documentationpackages/coding-agent/src/context/bridge/bridge.ts— may need to expose locator lookup by tool_use_idPointer format options
Minimal:
[t42](~2 tokens) — turn number only, LLM infers tool from conversation structureCompact:
[t42:read:src/parser.ts](~5 tokens) — turn + tool + primary pathRich:
[t42:read:src/parser.ts:L50-80](~7 tokens) — includes line rangeRecommendation: start with compact. The tool name and path give the LLM enough to decide whether to recover the content without looking at the full result.
Integration with bridge
The message transform currently operates independently of the bridge — it only knows about messages, not locator entries. To produce enriched stubs, the transform needs a lookup function: given a
tool_use_id, return the locator entry's metadata. This could be:MessageTransformOptionsEdge cases
Trade-offs Accepted