Getting started
Install
pip install contexel # pure Python, zero dependencies
pip install "contexel[accurate]" # + tiktoken, for exact token counts
The first PyPI release is in flight — until it lands, install from source below. This note disappears with the release.
From source (also how you get the benchmark suites):
git clone https://github.com/maheshvaikri-code/contexel && cd contexel
pip install -e . # the library
pip install -e ".[accurate]" # + tiktoken
pip install -e ".[benchmarks]" # + everything the benchmark suites use
Shape your first tool output
Everything operates on list[dict] — the shape tools already
return. Compose stages inline, and wrap them in trace() to see
exactly what each one removed:
from contexel import select, dedupe, rescore, truncate_field, rank, trim_to_budget, trace
raw = search_tool(query=user_query) # a batch of verbose results
with trace() as t:
r = select(raw, ["title", "url", "snippet", "published"])
r = dedupe(r, key="url")
r = rescore(r, query=user_query, fields=("title", "snippet"))
r = truncate_field(r, "snippet", max_tokens=120)
r = rank(r, by="score", desc=True)
r = trim_to_budget(r, max_tokens=1500)
print(t.report()) # per-stage: records in → out, tokens before → after
context = r # only this distilled result enters the model's context
Pin the policy at the tool boundary
For a policy the model can never vary, attach it to the tool itself with
@shaped — the context contract
pattern:
from contexel import shaped, stage, select, dedupe, trim_to_budget
@shaped([
stage(select, fields=["path", "line", "snippet"]),
stage(dedupe, key=["path", "line"]),
stage(trim_to_budget, max_tokens=2000),
])
def search_code(query: str) -> list[dict]:
return repo.search(query) # raw and heavy — shaped identically, every call
Where the contract lives
Agent sandbox
Programmatic tool calling: the sandbox imports the stages, the model
composes them. examples/programmatic_tool_calling.py
Tool wrapper
@shaped on the tool; the model never sees raw output.
examples/tool_boundary_wrapper.py
MCP server
Shape responses before they leave the server.
examples/mcp_server.py
Under a framework
A records ⇄ Document adapter for LangChain / LlamaIndex.
examples/framework_adapter.py
Shape, then encode
Price budgets in the encoding that actually enters context — e.g. an
ISON table.
examples/ison_boundary.py
Reference agent
A complete code-execution agent, no API key needed:
python -m reference_agent. Its tests prove byte-identical
context across runs.
Token accounting
Two pluggable axes, both process-wide:
from contexel import tokens
tokens.use_tiktoken() # exact counts (needs the accurate extra)
tokens.set_tokenizer(fn) # or your own text → count
tokens.set_serializer(fn) # price records in your boundary's encoding
tokens.set_serializer(None) # back to canonical JSON
Budgets are encoding-relative: a record's cost is the token count of its
serialized text. If your boundary emits something other than JSON,
plug that in so trim_to_budget prices what actually ships.
Next: the stage reference, or the evidence.
GitHub