canary-ops-sdk
The Operating System for AI Security — Python SDK for monitoring, securing, and auditing every AI agent and LLM application in production.
Zero-dependency telemetry, redaction, and firewall SDK. Works with any Python LLM library.
Install
pip install canary-ops-sdk
No runtime dependencies. Python 3.8+.
Quick start
from canary_ops import Canary
canary = Canary(
api_key="sk-canary-...", # from your Canary dashboard
agent_id="my-agent",
)
# Manual tracking
canary.track_prompt("What is the capital of France?", model="gpt-4o")
canary.track_response("Paris.", model="gpt-4o", tokens_in=10, tokens_out=3)
canary.track_tool_call("web_search", {"query": "Paris"}, {"results": [...]})
canary.flush() # or call shutdown() at process exit
OpenAI instrumentation
from openai import OpenAI
from canary_ops import Canary
canary = Canary(api_key="sk-canary-...", agent_id="my-agent")
client = canary.wrap_openai(OpenAI())
# All chat completions are now tracked automatically
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}],
)
Streaming is also supported — just pass stream=True.
Anthropic instrumentation
import anthropic
from canary_ops import Canary
canary = Canary(api_key="sk-canary-...", agent_id="my-agent")
client = canary.wrap_anthropic(anthropic.Anthropic())
response = client.messages.create(
model="claude-opus-4-5",
messages=[{"role": "user", "content": "Hello!"}],
max_tokens=256,
)
Prompt firewall
from canary_ops import Canary, CanaryBlockedError, ScanOptions
canary = Canary(api_key="sk-canary-...", agent_id="my-agent")
# scan() — returns a ScanResult, never raises
result = canary.scan(user_prompt, ScanOptions(remote=False))
if not result.allowed:
return "I can't help with that."
# guard() — raises CanaryBlockedError if the prompt is blocked
try:
safe_prompt = canary.guard(user_prompt)
except CanaryBlockedError as e:
print(f"Blocked: {e.scan_result.threats}")
Output scanning
# Scan a response for leaked secrets, PII, or exfiltration
from canary_ops import ScanResponseOptions
result = canary.scan_response(
llm_output,
ScanResponseOptions(throw_on_unsafe=True),
)
Canary tokens
# Plant a decoy credential in your agent's context
token = canary.plant_token()
system_prompt = f"Company API key: {token.token_value}\n{your_context}"
# If the token appears in any response, Canary fires a data_exfiltration alert
result = canary.scan_response(response_text)
RAG context scanning
from canary_ops import ScanContextOptions
docs = retriever.get_relevant_documents(query)
results = canary.scan_context(
[d.page_content for d in docs],
ScanContextOptions(concurrency=5),
)
safe_docs = [d for d, r in zip(docs, results) if r.allowed]
Configuration reference
from canary_ops import Canary, GuardConfig, RedactionConfig, RetryConfig
canary = Canary(
api_key="sk-canary-...",
agent_id="my-agent",
# Privacy
capture_content=True, # set False for metadata-only mode
max_content_length=10_000, # truncate long prompts
redaction=RedactionConfig(
secrets=True, # strip API keys, tokens, private keys
pii=True, # strip emails, phones, SSNs, credit cards
mode="mask", # "mask" | "hash" | "remove"
),
sample_rate=0.5, # only send 50% of events
# Firewall
guard=GuardConfig(
local=True, # run in-process heuristics
remote=True, # call the remote deep scanner
block_on_local=True, # short-circuit on high-confidence local hit
responses=False, # auto-scan every LLM response
),
fail_open=True, # allow prompts if the remote scanner is unreachable
# Resilience
timeout_ms=10_000,
retry=RetryConfig(retries=3, backoff_ms=250),
# Batching
flush_interval_ms=5_000, # drain queue every 5 s
max_batch_size=20, # flush immediately when queue hits 20
# Hooks
before_send=lambda event: event, # inspect/mutate/drop events
on_error=lambda exc: print(exc), # custom error handler
# Tagging
environment="production",
release="v1.2.3",
debug=False,
)
Error reference
| Exception | When it's raised |
|---|---|
CanaryBlockedError |
guard() or scan_response(..., throw_on_unsafe=True) when the firewall blocks |
CanaryApiError |
plant_token() when the API call fails |
CanaryNotInitializedError |
Calling SDK methods before Canary(...) is constructed |
CanaryBlockedError carries a .scan_result attribute with the full ScanResult.
Async support
All wrapper patching detects whether the underlying client's create method is a coroutine and patches it with an async wrapper automatically. The Canary client itself is thread-safe; background flushing runs on a daemon thread.
License
MIT © CryptoSuess & Txnchi
Metadata
Release files for canary-ops-sdk 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| canary_ops_sdk-0.2.0.tar.gz | 23.7 kB | Without provenance | Details for canary_ops_sdk-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| canary_ops_sdk-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for canary_ops_sdk-0.2.0-py3-none-any.whl |
Total release size: 44.9 kB
Release files / canary_ops_sdk-0.2.0.tar.gz
| Download URL | canary_ops_sdk-0.2.0.tar.gz |
|---|---|
| Size | 23.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2755a679155d6d2ac96e665415e0cf7003b74cbb16998656c54267a519437c8f
|
|
BLAKE2b-256 checksum How to use checksums |
b828167f06d641bb5573f00f130fa50927190f9463df374434d5ffb4b42d0991
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.14
|
Release files / canary_ops_sdk-0.2.0-py3-none-any.whl
| Download URL | canary_ops_sdk-0.2.0-py3-none-any.whl |
|---|---|
| Size | 21.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f8e2f581e7c6c43613d8cd8528d1e0ccaa73be4df9bb86184f3d96302303b497
|
|
BLAKE2b-256 checksum How to use checksums |
c52971b1fd6571324f990f842b32b929253694fc1587ea5e5f581327d3895dbc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.14
|
Security for canary-ops-sdk 0.2.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.