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:

  • Streamingrun.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 & 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.
  • 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 identityAgent(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.

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.22.2.tar.gz (429.9 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.22.2-py3-none-any.whl (117.8 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for cendor_sdk-1.22.2.tar.gz
Algorithm Hash digest
SHA256 549ee5ae48274a24427275405047d12001bf9415d7c6456f470aada5a8d3a7ad
MD5 97d4283123f83f076200b71e55364a71
BLAKE2b-256 bf4057d0770dd59a7f5ab55834363caf08f120d1b550aa2537a6fc5a34cd6a27

See more details on using hashes here.

Provenance

The following attestation bundles were made for cendor_sdk-1.22.2.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.22.2-py3-none-any.whl.

File metadata

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

File hashes

Hashes for cendor_sdk-1.22.2-py3-none-any.whl
Algorithm Hash digest
SHA256 16d23e6fba68f2bde137e56c734ff4afe03fef47cf8d18afa3bcaeda50168478
MD5 216e62984e49d092592adb68aaf14a15
BLAKE2b-256 1073f44478b3567498764e9b4423002a462130f8c73473133724fa7e42a10dc8

See more details on using hashes here.

Provenance

The following attestation bundles were made for cendor_sdk-1.22.2-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.

Release history Release notifications | RSS feed

This release

1.22.2 This release

2 files

1.22.1

2 files

1.22.0

2 files

1.21.0

2 files

1.20.0

2 files

1.19.1

2 files

1.19.0

2 files

1.18.0

2 files

1.17.0

2 files

1.16.0

2 files

1.15.0

2 files

1.14.0

2 files

1.13.0

2 files

1.12.0

2 files

1.11.0

2 files

1.10.0

2 files

1.9.0

2 files

1.8.0

2 files

1.7.2

2 files

1.7.1

2 files

1.7.0

2 files

1.6.2

2 files

1.6.1

2 files

1.6.0

2 files

1.5.0

2 files

1.4.0

2 files

1.2.0

2 files

1.1.1

2 files

1.1.0

2 files

1.0.1

2 files

1.0.0

2 files

Supported by

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