The Operating System for AI Security — monitor, secure, and audit every AI agent and LLM application in production.
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file canary_ops_sdk-0.1.0.tar.gz.
File metadata
- Download URL: canary_ops_sdk-0.1.0.tar.gz
- Upload date:
- Size: 21.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64c3a3c5d87a906c042fca84b82e2afc1876a7d813aa69b173f9731874198a5a
|
|
| MD5 |
02ae9e3ab0c7f081b07f2d047661b688
|
|
| BLAKE2b-256 |
fb123ee35ce9172f89098dce5c85ef814f2824ed3acdadedda7594a78fae5f7e
|
File details
Details for the file canary_ops_sdk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: canary_ops_sdk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eec725b1e4c789cce6dcec253b57bee982a857787c905ef06d534f4a9d6af1d3
|
|
| MD5 |
5e59b5d996720ff54c52de219c24c259
|
|
| BLAKE2b-256 |
808e57637f78e767e1c6a1df1bc4a369d59e1030afa430d76751c1386d0e597e
|