Skip to main content

A governed, provider-agnostic agent SDK — cost budgets, tamper-evident audit, PII redaction, context governance, and record/replay testing as the foundation, not plugins. The second door to the Cendor stack.

Project description

cendor-sdk

A governed agent in 10 lines — cost budgets, tamper-evident audit, and PII redaction built in.

version Python License Ruff types: mypy status: stable

provider-agnostic · local-first · offline by default · sync and async

The only agent SDK where cost budgets, tamper-evident audit, PII redaction, context governance, and record/replay testing are the foundation, not plugins.


Two doors into Cendor

Cendor is production plumbing for LLM applications. There are two ways in — pick by your situation, not by primacy:

When What you get
🥇 The libraries (primary) You already have a framework (LangChain, LlamaIndex, the provider SDKs). Drop cost, governance, and testing beneath the framework you already use. pip install cendor.
🚪 cendor-sdk (this repo) Starting fresh / want it simple. A batteries-included, governed agent SDK — you don't need to pick a framework or wire the libraries. pip install cendor-sdk.

Both doors expose the same primitivesbudget, guard, Policy, AuditLog, trace. A team that starts on the SDK and later adopts a framework drops to the libraries underneath with no concept rewrite. Movement between doors is continuous, not a migration.

cendor-sdk owns the agent loop, so every governance concern that is best-effort beneath a framework becomes first-class here: usage is never lost, budgets enforce before the model call, PII is redacted before send, and the whole run correlates under one trace_id.


Install

pip install "cendor-sdk[openai,anthropic]"     # provider SDKs are optional extras
pip install "cendor-sdk[all]"                  # every provider + interop, batteries included

The install bundles the whole Cendor stack (cendor-core, tokenguard, acttrace, contextkit, squeeze, cassette) by dependency — you install once and import only from cendor.sdk. Provider SDKs stay optional extras: [openai], [anthropic], [google], [bedrock], [ollama], [huggingface], [azure], [foundry-local], plus [mcp] and [otel].

The killer example — a governed agent in 10 lines

from cendor.sdk import Agent, tool, run, budget, guard, Policy, AuditLog

@tool
def get_weather(city: str) -> str:
    """Current weather for a city."""
    return f"Sunny in {city}"

agent = Agent(name="assistant", model="gpt-4o", tools=[get_weather],
              instructions="Answer using tools when helpful.")

log = AuditLog(system="support", risk_tier="limited", path="audit.jsonl")
with budget(usd=0.25, on_exceed="block"), guard(Policy.default(), audit=log):
    result = run(agent, "What's the weather in Paris?", audit=log)

print(result.output)                        # -> "It's sunny in Paris."
print(result.cost, result.usage)            # priced in Decimal, budgeted
print([s.name for s in result.tool_steps])  # -> ["get_weather"]
# audit.jsonl: audit_open -> decision -> llm_call -> tool_call -> llm_call, hash-chained &
# verify()-able, all correlated by one trace_id. Wrap in cassette.using("run.json") to replay it.

Ungoverned still works — on cendor-core alone. Every governance layer is optional and removable; drop the with block and run(agent, ...) runs bare:

from cendor.sdk import Agent, run
result = run(Agent(name="a", model="gpt-4o", instructions="Be brief."), "Hi")
result = await run.aio(agent, "Hi")   # same call, async

Why it's different

Provider lock Cost budgets Tamper-evident audit PII redaction Record/replay tests Local-first
OpenAI Agents SDK OpenAI-centric lib
LangGraph agnostic DIY DIY DIY DIY lib
Anthropic Agent SDK Anthropic-centric lib
CrewAI / Pydantic AI / ADK varies ✗/DIY lib
cendor-sdk agnostic built-in built-in built-in built-in yes

Governance is composed through Cendor's existing bus / interceptor / Sink / Compressor seams, correlated by trace()zero SDK-specific glue. Budgets, audit, redaction, and record/replay all ride the agent loop through those seams, so removing any one is just not entering its context.

How one turn executes

Runner, for each agent turn:

  1. Assemble context to the model's budget via contextkit (optional; falls back to raw messages) — emits an AssemblyReport that the audit chain records.
  2. Format messages + tool schemas for the target provider.
  3. Call the model through a cendor-core-instrumented client inside trace(run_id) → emits an LLMCall (usage/cost/reasoning). Pre-call, budget/guard interceptors fire (block / clamp / downgrade, redact-before-send).
  4. Normalize the response → assistant content + tool calls + finish reason.
  5. Execute any tool calls (each emits a ToolCall, same trace_id); append results; loop.
  6. Else finalize → structured-output parse → Result.

Multi-agent, one correlated tree

Handoff, supervisor/router, and sequential/parallel pipelines — with the correlation that was impossible beneath frameworks. A whole multi-agent run is one governed, trace_id-correlated tree, on one verifiable audit chain. Handoff even works across providers:

from cendor.sdk import Agent, run

writer  = Agent(name="writer",  model="claude-opus-4-8", instructions="Write the brief.")
planner = Agent(name="planner", model="gpt-4o", instructions="Plan, then hand off.",
                handoffs=["writer"])

result = run([planner, writer], "Research X and write a brief")   # OpenAI ➝ Anthropic handoff
print(result.agents)     # ["planner", "writer"]

See docs/multi-agent.md.

Every major provider — one canonical loop

The provider is inferred from the model id (override with provider=). History is held in one canonical shape, so a run can hand off between providers without rewriting it.

Provider Models Extra
OpenAI Chat Completions + Responses API [openai]
Anthropic Messages API [anthropic]
Google Gemini google-genai [google]
AWS Bedrock Converse API [bedrock]
Ollama local models [ollama]
Hugging Face Inference / endpoints [huggingface]
Azure AI Foundry deployments via the OpenAI v1 endpoint (Chat + Responses) [azure]
Foundry Local on-device, OpenAI-compatible [foundry-local]

More in the box

Everything a real agent needs — all governed through the same seams:

  • Streamingrun.stream / run.astream yield text deltas + tool events (native for the OpenAI family + Ollama).
  • Structured output — a dataclass / Pydantic / JSON-schema output_type uses each provider's native schema mode.
  • Reasoning & controlAgent.extra passes tool_choice, reasoning_effort, top_p, stop, …; o-series temperature is handled for you.
  • RAGVectorIndex + Agent(retriever=…) inject governed retrieval, or expose your store as a @tool.
  • MemorySession (conversation), SummarizingSession (rolling summary), SQLiteSessionStore (durable), context_budget (fit the window).
  • Embeddingsembed() / aembed() capture RAG calls on the same cost/audit tree.
  • Cost governance for any modelregister_model_price(...) so budgets bind on custom / deployment-named ids.

Status — v1.0.0 (stable)

All four phases are shipped, tested offline, and documented; provider coverage and agent capabilities have since been rounded out (streaming, RAG, memory, Hugging Face / Azure Foundry / Foundry Local).

Phase Scope State
1 Governed single agent (loop, providers, tools, structured output, session, governance) ✅ shipped
2 Multi-agent orchestration (handoff, supervisor, sequential/parallel) ✅ shipped
3 Ecosystem & interop (MCP, A2A, Foundry, OTel span tree, HITL) ✅ shipped
4 Production hardening (retries, checkpoints, durable memory) & governed eval ✅ shipped

Docs

License

Apache-2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cendor_sdk-1.0.0.tar.gz (99.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cendor_sdk-1.0.0-py3-none-any.whl (62.2 kB view details)

Uploaded Python 3

File details

Details for the file cendor_sdk-1.0.0.tar.gz.

File metadata

  • Download URL: cendor_sdk-1.0.0.tar.gz
  • Upload date:
  • Size: 99.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cendor_sdk-1.0.0.tar.gz
Algorithm Hash digest
SHA256 9ffaade6f36127bf00b615185be53eebe5a3dfbf2246fc2509ee27ccb4717bf6
MD5 9061e97276d00a9fb6c706de4505f340
BLAKE2b-256 ea8c659bd4cca7c2a7d9947d45b4e04430c6d7fc4e84511167a406797ce3c443

See more details on using hashes here.

Provenance

The following attestation bundles were made for cendor_sdk-1.0.0.tar.gz:

Publisher: release.yml on cendorhq/cendor-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cendor_sdk-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: cendor_sdk-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 62.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cendor_sdk-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4efdebcba5c2bc3c619250b22cb183f2d4e52c4b7de6de34841fbe631b95bbbf
MD5 011a84bbb8c6a7d4a91198d206f42709
BLAKE2b-256 fa4985e1fbcc7492aa6838d65ad755ded09ea322160c5431d8caee93ac949e8f

See more details on using hashes here.

Provenance

The following attestation bundles were made for cendor_sdk-1.0.0-py3-none-any.whl:

Publisher: release.yml on cendorhq/cendor-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page