Skip to main content

cendor-sdk

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

PyPI Python License Ruff types: mypy

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

A thin, provider-agnostic agent SDK where cost budgets, tamper-evident audit, PII redaction, context governance, and record/replay testing are the foundation, not a plugin.

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. It's the simple, batteries-included door into the Cendor stack — you don't need to pick a framework or wire the libraries. (Already have a framework? Compose the libraries beneath it: pip install cendor-libs.)

Install

pip install "cendor-sdk[openai,anthropic]"     # provider SDKs are optional extras
pip install "cendor-sdk[all]"                  # every provider + interop, batteries included
# Using uv? Same names, same extras: `uv add` instead of `pip install`.

The install bundles the whole Cendor stack — all seven libraries (cendor-core, tokenguard, guardrails, acttrace, contextkit, squeeze, cassette) — by dependency, so 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].

Using an AI coding assistant? uvx cendor-init (Python) / npx @cendor/init (TS) wires it up — or point it at cendor.ai/docs/for-ai-assistants.

A governed agent in 10 lines

Auth: OPENAI_API_KEY from your environment (or Agent(api_key=…), or a pre-built client=). The SDK builds the provider client for you — there's no Cendor-specific key. Full table: docs/providers.

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

run.aio is natively async for OpenAI (Chat + Responses — and the Microsoft Foundry (formerly Azure AI Foundry) / Foundry Local paths that use the same client), Anthropic, Google Gemini (google-genai's aio.models.generate_content), Ollama, and Hugging Face. Bedrock's boto3 converse is blocking, so run.aio offloads it to a worker thread (asyncio.to_thread) — the event loop keeps running, and the run's governance scope still attaches.

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.

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"]

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]
Microsoft 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:

  • Streaming — run.stream / run.astream yield text deltas + tool events. Incremental token-level deltas on the OpenAI Chat family (including Microsoft Foundry, Foundry Local, and Hugging Face), Anthropic, and Ollama; OpenAI Responses, Gemini, and Bedrock yield the whole response as one delta.
  • Structured output — a dataclass / Pydantic / JSON-schema output_type uses each provider's native schema mode.
  • Reasoning & control — Agent.extra passes tool_choice, reasoning_effort, top_p, stop, …; o-series temperature is handled for you.
  • RAG — VectorIndex + Agent(retriever=…) inject governed retrieval, or expose your store as a @tool.
  • Memory — Session (conversation), SummarizingSession (rolling summary), SQLiteSessionStore (durable), context_budget (fit the window).
  • Embeddings — embed() / aembed() capture RAG calls on the same cost/audit tree.
  • Cost governance for any model — register_model_price(...) so budgets bind on custom / deployment-named ids.
  • Interop — MCP tools, A2A server/client, a Foundry/Copilot adapter, and human-in-the-loop approvals on the same audit chain.
  • Production hardening — retry policies, and checkpointed/resumable runs so a crashed run continues where it stopped.
  • Observability, zero telemetry code — configure any OpenTelemetry provider and run() emits an agent.run span tree with usage/cost rollups and governance correlated to the run; CENDOR_TELEMETRY=off switches it off. Cendor has no endpoint or key — it emits into your backend.
  • Agent identity — Agent(id="reg-42") rides the semconv gen_ai.agent.id on every span and governance row, so a budget block says which agent it stopped; no id means the attribute is omitted, never fabricated.

Scope & honest limits

  • on_exceed="raise" overshoots by one call — it's post-flight. For a true ceiling use "block".
  • Unpriced models record $0, so a USD cap can't bind on them — register_model_price(...) or use a token cap.
  • guard redacts what its detectors find — regex/pattern detectors plus Presidio NER (an optional extra). See acttrace for coverage.
  • guard / interceptors are process-global — they register on the single in-process bus, so install policy once at startup rather than toggling per request.
  • Evidence, not compliance. The audit chain supports a compliance case; it doesn't make one, and it isn't legal advice.

Docs

Rendered, searchable, with a page-wide Python / TypeScript toggle at cendor.ai/docs/sdk — the same markdown also renders on GitHub.

License

Apache-2.0.

Metadata

Release files for cendor-sdk 1.22.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cendor-sdk 1.22.2
File Size Uploaded
cendor_sdk-1.22.2.tar.gz 429.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cendor-sdk 1.22.2
File Interpreter ABI Platform
cendor_sdk-1.22.2-py3-none-any.whl Python 3 none any Details

Total release size: 547.7 kB

Release files / cendor_sdk-1.22.2.tar.gz

Download URL cendor_sdk-1.22.2.tar.gz
Size 429.9 kB
Tags Source
SHA-256 checksum
How to use checksums
549ee5ae48274a24427275405047d12001bf9415d7c6456f470aada5a8d3a7ad
BLAKE2b-256 checksum
How to use checksums
bf4057d0770dd59a7f5ab55834363caf08f120d1b550aa2537a6fc5a34cd6a27
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 1, 2026.

Transparency log

Release files / cendor_sdk-1.22.2-py3-none-any.whl

Download URL cendor_sdk-1.22.2-py3-none-any.whl
Size 117.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
16d23e6fba68f2bde137e56c734ff4afe03fef47cf8d18afa3bcaeda50168478
BLAKE2b-256 checksum
How to use checksums
1073f44478b3567498764e9b4423002a462130f8c73473133724fa7e42a10dc8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.22.2 This release

2 release files

1.22.1

2 release files

1.22.0

2 release files

1.21.0

2 release files

1.20.0

2 release files

1.19.1

2 release files

1.19.0

2 release files

1.18.0

2 release files

1.17.0

2 release files

1.16.0

2 release files

1.15.0

2 release files

1.14.0

2 release files

1.13.0

2 release files

1.12.0

2 release files

1.11.0

2 release files

1.10.0

2 release files

1.9.0

2 release files

1.8.0

2 release files

1.7.2

2 release files

1.7.1

2 release files

1.7.0

2 release files

1.6.2

2 release files

1.6.1

2 release files

1.6.0

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page