Phase-specific, budget-aware context compilation for tool-using AI agents.
500+ tests passing · zero runtime dependencies · deterministic output · Python ≥ 3.10
Imagine a tool-using agent with a 100-tool catalog and a 50-turn conversation history. At each step the agent must answer four questions:
- Route — which tool should I call?
- Call — what arguments?
- Interpret — what did it return?
- Answer — how do I respond to the user?
Naive approach A — concatenate everything:
100 tool schemas (≈50k tokens) + 50 turns (≈30k tokens) = 80k tokens
Token limit: 8k → 10× overflow
Naive approach B — cherry-pick manually:
Pick 10 tools, last 5 turns → lose dependency chains
Agent hallucinates tool calls, repeats questions, forgets context
contextweaver approach — phase-specific budgeted compilation:
Route phase: 5 tool cards (≈500 tokens), no full schemas
Answer phase: 3 relevant turns + dependency closure (≈2k tokens)
Result: 2.5k tokens, complete context, deterministic
See examples/before_after.py for a runnable side-by-side comparison.
contextweaver provides two cooperating engines:
┌────────────────────────────┐
Events ──────>│ Context Engine │──> ContextPack (prompt)
│ candidates → closure → │
│ sensitivity → firewall → │
│ score → dedup → select → │
│ render │
└────────────────────────────┘
▲ facts / episodes
┌──────────┴─────────────────┐
Tools ───────>│ Routing Engine │──> ChoiceCards
│ Catalog → TreeBuilder → │
│ ChoiceGraph → Router │
└────────────────────────────┘
Context Engine — eight-stage pipeline:
- generate_candidates — pull phase-relevant events from the log for this request.
- dependency_closure — if a selected item has a
parent_id, include the parent automatically. - sensitivity_filter — drop or redact items at or above the configured sensitivity floor.
- apply_firewall — tool results are stored out-of-band; large outputs are summarized/truncated before prompt assembly.
- score_candidates — rank by recency, tag match, kind priority, and token cost.
- deduplicate_candidates — remove near-duplicates using Jaccard similarity.
- select_and_pack — greedily pack highest-scoring items into the phase token budget.
- render_context — assemble final prompt string with
BuildStatsmetadata.
Routing Engine — four-stage pipeline:
- Catalog — register and manage
SelectableItemobjects. - TreeBuilder — convert a flat catalog into a bounded
ChoiceGraphDAG. - Router — beam-search over the graph; deterministic tie-breaking by ID.
- ChoiceCards — compact, LLM-friendly cards (never includes full schemas).
pip install contextweaverOr from source:
git clone https://github.com/dgenio/contextweaver.git
cd contextweaver
pip install -e ".[dev]"from contextweaver.context.manager import ContextManager
from contextweaver.types import ContextItem, ItemKind, Phase
mgr = ContextManager()
mgr.ingest(ContextItem(id="u1", kind=ItemKind.user_turn, text="How many users?"))
mgr.ingest(ContextItem(id="tc1", kind=ItemKind.tool_call,
text="db_query('SELECT COUNT(*) FROM users')", parent_id="u1"))
mgr.ingest(ContextItem(id="tr1", kind=ItemKind.tool_result,
text="count: 1042", parent_id="tc1"))
pack = mgr.build_sync(phase=Phase.answer, query="user count")
print(pack.prompt) # budget-aware compiled context
print(pack.stats) # what was kept, dropped, deduplicatedfrom contextweaver.routing.catalog import Catalog, load_catalog_json
from contextweaver.routing.tree import TreeBuilder
from contextweaver.routing.router import Router
catalog = Catalog()
for item in load_catalog_json("catalog.json"):
catalog.register(item)
graph = TreeBuilder(max_children=10).build(catalog.all())
router = Router(graph, items=catalog.all(), beam_width=3, top_k=5)
result = router.route("send a reminder email about unpaid invoices")
print(result.candidate_ids)| Framework | Guide | Use Case |
|---|---|---|
| MCP | Guide | Tool conversion, session loading, firewall |
| A2A | Guide | Agent cards, multi-agent sessions |
| LlamaIndex | Guide (coming soon) | RAG + tools with budget control |
| OpenAI Agents SDK | Guide (coming soon) | Function-calling agents with routing |
| Google ADK | Guide (coming soon) | Gemini tool-use with context budgets |
| LangChain / LangGraph | Guide (coming soon) | Chain + graph agents with firewall |
| Proof point | Detail |
|---|---|
| 500+ tests passing | Context pipeline, routing engine, firewall, adapters, CLI, sensitivity enforcement |
| Zero runtime dependencies | Stdlib-only, Python ≥ 3.10. Works with any LLM provider. No vendor lock-in. |
| Deterministic | Tie-break by ID, sorted keys. Identical inputs always produce identical outputs. |
| Protocol-based stores | EventLog, ArtifactStore, EpisodicStore, FactStore are typing.Protocol interfaces — swap any backend. |
| MCP + A2A adapters | First-class support for both emerging agentic standards. |
BuildStats transparency |
Every context build reports exactly what was kept, dropped, deduplicated, and why. |
| Concept | Description |
|---|---|
ContextItem |
Atomic event log entry: user turn, agent message, tool call, tool result, fact, plan state. |
Phase |
route / call / interpret / answer — each with its own token budget. |
ContextFirewall |
Intercepts tool results: stores raw bytes out-of-band, injects compact summary (with truncation for large outputs). |
ChoiceGraph |
Bounded DAG over the tool catalog. Router beam-searches it; LLM sees only a focused shortlist. |
ResultEnvelope |
Structured tool output: summary + extracted facts + artifact handles + views. |
BuildStats |
Per-build diagnostics: candidate count, included/dropped counts, token usage, drop reasons. |
See docs/concepts.md for the full glossary and
docs/architecture.md for pipeline detail and design rationale.
contextweaver ships with a CLI for quick experimentation:
contextweaver demo # end-to-end demonstration
contextweaver init # scaffold config + sample catalog
contextweaver build --catalog c.json --out g.json # build routing graph
contextweaver route --graph g.json --query "send email"
contextweaver print-tree --graph g.json
contextweaver ingest --events session.jsonl --out session.json
contextweaver replay --session session.json --phase answer| Script | Description |
|---|---|
minimal_loop.py |
Basic event ingestion → context build |
tool_wrapping.py |
Context firewall in action |
routing_demo.py |
Build catalog → route queries → choice cards |
before_after.py |
Side-by-side token comparison: WITHOUT vs WITH contextweaver |
mcp_adapter_demo.py |
MCP adapter: tool conversion, session loading, firewall |
a2a_adapter_demo.py |
A2A adapter: agent cards, multi-agent sessions |
make example # run all examplesmake fmt # format (ruff)
make lint # lint (ruff)
make type # type-check (mypy)
make test # run tests (pytest)
make example # run all examples
make demo # run the built-in demo
make ci # all of the aboveSee CONTRIBUTING.md for setup instructions.
| Milestone | Status | Highlights |
|---|---|---|
| v0.1 — Foundation | ✅ complete | Context Engine, Routing Engine, MCP + A2A adapters, CLI, sensitivity enforcement, logging |
| v0.2 — Integrations | 🚧 in progress | Framework integration guides (LlamaIndex, OpenAI Agents SDK, Google ADK, LangChain) |
| v0.3 — Tooling | 📋 planned | DAG visualization, merge compression, LLM-assisted labeler |
| Future | 📋 planned | Context versioning, distributed stores, multi-agent coordination |
See CHANGELOG.md for the detailed release history.
Apache-2.0