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

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.

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

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

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.

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

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.1.0.tar.gz (106.6 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.1.0-py3-none-any.whl (64.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: cendor_sdk-1.1.0.tar.gz
  • Upload date:
  • Size: 106.6 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.1.0.tar.gz
Algorithm Hash digest
SHA256 b7efa54583795061e354048698a43b6f2854859483f8a26aef8ff3ff65dd6449
MD5 1bfa2dfe000742d4f29d6f1b9a5911bb
BLAKE2b-256 be582ad6c2a0d4fb1fc379a8f7523061bffaa62fdc522c5fb030230a998620e4

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: cendor_sdk-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 64.0 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bf61a2ef429c29d3fd126b1bbf4d1b6aecb403eb72e6e6d15a8b38253e41290b
MD5 dca63adc08267bf38ed6d10aea03f670
BLAKE2b-256 7a5231700a424d03d87585c4e33b4a6b76b5c933db17351932411838a989904e

See more details on using hashes here.

Provenance

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