Context Engine — agent-core to Exo Mapping
Epic: 4 — Context Engine Enhancements Date: 2026-03-10
Epic: 4 — Context Engine Enhancements Date: 2026-03-10
This document maps agent-core’s (openJiuwen) context engine to Exo’s
enhanced exo-context package, helping contributors familiar with
either framework navigate both.
1. Agent-Core Overview
Agent-core’s context engine lives in openjiuwen/core/context_engine/ (also
referenced as context/) and provides layered context management for long-
running agent conversations.
Key Components
ContextManager — The central orchestrator that coordinates all context
operations. Manages the conversation history buffer, delegates to specialized
managers for offloading, compression, and windowing, and enforces token
budgets before LLM calls.
OffloadManager — Handles message-level offloading for oversized content.
When a message exceeds a configurable character threshold, the manager replaces
it with an [[OFFLOAD: handle=<id>]] marker and stores the original content
for on-demand retrieval. This keeps the active context small while preserving
access to full content when needed.
CompressManager — LLM-based dialogue compression. Detects verbose
tool-call chains (sequences of assistant messages with tool_calls followed
by tool results) and replaces them with concise summaries generated by an
LLM call. Dramatically reduces context size for multi-step tool use without
losing semantic content.
RoundManager — Round-level windowing that understands dialogue structure.
Defines a “round” as a user message through the next assistant response without
tool calls. Trims history to the most recent N rounds while preserving complete
round boundaries, preventing mid-conversation truncation that confuses models.
TokenBudgetManager — Accurate token counting and enforcement via tiktoken.
Supports two encodings:
| Encoding | Models |
|---|---|
cl100k_base | GPT-3.5-turbo, GPT-4, GPT-4-turbo |
o200k_base | GPT-4o, GPT-4o-mini, o1, o3 |
Counts tokens for all messages in history and trims oldest messages when the total exceeds a configurable budget, acting as a final safety net.
ContextConfig — Configuration dataclass controlling all context behavior:
| Field | Purpose |
|---|---|
max_history_rounds | Maximum conversation rounds to keep |
summary_threshold | Message count before summarization triggers |
offload_threshold | Message size before offloading triggers |
max_tokens | Hard token budget for context |
encoding | Tiktoken encoding name |
Processing Order
Agent-core applies context management in this sequence before each LLM call:
- Offload oversized individual messages
- Compress verbose tool-call chains
- Window to recent N rounds
- Summarize if threshold exceeded
- Enforce hard token budget
2. Exo Equivalent
Exo’s context engine lives in the exo-context package
(packages/exo-context/) and implements the same capabilities as
event-driven ContextProcessor subclasses that plug into a
ProcessorPipeline — no monolithic manager needed.
Architecture Difference
Where agent-core uses a single ContextManager that calls specialized
managers in sequence, Exo uses a composable processor pipeline:
# Agent-core: monolithic manager
context_manager = ContextManager(config)
context_manager.process(history) # calls all managers internally
# Exo: composable pipeline
pipeline = ProcessorPipeline()
pipeline.register(MessageOffloader(max_message_size=10_000))
pipeline.register(DialogueCompressor(summarizer=my_summarizer))
pipeline.register(RoundWindowProcessor())
pipeline.register(SummarizeProcessor())
pipeline.register(TokenBudgetProcessor(max_tokens=100_000))
await pipeline.fire("pre_llm_call", ctx, {})Each processor is independent, opt-in, and can be registered in any order (though the recommended order matches agent-core’s sequence).
Component Mapping
| Agent-Core Component | Exo Equivalent | Notes |
|---|---|---|
ContextManager | ProcessorPipeline | Pipeline dispatches to registered processors by event |
OffloadManager | MessageOffloader + ToolResultOffloader | Split into message-level and tool-result offloading |
CompressManager | DialogueCompressor | LLM-agnostic via injected summarizer callable |
RoundManager | RoundWindowProcessor | Uses ContextConfig.history_rounds for window size |
TokenBudgetManager | TokenBudgetProcessor + TiktokenCounter | Separate counter class for reuse |
ContextConfig | ContextConfig | Frozen dataclass with extra dict for extensibility |
[[OFFLOAD: handle=<id>]] markers | [[OFFLOADED: handle=off_<hex>]] markers | Same concept, slightly different format |
| (no equivalent) | Context with fork/merge | Per-task hierarchical state with parent-chain inheritance |
| (no equivalent) | ContextState | Hierarchical key-value state (reads inherit, writes isolate) |
| (no equivalent) | Checkpoint / CheckpointStore | Versioned snapshots of context state |
| (no equivalent) | TokenTracker / TokenStep | Per-agent, per-step token usage tracking |
| (no equivalent) | Context tools (planning, knowledge, file, reload) | Agent-callable tools for self-managing context |
Key Exo Additions Beyond Agent-Core
Hierarchical Context (Context + ContextState) — Exo introduces a
fork/merge lifecycle for task decomposition. A parent context can fork() child
contexts that inherit state but write in isolation. On merge(), the child’s
state changes and net token delta flow back to the parent.
Automation Modes — ContextConfig.mode supports three presets:
| Mode | history_rounds | summary_threshold | offload_threshold |
|---|---|---|---|
pilot | 100 | (disabled) | (disabled) |
copilot | 20 | 10 | 50 |
navigator | 10 | 5 | 20 |
Context Tools — Agents can self-manage their context via built-in tools:
reload_offloaded(handle) retrieves offloaded content, planning tools manage
a task checklist, knowledge tools search workspace artifacts, and file tools
provide safe filesystem access.
3. Configuration Comparison
Agent-Core ContextConfig
# openjiuwen/core/context_engine/config.py
@dataclass
class ContextConfig:
max_history_rounds: int = 20
summary_threshold: int = 10
offload_threshold: int = 50
max_tokens: int = 100_000
encoding: str = "cl100k_base"Exo ContextConfig
# exo-context: config.py
@dataclass(frozen=True)
class ContextConfig:
mode: AutomationMode = "copilot" # pilot / copilot / navigator
history_rounds: int = 20 # ≡ max_history_rounds
summary_threshold: int = 10 # same semantics
offload_threshold: int = 50 # same semantics
enable_retrieval: bool = False # RAG integration toggle
neuron_names: tuple[str, ...] = () # prompt composition neurons
extra: dict[str, Any] = field( # extensible — token_budget, encoding, etc.
default_factory=dict
)Field Mapping
| Agent-Core Field | Exo Field | Notes |
|---|---|---|
max_history_rounds | history_rounds | Same default (20) |
summary_threshold | summary_threshold | Identical |
offload_threshold | offload_threshold | Identical |
max_tokens | extra["token_budget"] | Moved to extra dict to keep frozen schema stable |
encoding | extra["token_encoding"] | Same — defaults to cl100k_base if not set |
| (no equivalent) | mode | Automation level presets |
| (no equivalent) | enable_retrieval | RAG toggle |
| (no equivalent) | neuron_names | Prompt composition |
Factory Function
Exo provides make_config(mode, **overrides) to create configs with
sensible defaults per automation level, avoiding manual threshold tuning:
from exo.context import make_config
config = make_config("navigator") # aggressive compression settings
config = make_config("pilot") # minimal processing, large context window4. Migration Table
| Agent-Core Path | Exo Import | Symbol |
|---|---|---|
openjiuwen.core.context_engine.ContextManager | exo.context.ProcessorPipeline | Composable processor dispatch (replaces monolithic manager) |
openjiuwen.core.context_engine.OffloadManager | exo.context.MessageOffloader | Message-level offloading with [[OFFLOADED: handle=...]] markers |
| (tool result offloading in OffloadManager) | exo.context.ToolResultOffloader | Truncates large tool results, stores full content in state |
openjiuwen.core.context_engine.CompressManager | exo.context.DialogueCompressor | LLM-based tool-chain compression via injected summarizer |
openjiuwen.core.context_engine.RoundManager | exo.context.RoundWindowProcessor | Round-level history windowing |
openjiuwen.core.context_engine.TokenBudgetManager | exo.context.TokenBudgetProcessor | Hard token budget enforcement |
openjiuwen.core.context_engine.ContextConfig | exo.context.ContextConfig | Frozen config with extra dict for extensibility |
| (tiktoken usage inline) | exo.context.TiktokenCounter | Standalone token counter with model→encoding mapping |
| (no equivalent) | exo.context.Context | Per-task context with fork/merge lifecycle |
| (no equivalent) | exo.context.ContextState | Hierarchical key-value state |
| (no equivalent) | exo.context.ContextProcessor | ABC for event-driven processors |
| (no equivalent) | exo.context.SummarizeProcessor | Marks history for summarization at threshold |
| (no equivalent) | exo.context.Checkpoint | Versioned context state snapshot |
| (no equivalent) | exo.context.CheckpointStore | Manages checkpoint versions per task |
| (no equivalent) | exo.context.TokenTracker | Per-agent, per-step token usage tracking |
| (no equivalent) | exo.context.TokenStep | Single LLM call token record |
| (no equivalent) | Context tools (get_context_tools()) | Agent-callable tools for reload, planning, knowledge, files |
All public symbols are re-exported from exo.context (the package
__init__.py), so from exo.context import MessageOffloader works
as a convenience import.
Processor Event Mapping
| Agent-Core Processing Step | Exo Processor | Event |
|---|---|---|
| Offload oversized messages | MessageOffloader | pre_llm_call |
| Compress tool chains | DialogueCompressor | pre_llm_call |
| Window to N rounds | RoundWindowProcessor | pre_llm_call |
| Mark for summarization | SummarizeProcessor | pre_llm_call |
| Enforce token budget | TokenBudgetProcessor | pre_llm_call |
| Truncate tool results | ToolResultOffloader | post_tool_call |