The whole stack, visible: all seven libraries in one chat app — budgets, receipts, compression, a deterministic gate that refuses a prompt before it leaves, replay, and a tamper-evident audit trail.
Copy-paste recipes that run offline.
Every sample in the cookbook runs without an API key — each one drives a provider-shaped fake client through the real Cendor seam, so the budgets, the costs and the audit chain are genuine over a canned response. Clone, run, adapt. Two repos, one per toolchain: a recipe folder name means the same thing in both.
18 of them also ship an optional live switch — a documented one-liner (an env var, the playground's Live mode, or a client swap) that trades the fake for a real provider using your key. Nothing needs a key to run; the switch is there when you want to see the same governance against real traffic.
Showing 55 of 55 recipes
A governed agent in ~10 lines — a real tool loop (zod tools on the TypeScript side) with a pre-flight budget, PII redaction, and a tamper-evident audit chain. Built on cendor-sdk / @cendor/sdk.
Govern a Microsoft 365 Agents SDK custom engine agent: a session cap held in TurnState, gates on the inbound Activity, evidence per turn, the whole agent replayed offline for $0 CI — and on the TypeScript side, a negative control for the afterTurn trap that silently stops the cap binding.
A hash-chained audit log that verifies offline — one edited byte fails the chain.
register_detector() with a validator, plus enable_locale_pack(). Of five sensitive values, the built-ins found one; four registrations later, all five.
Budget + audit Claude calls, including prompt-cache read/write accounting.
Your Foundry deployment name is unpriced, so a USD cap silently never binds — then one line and it does. On the v1 GA endpoint, with the Foundry SDK too.
A managed runtime owns the loop — ingest its gen_ai.* spans and keep budgets + audit on calls your process never made.
You hold the client — export every governance event to Azure Monitor as an ordinary OTel span, refusals included.
The Batch API runs server-side and hands back a results file — so nothing was ever on your bus. otel.ingest() replays the job's usage after the fact, priced and attributed like a live call.
camelCase Converse usage, and the two caps that still bind on an unpriced marketplace id.
A guardrail block pre-empts the recorder: two requests in, one provider call and one cassette entry out. Your cassettes only ever hold traffic that was allowed.
on_exceed="break" cuts a runaway stream mid-flight and closes the socket; the cut is chained as a budget_event that still verifies.
Record a run once, replay it forever — deterministic, offline, free test fixtures.
record / replay / rerecord / auto, with the provider-call count printed for each — and why auto is the wrong choice for CI.
Measured, and not the intuitive result: a surface scorer keeps the harmless paraphrase and drops the real change. That is why semantic_drift() takes a scorer.
One cendor Guardrail, exposed as a PreToolUse hook. A cendor block becomes the SDK's permissionDecision: "deny" — same policy as under cendor-sdk, different agent loop.
A reversible eviction, chained as a metadata-only compression audit entry. A planted marker is asserted absent from every field — the chain is safe to keep when the content is not.
The clamp binds on the assembled prompt: contextkit's receipt is the billed input — measured against a fake provider that bills exactly what it was sent.
Assemble a token-budgeted context window with an auditable packing receipt.
priority · pin · evict · keep, and the AssemblyReport receipt that says which block went and why. whatif() prices a tighter budget without committing.
use_compressor() with a domain backend — no base class, no import, no call site changed. The reversible handle is the whole contract.
The instrument() seam: one wrap, and every model call emits exact usage + decimal cost on the bus — cendor-core in Python, @cendor/core in TypeScript.
trace(), add_stream_observer() — an enforcement seam, not a logging hook — and tokens.register(). The three hooks every other library is built on.
prices.explain() — which source priced this call, as of what date, and whether one of your registrations is overriding it. Plus save/load, refresh(required), and the warning a table older than 45 days raises once per process.
A keyword denylist blocks the phrase and sails past the paraphrase. custom_category catches a request by meaning, with the embedding work done locally.
Byte-identical assembly across runs — with real eviction active — is what makes a replay mean anything. Ships its own one-character hash control.
Decisions, human oversight, policy flags → export an evidence pack and verify it offline.
usage_metadata, not usage — a different shape entirely, and the same three governance lines. Streaming captured.
Block a prompt-injection attempt and redact a leaked key before the call is sent — every decision in the audit chain, $0.00 spent.
Guardrails declared in a versioned file rather than scattered through the app — and the policy_hash on the chain proves which version was live when the decision was made.
"Our guardrails catch jailbreaks" is a claim, not a number. Runs a labeled attack corpus and reports the measured trip rate, so the claim becomes a figure you can regress on.
Not every turn deserves a model call. Classify the intent first and refuse off-scope requests before anything is spent.
Wrap the client under a LangChain/LangGraph agent; budgets and audit ride unchanged.
The same guardrail as a LangChain agent middleware. Its before_model hook is the input intervention point, so a fail-closed block stops the run before the model is called — $0 spent.
contextkit packing alongside a RAG pipeline — with the assembly receipt.
Deterministic rules cannot catch a novel jailbreak. Screen with a model — and budget, record and audit the judge too, because a judge is a model call like any other.
Gate the tools your MCP server exposes to any client. A dangerous argument is refused before the tool body runs, and the model gets a result it can read rather than a crash.
Fully local, zero-key, end-to-end: a llama3 agent that's budgeted, recorded, audited.
The same guardrail as an @input_guardrail, mapping a cendor decision onto OpenAI's tripwire_triggered. Guardrails ride core's seam, not any one agent framework.
A Responses-based agent loop with pre-flight budgets and a tamper-evident trail.
Instrument Chat Completions: budgets, recording, audit on the classic entrypoint.
The Responses API — the default for new OpenAI apps — through the same seam.
Governance as standard gen_ai.* telemetry, into whichever OTel backend you already run. Cendor never operates an endpoint — it emits into the global provider.
PII and secrets scrubbed before the payload reaches the model, with the tamper-evident record to prove the raw value never left.
A real agent test suite: record once, replay in CI, xdist-safe cassette layout.
Record the budgeted, audited triad once and replay it for $0 — proven by a client that raises if it is ever reached.
Indirect prompt injection hides instructions inside content your agent reads. Spotlighting wraps retrieved text so the model treats it as data, not orders.
Deterministic prompt compression with reversible, content-addressed handles.
json / logs / code / prose × three fidelities, with ratios measured on the recipe's own inputs. Logs compress ~400×; lossless is a real setting, not a slower one.
Restore the original in a second process — a real interpreter boundary, with the in-memory store's failure shown beside it as the control.
Agents drift. A BYO-judge check on each tool call asks whether it is still on the task the user actually gave — recorded to a cassette so it is free to re-run.
Budgets, spend tracking, and reports — enforced pre-flight, before the call ever runs.
Durable spend off the hot path, plus the BudgetEvent stream — the only trace a blocked call leaves, because it never becomes an LLMCall.
clamp (the provider enforces it) vs break (you do, mid-flight) — including break on a non-streamed call, where it can only tell you afterwards.
git clone → uv run — that's it.
Python: uv run python recipes/<category>/<name>/main.py — 20 of them also ship a notebook.ipynb. TypeScript: cd recipes/<category>/<name> && npm install && node index.mjs — typed index.mts source, runnable as plain JS with no build step. No keys · docs →
Two exceptions to the Python line, because their entry point is not main.py: apps/chat-playground is app.py, and testing/pytest-cassette is a pytest module (uv run pytest recipes/testing/pytest-cassette).
Wiring Cendor into an AI coding assistant? See For AI assistants or the MCP server.