canary-ops-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main, develop]
8
+
9
+ jobs:
10
+ test:
11
+ name: Python ${{ matrix.python-version }}
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Python ${{ matrix.python-version }}
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install dependencies
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ pip install -e .
30
+ pip install pytest pytest-asyncio
31
+
32
+ - name: Run tests
33
+ run: pytest tests/ -v
34
+
35
+ publish:
36
+ name: Publish to PyPI
37
+ needs: test
38
+ runs-on: ubuntu-latest
39
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
40
+ environment: pypi
41
+ permissions:
42
+ id-token: write # for trusted publishing
43
+
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+
47
+ - name: Set up Python
48
+ uses: actions/setup-python@v5
49
+ with:
50
+ python-version: "3.12"
51
+
52
+ - name: Install build tools
53
+ run: pip install build
54
+
55
+ - name: Build distribution
56
+ run: python -m build
57
+
58
+ - name: Publish to PyPI
59
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,20 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .eggs/
8
+ .venv/
9
+ venv/
10
+ env/
11
+ .env
12
+ *.egg
13
+ MANIFEST
14
+ .pytest_cache/
15
+ .mypy_cache/
16
+ .ruff_cache/
17
+ htmlcov/
18
+ .coverage
19
+ coverage.xml
20
+ *.cover
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ ### Added
6
+
7
+ - Initial release: Python SDK for Canary AI Security.
8
+ - **`Canary`** class — main client with background batch flushing, redaction, firewall, and cost auto-computation.
9
+ - **`track_prompt()`**, **`track_response()`**, **`track_tool_call()`**, **`track_error()`** — telemetry event tracking.
10
+ - **`scan(prompt)`** — local + remote prompt firewall returning a `ScanResult`.
11
+ - **`guard(prompt)`** — raises `CanaryBlockedError` on blocked prompts.
12
+ - **`scan_response(text)`** — output-side guardrails: secret/PII regex + remote LLM-as-judge.
13
+ - **`plant_token()`** — synthetic canary token generation; auto-detected by `scan_response`.
14
+ - **`scan_context(docs)`** — parallel RAG document scanning (OWASP LLM04).
15
+ - **`trace(name)`** — context manager for recording arbitrary async steps as spans.
16
+ - **`wrap_fetch(fn)`** — decorator wrapping any callable with latency + error tracking.
17
+ - **`wrap_openai(client)`** — instrument `openai.OpenAI` / `openai.AsyncOpenAI` (sync + streaming + async).
18
+ - **`wrap_anthropic(client)`** — instrument `anthropic.Anthropic` / `anthropic.AsyncAnthropic` (sync + streaming + async).
19
+ - **19 local threat patterns** — ported from JS SDK: injection, jailbreak, system-prompt extraction, data exfiltration, leet-speak / encoding evasion.
20
+ - **Redaction engine** — masks/hashes/removes secrets (OpenAI, AWS, GitHub, Anthropic, Slack, Google, bearer tokens, JWTs, private keys) and optional PII (email, phone, SSN, credit card, IP).
21
+ - **Auto cost** — built-in pricing table for OpenAI, Anthropic, Gemini, Bedrock, and Mistral models.
22
+ - **Resilient transport** — `urllib`-based HTTP with retry + exponential backoff + jitter + circuit breaker.
23
+ - Zero runtime dependencies. Python 3.8+.
@@ -0,0 +1,232 @@
1
+ Metadata-Version: 2.4
2
+ Name: canary-ops-sdk
3
+ Version: 0.1.0
4
+ Summary: The Operating System for AI Security — monitor, secure, and audit every AI agent and LLM application in production.
5
+ Project-URL: Homepage, https://canary-ops.base44.app
6
+ Project-URL: Repository, https://github.com/CryptoSuess/canary-sdk-python
7
+ Project-URL: Bug Tracker, https://github.com/CryptoSuess/canary-sdk-python/issues
8
+ Project-URL: Changelog, https://github.com/CryptoSuess/canary-sdk-python/blob/main/CHANGELOG.md
9
+ Author: CryptoSuess & Txnchi
10
+ License: MIT
11
+ Keywords: agent-monitoring,ai-firewall,ai-security,canary,llm,llmops,observability,prompt-injection,telemetry
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Security
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+
27
+ # canary-ops-sdk
28
+
29
+ **The Operating System for AI Security** — Python SDK for monitoring, securing, and auditing every AI agent and LLM application in production.
30
+
31
+ Zero-dependency telemetry, redaction, and firewall SDK. Works with any Python LLM library.
32
+
33
+ [![PyPI](https://img.shields.io/pypi/v/canary-ops-sdk)](https://pypi.org/project/canary-ops-sdk/)
34
+ [![Python](https://img.shields.io/pypi/pyversions/canary-ops-sdk)](https://pypi.org/project/canary-ops-sdk/)
35
+
36
+ ---
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pip install canary-ops-sdk
42
+ ```
43
+
44
+ No runtime dependencies. Python 3.8+.
45
+
46
+ ---
47
+
48
+ ## Quick start
49
+
50
+ ```python
51
+ from canary_ops import Canary
52
+
53
+ canary = Canary(
54
+ api_key="sk-canary-...", # from your Canary dashboard
55
+ agent_id="my-agent",
56
+ )
57
+
58
+ # Manual tracking
59
+ canary.track_prompt("What is the capital of France?", model="gpt-4o")
60
+ canary.track_response("Paris.", model="gpt-4o", tokens_in=10, tokens_out=3)
61
+ canary.track_tool_call("web_search", {"query": "Paris"}, {"results": [...]})
62
+
63
+ canary.flush() # or call shutdown() at process exit
64
+ ```
65
+
66
+ ---
67
+
68
+ ## OpenAI instrumentation
69
+
70
+ ```python
71
+ from openai import OpenAI
72
+ from canary_ops import Canary
73
+
74
+ canary = Canary(api_key="sk-canary-...", agent_id="my-agent")
75
+ client = canary.wrap_openai(OpenAI())
76
+
77
+ # All chat completions are now tracked automatically
78
+ response = client.chat.completions.create(
79
+ model="gpt-4o",
80
+ messages=[{"role": "user", "content": "Hello!"}],
81
+ )
82
+ ```
83
+
84
+ Streaming is also supported — just pass `stream=True`.
85
+
86
+ ---
87
+
88
+ ## Anthropic instrumentation
89
+
90
+ ```python
91
+ import anthropic
92
+ from canary_ops import Canary
93
+
94
+ canary = Canary(api_key="sk-canary-...", agent_id="my-agent")
95
+ client = canary.wrap_anthropic(anthropic.Anthropic())
96
+
97
+ response = client.messages.create(
98
+ model="claude-opus-4-5",
99
+ messages=[{"role": "user", "content": "Hello!"}],
100
+ max_tokens=256,
101
+ )
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Prompt firewall
107
+
108
+ ```python
109
+ from canary_ops import Canary, CanaryBlockedError, ScanOptions
110
+
111
+ canary = Canary(api_key="sk-canary-...", agent_id="my-agent")
112
+
113
+ # scan() — returns a ScanResult, never raises
114
+ result = canary.scan(user_prompt, ScanOptions(remote=False))
115
+ if not result.allowed:
116
+ return "I can't help with that."
117
+
118
+ # guard() — raises CanaryBlockedError if the prompt is blocked
119
+ try:
120
+ safe_prompt = canary.guard(user_prompt)
121
+ except CanaryBlockedError as e:
122
+ print(f"Blocked: {e.scan_result.threats}")
123
+ ```
124
+
125
+ ---
126
+
127
+ ## Output scanning
128
+
129
+ ```python
130
+ # Scan a response for leaked secrets, PII, or exfiltration
131
+ from canary_ops import ScanResponseOptions
132
+
133
+ result = canary.scan_response(
134
+ llm_output,
135
+ ScanResponseOptions(throw_on_unsafe=True),
136
+ )
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Canary tokens
142
+
143
+ ```python
144
+ # Plant a decoy credential in your agent's context
145
+ token = canary.plant_token()
146
+ system_prompt = f"Company API key: {token.token_value}\n{your_context}"
147
+
148
+ # If the token appears in any response, Canary fires a data_exfiltration alert
149
+ result = canary.scan_response(response_text)
150
+ ```
151
+
152
+ ---
153
+
154
+ ## RAG context scanning
155
+
156
+ ```python
157
+ from canary_ops import ScanContextOptions
158
+
159
+ docs = retriever.get_relevant_documents(query)
160
+ results = canary.scan_context(
161
+ [d.page_content for d in docs],
162
+ ScanContextOptions(concurrency=5),
163
+ )
164
+ safe_docs = [d for d, r in zip(docs, results) if r.allowed]
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Configuration reference
170
+
171
+ ```python
172
+ from canary_ops import Canary, GuardConfig, RedactionConfig, RetryConfig
173
+
174
+ canary = Canary(
175
+ api_key="sk-canary-...",
176
+ agent_id="my-agent",
177
+ # Privacy
178
+ capture_content=True, # set False for metadata-only mode
179
+ max_content_length=10_000, # truncate long prompts
180
+ redaction=RedactionConfig(
181
+ secrets=True, # strip API keys, tokens, private keys
182
+ pii=True, # strip emails, phones, SSNs, credit cards
183
+ mode="mask", # "mask" | "hash" | "remove"
184
+ ),
185
+ sample_rate=0.5, # only send 50% of events
186
+ # Firewall
187
+ guard=GuardConfig(
188
+ local=True, # run in-process heuristics
189
+ remote=True, # call the remote deep scanner
190
+ block_on_local=True, # short-circuit on high-confidence local hit
191
+ responses=False, # auto-scan every LLM response
192
+ ),
193
+ fail_open=True, # allow prompts if the remote scanner is unreachable
194
+ # Resilience
195
+ timeout_ms=10_000,
196
+ retry=RetryConfig(retries=3, backoff_ms=250),
197
+ # Batching
198
+ flush_interval_ms=5_000, # drain queue every 5 s
199
+ max_batch_size=20, # flush immediately when queue hits 20
200
+ # Hooks
201
+ before_send=lambda event: event, # inspect/mutate/drop events
202
+ on_error=lambda exc: print(exc), # custom error handler
203
+ # Tagging
204
+ environment="production",
205
+ release="v1.2.3",
206
+ debug=False,
207
+ )
208
+ ```
209
+
210
+ ---
211
+
212
+ ## Error reference
213
+
214
+ | Exception | When it's raised |
215
+ |---|---|
216
+ | `CanaryBlockedError` | `guard()` or `scan_response(..., throw_on_unsafe=True)` when the firewall blocks |
217
+ | `CanaryApiError` | `plant_token()` when the API call fails |
218
+ | `CanaryNotInitializedError` | Calling SDK methods before `Canary(...)` is constructed |
219
+
220
+ `CanaryBlockedError` carries a `.scan_result` attribute with the full `ScanResult`.
221
+
222
+ ---
223
+
224
+ ## Async support
225
+
226
+ 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.
227
+
228
+ ---
229
+
230
+ ## License
231
+
232
+ MIT © CryptoSuess & Txnchi
@@ -0,0 +1,206 @@
1
+ # canary-ops-sdk
2
+
3
+ **The Operating System for AI Security** — Python SDK for monitoring, securing, and auditing every AI agent and LLM application in production.
4
+
5
+ Zero-dependency telemetry, redaction, and firewall SDK. Works with any Python LLM library.
6
+
7
+ [![PyPI](https://img.shields.io/pypi/v/canary-ops-sdk)](https://pypi.org/project/canary-ops-sdk/)
8
+ [![Python](https://img.shields.io/pypi/pyversions/canary-ops-sdk)](https://pypi.org/project/canary-ops-sdk/)
9
+
10
+ ---
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pip install canary-ops-sdk
16
+ ```
17
+
18
+ No runtime dependencies. Python 3.8+.
19
+
20
+ ---
21
+
22
+ ## Quick start
23
+
24
+ ```python
25
+ from canary_ops import Canary
26
+
27
+ canary = Canary(
28
+ api_key="sk-canary-...", # from your Canary dashboard
29
+ agent_id="my-agent",
30
+ )
31
+
32
+ # Manual tracking
33
+ canary.track_prompt("What is the capital of France?", model="gpt-4o")
34
+ canary.track_response("Paris.", model="gpt-4o", tokens_in=10, tokens_out=3)
35
+ canary.track_tool_call("web_search", {"query": "Paris"}, {"results": [...]})
36
+
37
+ canary.flush() # or call shutdown() at process exit
38
+ ```
39
+
40
+ ---
41
+
42
+ ## OpenAI instrumentation
43
+
44
+ ```python
45
+ from openai import OpenAI
46
+ from canary_ops import Canary
47
+
48
+ canary = Canary(api_key="sk-canary-...", agent_id="my-agent")
49
+ client = canary.wrap_openai(OpenAI())
50
+
51
+ # All chat completions are now tracked automatically
52
+ response = client.chat.completions.create(
53
+ model="gpt-4o",
54
+ messages=[{"role": "user", "content": "Hello!"}],
55
+ )
56
+ ```
57
+
58
+ Streaming is also supported — just pass `stream=True`.
59
+
60
+ ---
61
+
62
+ ## Anthropic instrumentation
63
+
64
+ ```python
65
+ import anthropic
66
+ from canary_ops import Canary
67
+
68
+ canary = Canary(api_key="sk-canary-...", agent_id="my-agent")
69
+ client = canary.wrap_anthropic(anthropic.Anthropic())
70
+
71
+ response = client.messages.create(
72
+ model="claude-opus-4-5",
73
+ messages=[{"role": "user", "content": "Hello!"}],
74
+ max_tokens=256,
75
+ )
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Prompt firewall
81
+
82
+ ```python
83
+ from canary_ops import Canary, CanaryBlockedError, ScanOptions
84
+
85
+ canary = Canary(api_key="sk-canary-...", agent_id="my-agent")
86
+
87
+ # scan() — returns a ScanResult, never raises
88
+ result = canary.scan(user_prompt, ScanOptions(remote=False))
89
+ if not result.allowed:
90
+ return "I can't help with that."
91
+
92
+ # guard() — raises CanaryBlockedError if the prompt is blocked
93
+ try:
94
+ safe_prompt = canary.guard(user_prompt)
95
+ except CanaryBlockedError as e:
96
+ print(f"Blocked: {e.scan_result.threats}")
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Output scanning
102
+
103
+ ```python
104
+ # Scan a response for leaked secrets, PII, or exfiltration
105
+ from canary_ops import ScanResponseOptions
106
+
107
+ result = canary.scan_response(
108
+ llm_output,
109
+ ScanResponseOptions(throw_on_unsafe=True),
110
+ )
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Canary tokens
116
+
117
+ ```python
118
+ # Plant a decoy credential in your agent's context
119
+ token = canary.plant_token()
120
+ system_prompt = f"Company API key: {token.token_value}\n{your_context}"
121
+
122
+ # If the token appears in any response, Canary fires a data_exfiltration alert
123
+ result = canary.scan_response(response_text)
124
+ ```
125
+
126
+ ---
127
+
128
+ ## RAG context scanning
129
+
130
+ ```python
131
+ from canary_ops import ScanContextOptions
132
+
133
+ docs = retriever.get_relevant_documents(query)
134
+ results = canary.scan_context(
135
+ [d.page_content for d in docs],
136
+ ScanContextOptions(concurrency=5),
137
+ )
138
+ safe_docs = [d for d, r in zip(docs, results) if r.allowed]
139
+ ```
140
+
141
+ ---
142
+
143
+ ## Configuration reference
144
+
145
+ ```python
146
+ from canary_ops import Canary, GuardConfig, RedactionConfig, RetryConfig
147
+
148
+ canary = Canary(
149
+ api_key="sk-canary-...",
150
+ agent_id="my-agent",
151
+ # Privacy
152
+ capture_content=True, # set False for metadata-only mode
153
+ max_content_length=10_000, # truncate long prompts
154
+ redaction=RedactionConfig(
155
+ secrets=True, # strip API keys, tokens, private keys
156
+ pii=True, # strip emails, phones, SSNs, credit cards
157
+ mode="mask", # "mask" | "hash" | "remove"
158
+ ),
159
+ sample_rate=0.5, # only send 50% of events
160
+ # Firewall
161
+ guard=GuardConfig(
162
+ local=True, # run in-process heuristics
163
+ remote=True, # call the remote deep scanner
164
+ block_on_local=True, # short-circuit on high-confidence local hit
165
+ responses=False, # auto-scan every LLM response
166
+ ),
167
+ fail_open=True, # allow prompts if the remote scanner is unreachable
168
+ # Resilience
169
+ timeout_ms=10_000,
170
+ retry=RetryConfig(retries=3, backoff_ms=250),
171
+ # Batching
172
+ flush_interval_ms=5_000, # drain queue every 5 s
173
+ max_batch_size=20, # flush immediately when queue hits 20
174
+ # Hooks
175
+ before_send=lambda event: event, # inspect/mutate/drop events
176
+ on_error=lambda exc: print(exc), # custom error handler
177
+ # Tagging
178
+ environment="production",
179
+ release="v1.2.3",
180
+ debug=False,
181
+ )
182
+ ```
183
+
184
+ ---
185
+
186
+ ## Error reference
187
+
188
+ | Exception | When it's raised |
189
+ |---|---|
190
+ | `CanaryBlockedError` | `guard()` or `scan_response(..., throw_on_unsafe=True)` when the firewall blocks |
191
+ | `CanaryApiError` | `plant_token()` when the API call fails |
192
+ | `CanaryNotInitializedError` | Calling SDK methods before `Canary(...)` is constructed |
193
+
194
+ `CanaryBlockedError` carries a `.scan_result` attribute with the full `ScanResult`.
195
+
196
+ ---
197
+
198
+ ## Async support
199
+
200
+ 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.
201
+
202
+ ---
203
+
204
+ ## License
205
+
206
+ MIT © CryptoSuess & Txnchi
@@ -0,0 +1,56 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "canary-ops-sdk"
7
+ version = "0.1.0"
8
+ description = "The Operating System for AI Security — monitor, secure, and audit every AI agent and LLM application in production."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = {text = "MIT"}
12
+ authors = [{name = "CryptoSuess & Txnchi"}]
13
+ keywords = [
14
+ "canary",
15
+ "ai-security",
16
+ "llm",
17
+ "observability",
18
+ "telemetry",
19
+ "ai-firewall",
20
+ "prompt-injection",
21
+ "agent-monitoring",
22
+ "llmops",
23
+ ]
24
+ classifiers = [
25
+ "Development Status :: 3 - Alpha",
26
+ "Intended Audience :: Developers",
27
+ "License :: OSI Approved :: MIT License",
28
+ "Programming Language :: Python :: 3",
29
+ "Programming Language :: Python :: 3.8",
30
+ "Programming Language :: Python :: 3.9",
31
+ "Programming Language :: Python :: 3.10",
32
+ "Programming Language :: Python :: 3.11",
33
+ "Programming Language :: Python :: 3.12",
34
+ "Topic :: Security",
35
+ "Topic :: Software Development :: Libraries :: Python Modules",
36
+ "Typing :: Typed",
37
+ ]
38
+ dependencies = []
39
+
40
+ [project.urls]
41
+ Homepage = "https://canary-ops.base44.app"
42
+ Repository = "https://github.com/CryptoSuess/canary-sdk-python"
43
+ "Bug Tracker" = "https://github.com/CryptoSuess/canary-sdk-python/issues"
44
+ Changelog = "https://github.com/CryptoSuess/canary-sdk-python/blob/main/CHANGELOG.md"
45
+
46
+ [tool.hatch.build.targets.wheel]
47
+ packages = ["src/canary_ops"]
48
+
49
+ [tool.pytest.ini_options]
50
+ testpaths = ["tests"]
51
+ asyncio_mode = "auto"
52
+
53
+ [tool.mypy]
54
+ python_version = "3.8"
55
+ strict = true
56
+ ignore_missing_imports = true
@@ -0,0 +1,65 @@
1
+ """
2
+ canary-ops-sdk — The Operating System for AI Security.
3
+
4
+ Quick start::
5
+
6
+ from canary_ops import Canary
7
+
8
+ canary = Canary(api_key="sk-canary-...", agent_id="my-agent")
9
+ canary.track_prompt("Hello, world!")
10
+ canary.flush()
11
+ """
12
+ from ._client import (
13
+ Canary,
14
+ CanaryApiError,
15
+ CanaryBlockedError,
16
+ CanaryNotInitializedError,
17
+ )
18
+ from ._types import (
19
+ CanaryConfig,
20
+ CanaryToken,
21
+ DetectedThreat,
22
+ FirewallAction,
23
+ GuardConfig,
24
+ PlantTokenOptions,
25
+ RedactionConfig,
26
+ RetryConfig,
27
+ ScanContextOptions,
28
+ ScanOptions,
29
+ ScanResponseOptions,
30
+ ScanResult,
31
+ TelemetryEvent,
32
+ TokenType,
33
+ )
34
+ from .instrument import wrap_anthropic, wrap_openai
35
+
36
+ __version__ = "0.1.0"
37
+
38
+ __all__ = [
39
+ # Main client
40
+ "Canary",
41
+ # Errors
42
+ "CanaryNotInitializedError",
43
+ "CanaryBlockedError",
44
+ "CanaryApiError",
45
+ # Types
46
+ "CanaryConfig",
47
+ "TelemetryEvent",
48
+ "ScanResult",
49
+ "ScanOptions",
50
+ "ScanResponseOptions",
51
+ "PlantTokenOptions",
52
+ "ScanContextOptions",
53
+ "CanaryToken",
54
+ "TokenType",
55
+ "DetectedThreat",
56
+ "FirewallAction",
57
+ "RedactionConfig",
58
+ "GuardConfig",
59
+ "RetryConfig",
60
+ # Standalone instrumentors
61
+ "wrap_openai",
62
+ "wrap_anthropic",
63
+ # Version
64
+ "__version__",
65
+ ]