Phosphor automatically summarizes a session's conversation history when the context window is approaching capacity. This "compaction" prevents context overflow by replacing the full message history with a concise summary produced by the model itself.
The summarize_model option in phosphor.json controls which model handles
compaction. Valid values:
| Value | Behavior |
|---|---|
"main" (default, alias for large) |
Use the session's large model |
"large" |
Use the configured large model |
"small" |
Use the configured small model |
"embedded" |
Use the local dlgo GGUF model (requires embedded_models config) |
These live in phosphor.json under the options key:
{
"options": {
"disable_auto_summarize": false,
"summarize_threshold": 0.8,
"summarize_model": "main",
"summarize_tool_output_chars": 200,
"summarize_tool_output_aggressive_chars": 50
}
}
Number of characters to keep for each tool output during standard pre-compaction
pruning. Defaults to 200. Tool results longer than this value are truncated
and appended with \n... [truncated]. Non-tool messages are passed through
unchanged. Lower values produce more aggressive context reduction; higher values
retain more tool output detail.
Number of characters to keep during overflow recovery pruning. Defaults to 50. Used as a fallback when the standard pruned input still exceeds the model's context window — the engine retries with this more aggressive truncation.
{
"embedded_models": {
"inference": {
"enabled": true,
"model_repo": "Qwen3.5-0.8B",
"gpu": false
}
}
}model_repo: HuggingFace repo ID for auto-download (e.g.,"Qwen3.5-0.8B","Phi-3-mini","Gemma-2-2B")model_path: Local path to a GGUF file (alternative tomodel_repo)gpu: Enable GPU acceleration (requires build with Vulkan support); falls back to CPU if GPU is unavailable.
Auto-summarization is triggered at two checkpoints during SessionAgent.Run():
Before sending the LLM request, the agent estimates the current token count of all messages and checks whether it exceeds the configured threshold fraction of the model's context window:
fraction = currentTokens / contextWindow
If fraction >= threshold (default 0.8, i.e. 80%), summarization fires.
After adding the new user message to the session, the agent re-estimates total tokens. If the total would exceed the model's context window, it force-summarizes before sending the request:
if totalTokens > contextWindow:
force summarize
This is a safety net — it catches cases where a single large user prompt would push the conversation past the model's limit.
When triggered, SessionAgent.Summarize() executes:
- Loads conversation history via
getSessionMessages(). - Prunes tool outputs — verbose tool results are truncated to
summarize_tool_output_chars(default 200) characters (pkg/agent/prune.go) to reduce context pressure before summarization. - Loads summary prompt from the profile system
(
pkg/agent/prompt/templates/summarization.md.tpl), with optional iterative context (previous summary prepended). - Creates a summary message (
IsSummaryMessage: true) in the session. - Sends the pruned history to the configured model (main/large, small, or embedded).
- Streams the summary — text deltas are appended to the summary message in real-time.
- Updates session state:
SummaryMessageIDis set to the new summary message's ID.CurrentTokensis recalculated from the summary content usingapproxTokenCount().CompletionTokensis updated from the response usage.PromptTokensis reset to 0 (the summary replaces the full history).
- Processes queued messages — if user sent new prompts during summarization, the first queued message is processed immediately after.
If the model rejects the request due to context overflow, the compaction engine retries with aggressive pruning (tool outputs truncated to 'summarize_tool_output_aggressive_chars', default 50). This handles edge cases where the standard pruning wasn't enough.
On subsequent compaction cycles, the previous summary is prepended to the prompt, allowing the model to compound knowledge across multiple summarization passes.
When summarize_model: "embedded", the summarizeEmbedded() path handles:
- Model download: Auto-downloads GGUF models from HuggingFace at startup
(
ensureEmbeddedModel). - GPU acceleration: If
gpu: true, attempts Vulkan GPU offload; falls back to CPU if no GPU is available. - Otel instrumentation: Tracks
gen_ai.usage.input_tokensandgen_ai.usage.output_tokensfor observability.
The summarization prompt is loaded via the 3-tier profile system:
- Workspace:
.phosphor/profiles/<profile>/summarization.md.tpl - Global:
%LOCALAPPDATA%/phosphor/profiles/<profile>/summarization.md.tpl - Default:
pkg/agent/prompt/templates/summarization.md.tpl(embedded)
Users can customize the prompt per-profile to tailor summary structure or focus.