FAQ
Libraries or SDK — which door do I take?
Pick by what you already have:
- You have a framework (LangChain, LlamaIndex) or call a provider SDK directly → use the
libraries underneath it. You keep your loop; Cendor adds budgets, audit, redaction,
record/replay beneath it via one
instrument()wrap (or the LangChain callback handler). - You’re starting fresh, or want an agent without picking a framework → use the SDK.
Agent+tool+run, with every governance layer one import away. - You’re not sure → start with the SDK; it’s the shorter path to a working governed agent, and moving down to the libraries later is continuous (next answer).
Can I use both at the same time?
Yes — they’re the same objects. budget, track, guard, Policy, AuditLog, and trace
re-exported from cendor.sdk are the tokenguard/acttrace originals, so a budget() opened
around an SDK run() also caps a bare instrumented client call in the same scope, and one
AuditLog records both. A common mix: the SDK runs the agent loop, while a separately
instrument()-ed client handles non-agent calls (embeddings, one-shot completions) — one budget,
one audit chain, one report().
Does the SDK lock me in?
No. result.messages is the canonical (OpenAI-shape) conversation; tools are plain functions;
governance objects are library objects. Dropping the SDK means keeping the libraries and writing
your own loop — the concepts transfer one-to-one because they were never SDK concepts.
Is this another LangChain?
It’s deliberately less. No chains, no graph DSL, no vector store, no prompt templates — a bounded ReAct loop with tools, sessions, and governance built in. If you want a rich orchestration vocabulary, use a framework — and run the libraries beneath it; that’s what they’re for.
Which languages are supported?
Python (pip install cendor-sdk) and TypeScript/JavaScript (npm i @cendor/sdk). Same API
shapes (snake_case ↔ camelCase), same defaults, same error names; artifacts (cassettes,
audit chains) are byte-for-byte interoperable. All ten provider paths ship in TypeScript — the
full split (and what stays Python-only) is in the parity matrix.
Why did my budget(usd=...) not stop a run?
Almost always one of two things:
- The model is unpriced — Hub ids, Azure deployment names, and custom gateways aren’t in
the bundled price table, so calls record
$0. Register a rate (Providers → pricing unpriced models) or use atokens=cap. - The mode is post-flight —
on_exceed="raise"trips after the breaching call returns. For a hard ceiling use"block"(Governance → budgets).
How do I test an agent without an API key?
Record once, replay forever: wrap the run in
cassette.using(...) — first run records,
every run after replays offline with real usage/cost re-emitted. The
eval harness turns those recordings into CI regression tests.
Can agents on different providers work together?
Yes — the conversation is canonical, so an OpenAI planner can hand off to an Anthropic writer with no translation (Multi-agent). Provider handoff is a model-id change, not an architecture change.
Does it work in notebooks / scripts / servers?
All three. In Python run() is sync, with run.aio / run.astream for servers and notebooks with
running loops; in TypeScript everything is async (run / run.stream). Nothing spawns background
services; state lives in the process (and in whatever session/checkpoint files you ask for).
Where do the numbers on the website come from?
Every performance and behaviour claim is measured by the reproducible, offline benchmark suite — see /benchmarks and the library docs’ benchmark methodology.