Wrap your client once.
Everything else plugs in.

Six small, composable libraries for the layer beneath your agent framework — context, cost, testing, and audit. Each works alone; together they ride one event bus with zero per-call wiring. In Python and TypeScript.

Python 3.11+TypeScript · @cendor on npmApache-2.0PyPI + npm 6 providers + OTellocal-first · no server
from cendor.core import instrument
from cendor.tokenguard import budget

client = instrument(OpenAI())   # ← the one line you change

@budget(usd=0.50, on_exceed="block")
def answer(q):                 # over-budget call never runs
    return client.responses.create(model="gpt-4o", input=q)
Then production happened

Frameworks decide what your agent does.
They don't handle what happens underneath.

Prompts overflow

The context window fills up, and naive truncation drops exactly the wrong things.

contextkit + squeeze
Cost is a black box

A looping agent quietly burns real money — and you can't say which feature or user spent it.

tokenguard
You can't test it

Every run hits a paid, non-deterministic API. No fast tests, no CI, just vibes.

cassette
No audit trail

When something goes wrong — or a regulator asks — you can't show what the agent saw, did, or refused.

acttrace
The one idea

One seam, many listeners.

Every tool that needs to see an LLM call usually monkey-patches your client — stack three and they fight. Cendor makes interception a single shared primitive.

instrument() normalizes every call

OpenAI (Chat + Responses), Anthropic, Hugging Face, Bedrock, Gemini, Ollama — detected by shape, so new models work the day they ship. Sync, async, streaming.

The event bus fans it out

Budgets, recording, and audit subscribe — none patches your client, none imports another. Adding a library is free at the call site.

Don't own the loop? Ingest it.

Managed runtimes emit OpenTelemetry gen_ai spans — feed them to otel.ingest() and the same tools keep working.

seamcontextkitsqueezetokenguardcassetteacttraceotel

The mark is the architecture — one hub, many listeners.

Where it fits

Your framework stays. Cendor works above and below it.

One call, start to finish — what's yours, what's Cendor, and the single seam where they meet. You wrap the client once; every step after is automatic, over the bus.

your stackcendorthe seam
Build the prompt
01
Input

Your user, app, or system sends a request.

yours
02
Your agent framework

LangChain · OpenAI Agents SDK · LlamaIndex — or no framework at all.

yours
03
contextkit + squeeze

Pack the prompt into the token budget; oversized blocks compressed, reversibly.

cendor
04
Your tools

Wrapped with instrument_tool(), so tool calls join the same stream.

yours
Pre-flight — before the call runs
05
tokenguard

Blocks or downgrades an over-budget call before a token is spent.

cendor
06
acttrace guard()

Detects secrets & PII and, per your policy, blocks the call or redacts them before send — recorded on the tamper-evident chain.

cendor
The call
07
core.instrument() — the seam

Every call is normalized and published to the event bus. One wrap, many listeners — no tool patches your client, none imports another.

After the call — automatic, via the bus
08
tokenguard

Records spend by feature and user; costs labeled reported vs estimated.

cendor
09
cassette

Records the run — replay it in tests, offline and deterministic.

cendor
10
acttrace

Appends to the tamper-evident log: calls, costs, context decisions, and what the policy flagged or refused.

cendor
11
Your observability

Any OpenTelemetry backend via core.otel — or ingest a managed runtime's spans back onto the bus.

yours · optional
12
Output

The response — budgeted, scrubbed, recorded, and audited, with your code unchanged.

yours

The dependency graph is a star, not a web — adding a library is free at the call site. See the full architecture →

Measured, not promised

Every number regenerates offline.

0%

token-count error vs the real tokenizer (OpenAI, with tiktoken)

97%

smaller logs — compressed reversibly, restored byte-for-byte

~12µs

instrument() overhead per call — bus emit, usage, Decimal pricing

1 byte

a single edited byte breaks the audit chain — verify() fails

Reproduce every figure — no network, no API keys: uv run python benchmarks/run_all.py

Honest by design

Token counts report which method produced them. Costs are labeled reported vs estimated, in exact Decimal — never float. And acttrace produces evidence to support compliance, never a guarantee. No marketing math, and the limits are documented next to the features.

Get started

Your framework stays. Add the plumbing.

$ pip install cendor-libs
$ npm i @cendor/libs

or just one piece: pip install cendor-tokenguard · then the 5-minute quickstart →