liveBook · Manning

Summarization

As explained in Build an AI Agent (From Scratch)

Summarization is a context-reduction technique that replaces information with a shorter representation of its meaning, typically generated by a language model.

Summarization reduces a growing agent context by replacing older intermediate work with a shorter account of its meaning. Preserve the user's original question and the most recent messages; summarize the tools used, findings, and progress between them. section 6.2.5

A practical strategy is to:

  • Measure context size and try compaction first; summarize only if compaction does not bring usage below the threshold. section 6.2.6
  • Find the original user message, retain a configured number of recent messages, and summarize the intervening history. section 6.2.5
  • Record the last summarized position so later calls do not summarize the same history again. section 6.2.5

Unlike compaction, which is deterministic and reversible, summarization relies on an LLM to select what matters and permanently discards the original reasoning. It adds LLM-call cost, so use it when cheaper reduction is insufficient. section 6.2.5

Listing 6.6 Summarization strategy implementation
async def apply_summarization(
    context: ExecutionContext,
    request: LlmRequest,
    llm_client: LlmClient,
    keep_recent: int = 5
) -> None:
    """Replace old messages with a summary"""

    contents = request.contents

    # Find user message position
    user_idx = None
    for i, item in enumerate(contents):
        if isinstance(item, Message) and item.role == "user":
            user_idx = i
            break

    if user_idx is None:
        return

    # Check previous summary position (skip already-summarized portions)
    last_summary_idx = context.state.get("last_summary_idx", user_idx)

    # Calculate summarization target range
    summary_start = last_summary_idx + 1
    summary_end = len(contents) - keep_recent

    # Overlap prevention: exit if nothing to summarize or range is invalid
    if summary_end <= summary_start:
        return

    # Determine portions to preserve (no overlap)
    preserved_start = contents[:last_summary_idx + 1]
    preserved_end = contents[summary_end:]
    to_summarize = contents[summary_start:summary_end]

    # Generate summary
    history_text = format_history_for_summary(to_summarize)
    summary = await generate_summary(llm_client, history_text)

    # Add summary to instructions
    request.append_instructions(f"[Previous work summary]\n{summary}")

    # Keep only preserved portions in contents
    request.contents = preserved_start + preserved_end

    # Record summary position
    context.state["last_summary_idx"] = len(preserved_start) - 1


def format_history_for_summary(items: List[ContentItem]) -> str:
    """Convert ContentItem list to text for summarization"""
    lines = []
    for item in items:
        if isinstance(item, Message):
            lines.append(f"[{item.role}]: {item.content[:500]}...")
        elif isinstance(item, ToolCall):
            lines.append(f"[Tool Call]: {item.name}({item.arguments})")
        elif isinstance(item, ToolResult):
            content_preview = str(item.content[0])[:200] if item.content else ""
            lines.append(f"[Tool Result]: {item.name} -> {content_preview}...")
    return "\n".join(lines)


async def generate_summary(llm_client: LlmClient, history: str) -> str:
    """Generate history summary using LLM"""

    request = LlmRequest(
        instructions=[SUMMARIZATION_PROMPT.format(history=history)],
        contents=[Message(role="user", content="Please summarize.")]
    )

    response = await llm_client.generate(request)

    for item in response.content:
        if isinstance(item, Message):
            return item.content

    return ""

See the asynchronous implementation for target-range calculation, recent-message preservation, and summary-position tracking. section 6.2.5

How Build an AI Agent (From Scratch) covers it

How deep it goes
Details target selection, preservation boundaries, structured prompts, state tracking, and fallback ordering.
Examples
Uses execution histories organized around key findings, tools called, current status, and remaining work.
What you can do after
Operate it by preserving the original question and recent messages, summarizing intermediate work, and tracking the last summarized position.
How it connects
Pairs with compaction and sliding-window context management, applying reduction after token measurement when compaction is insufficient.

Also explained in

Compare how 12 books explain summarization →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Build an AI Agent (From Scratch). The section links point to the parts of the book it draws on.