Architecture
contextweaver is structured around two cooperating engines that together solve the "context window problem" for tool-using AI agents.
High-level overview
┌────────────────────────────┐
Events ─────>│ Context Engine │──> ContextPack (prompt)
│ candidates → closure → │
│ sensitivity → firewall → │
│ score → dedup → select → │
│ render │
└────────────────────────────┘
▲ facts / episodes
┌──────────┴─────────────────┐
Tools ──────>│ Routing Engine │──> ChoiceCards
│ Catalog → TreeBuilder → │
│ ChoiceGraph → Router │
└────────────────────────────┘
Package layout
| Path | Responsibility |
|---|---|
types.py |
Core dataclasses and enums (SelectableItem, ContextItem, Phase, ItemKind) |
envelope.py |
Result types (ResultEnvelope, BuildStats, ContextPack, ChoiceCard, HydrationResult) |
config.py |
Configuration dataclasses (ContextBudget, ContextPolicy, ScoringConfig) |
protocols.py |
Protocol interfaces (TokenEstimator, EventHook, Summarizer, …) |
exceptions.py |
Custom exception hierarchy |
_utils.py |
Text similarity primitives (tokenize, jaccard, TfIdfScorer) |
serde.py |
Serialisation helpers for to_dict / from_dict patterns |
store/ |
In-memory data stores (EventLog, ArtifactStore, EpisodicStore, FactStore) |
summarize/ |
Rule engine and structured fact extraction |
context/ |
Full context compilation pipeline |
routing/ |
Catalog, DAG builder, beam-search router, card renderer |
adapters/ |
MCP, FastMCP, and A2A protocol adapters |
__main__.py |
CLI entry point (7 subcommands) |
Context Engine pipeline
The Context Engine compiles a phase-aware, budget-constrained prompt from the event log. The pipeline has eight stages:
- generate_candidates — pull phase-relevant events from the event log into the initial candidate pool.
- dependency_closure — if a selected item has a
parent_id, bring the parent along even if it scored lower. - sensitivity_filter — drop or redact items whose
sensitivitylevel meets or exceedsContextPolicy.sensitivity_floor. - apply_firewall — tool results are stored out-of-band in the ArtifactStore and replaced with summarized/truncated text for prompt assembly.
- score_candidates — rank candidates by recency, tag match, kind priority, and token cost.
- deduplicate_candidates — remove near-duplicate items using Jaccard similarity over tokenised text.
- select_and_pack — greedily pack the highest-scoring candidates into the token budget for the current phase.
- render_context — assemble the final prompt string, grouped by
section (facts, history, tool results), with
BuildStatsmetadata.
Routing Engine pipeline
The Routing Engine efficiently navigates large tool catalogs so the LLM never sees all tools at once:
- Catalog — register and manage
SelectableItemobjects. - TreeBuilder — convert a flat item list into a bounded
ChoiceGraphDAG using namespace grouping, Jaccard clustering, or alphabetical fallback. - Router — beam-search over the graph to find the top-k items most relevant to a user query.
- ChoiceCards — render compact, LLM-friendly cards for the selected items (never includes full schemas).
Data stores
All stores are protocol-based with in-memory defaults:
- EventLog — append-only log of
ContextItemevents. - ArtifactStore — blob storage for raw tool outputs intercepted by the firewall.
- EpisodicStore — short episodic memory entries (keyed by episode ID).
- FactStore — key-value fact entries persisted across turns.
- StoreBundle — convenience wrapper grouping all four stores.
Progressive disclosure
context/views.py provides a ViewRegistry that maps content-type patterns
to view generators. When the firewall stores a large tool output as an artifact,
the view system generates alternative representations (JSON subset, CSV summary,
etc.) the agent can drilldown into without retrieving the full blob.
drilldown_tool_spec() exposes drilldown as an agent-callable tool.
Design principles
- Zero runtime dependencies — stdlib-only, Python ≥ 3.10.
- Deterministic — tie-break by ID, sorted keys.
- Protocol-based — all store and estimator interfaces are
typing.Protocol, allowing custom implementations. - Async-first — the Context Engine exposes
build()(async) with abuild_sync()wrapper for synchronous callers. - Budget-aware — every build is constrained by the phase-specific
token budget;
BuildStatsexplains what was kept and what was dropped.