computer-agent-py 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.
Files changed (25) hide show
  1. computer_agent_py-0.1.0/PKG-INFO +307 -0
  2. computer_agent_py-0.1.0/README.md +264 -0
  3. computer_agent_py-0.1.0/pyproject.toml +128 -0
  4. computer_agent_py-0.1.0/src/computeragent/__init__.py +90 -0
  5. computer_agent_py-0.1.0/src/computeragent/_proxy/__init__.py +8 -0
  6. computer_agent_py-0.1.0/src/computeragent/_proxy/client.py +225 -0
  7. computer_agent_py-0.1.0/src/computeragent/_proxy/query.py +165 -0
  8. computer_agent_py-0.1.0/src/computeragent/policy/__init__.py +59 -0
  9. computer_agent_py-0.1.0/src/computeragent/policy/authorizer.py +161 -0
  10. computer_agent_py-0.1.0/src/computeragent/policy/cedar.py +182 -0
  11. computer_agent_py-0.1.0/src/computeragent/policy/opa.py +124 -0
  12. computer_agent_py-0.1.0/src/computeragent/policy/types.py +121 -0
  13. computer_agent_py-0.1.0/src/computeragent/py.typed +0 -0
  14. computer_agent_py-0.1.0/src/computeragent/telemetry/__init__.py +24 -0
  15. computer_agent_py-0.1.0/src/computeragent/telemetry/config.py +176 -0
  16. computer_agent_py-0.1.0/src/computeragent/telemetry/event.py +355 -0
  17. computer_agent_py-0.1.0/src/computeragent/telemetry/middleware/__init__.py +8 -0
  18. computer_agent_py-0.1.0/src/computeragent/telemetry/middleware/guardrails.py +127 -0
  19. computer_agent_py-0.1.0/src/computeragent/telemetry/middleware/pii.py +158 -0
  20. computer_agent_py-0.1.0/src/computeragent/telemetry/pipeline.py +160 -0
  21. computer_agent_py-0.1.0/src/computeragent/telemetry/sinks/__init__.py +28 -0
  22. computer_agent_py-0.1.0/src/computeragent/telemetry/sinks/agentos.py +442 -0
  23. computer_agent_py-0.1.0/src/computeragent/telemetry/sinks/message_archive.py +136 -0
  24. computer_agent_py-0.1.0/src/computeragent/telemetry/sinks/otel.py +375 -0
  25. computer_agent_py-0.1.0/src/computeragent/types.py +13 -0
@@ -0,0 +1,307 @@
1
+ Metadata-Version: 2.3
2
+ Name: computer-agent-py
3
+ Version: 0.1.0
4
+ Summary: Drop-in replacement for claude-agent-sdk that adds a proxied telemetry pipeline (PII redaction + guardrails) with OpenTelemetry and AgentOS sinks.
5
+ Keywords: computeragent,claude-agent-sdk,claude,agent,telemetry,otel,opentelemetry,agentos,pii
6
+ Author: Abhi Bhat
7
+ Author-email: Abhi Bhat <abhishek.bhat@lyzr.ai>
8
+ License: MIT
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Typing :: Typed
20
+ Requires-Dist: claude-agent-sdk>=0.2,<0.3
21
+ Requires-Dist: typing-extensions>=4.12
22
+ Requires-Dist: motor>=3.5 ; extra == 'agentos'
23
+ Requires-Dist: opentelemetry-api>=1.27 ; extra == 'all'
24
+ Requires-Dist: opentelemetry-sdk>=1.27 ; extra == 'all'
25
+ Requires-Dist: opentelemetry-exporter-otlp>=1.27 ; extra == 'all'
26
+ Requires-Dist: opentelemetry-semantic-conventions>=0.48b0 ; extra == 'all'
27
+ Requires-Dist: motor>=3.5 ; extra == 'all'
28
+ Requires-Dist: cedarpy>=4,<5 ; extra == 'all'
29
+ Requires-Dist: cedarpy>=4,<5 ; extra == 'cedar'
30
+ Requires-Dist: opentelemetry-api>=1.27 ; extra == 'otel'
31
+ Requires-Dist: opentelemetry-sdk>=1.27 ; extra == 'otel'
32
+ Requires-Dist: opentelemetry-exporter-otlp>=1.27 ; extra == 'otel'
33
+ Requires-Dist: opentelemetry-semantic-conventions>=0.48b0 ; extra == 'otel'
34
+ Requires-Python: >=3.10
35
+ Project-URL: Changelog, https://github.com/open-gitagent/computer-agent-py/blob/main/CHANGELOG.md
36
+ Project-URL: Homepage, https://github.com/open-gitagent/computer-agent-py
37
+ Project-URL: Issues, https://github.com/open-gitagent/computer-agent-py/issues
38
+ Provides-Extra: agentos
39
+ Provides-Extra: all
40
+ Provides-Extra: cedar
41
+ Provides-Extra: otel
42
+ Description-Content-Type: text/markdown
43
+
44
+ # computer-agent-py
45
+
46
+ [![PyPI](https://img.shields.io/pypi/v/computer-agent-py.svg)](https://pypi.org/project/computer-agent-py/)
47
+ [![Python](https://img.shields.io/pypi/pyversions/computer-agent-py.svg)](https://pypi.org/project/computer-agent-py/)
48
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
49
+
50
+ **Drop-in replacement for [`claude-agent-sdk`](https://pypi.org/project/claude-agent-sdk/)** — change the import line, get a proxied telemetry pipeline with PII redaction, configurable OTel export, policy-based tool authorization, and full AgentOS integration for free.
51
+
52
+ ```diff
53
+ - from claude_agent_sdk import ClaudeAgentOptions, query
54
+ - from claude_agent_sdk.types import ResultMessage
55
+ + from computeragent import ClaudeAgentOptions, query
56
+ + from computeragent.types import ResultMessage
57
+ ```
58
+
59
+ Every other line stays identical. `isinstance(msg, ResultMessage)` still works. The `claude` CLI subprocess, AWS Bedrock auth, MCP servers, permission modes, `cwd`, `add_dirs` — all behave exactly as the upstream SDK does.
60
+
61
+ > **Package vs import name** — PyPI distribution is `computer-agent-py` (hyphens for the wheel); the import name is `computeragent` (Python doesn't allow hyphens). So `pip install computer-agent-py` then `from computeragent import …`.
62
+
63
+ ## Why use this
64
+
65
+ Adopting `computer-agent-py` in place of `claude-agent-sdk` gives you, without rewriting your agent code:
66
+
67
+ - **OpenTelemetry traces** following the GenAI Semantic Conventions, vendor-neutral (New Relic, Datadog, ClickHouse, Honeycomb, Tempo, Jaeger — one env-var change).
68
+ - **PII redaction** at the package boundary — email, phone, SSN, credit cards, AWS keys redacted before anything reaches a sink.
69
+ - **Generic guardrails** — attribute truncation, tool allowlists, per-session cost ceilings, content filters.
70
+ - **Policy-based tool-use authorization** — gate every tool call through OPA (remote) or Cedar (in-process). Fail-closed by default.
71
+ - **AgentOS visibility** — write to the same Mongo collections (`agent_registry`, `agent_logs`, `agent_messages`, `sessions`, `slack_threads`) the AgentOS frontend already reads. Library-mode agents show up in the Agents list, Logs tab, Chat transcript, and (with the harness running) live chat sandboxes.
72
+ - **Per-message archive** — every message, tool call, and policy decision archived to `agent_messages` for replay, RAG, and forensic audit.
73
+
74
+ ## Install
75
+
76
+ ```bash
77
+ pip install computer-agent-py # core drop-in + OPA policy engine
78
+ pip install 'computer-agent-py[otel]' # + OpenTelemetry sink
79
+ pip install 'computer-agent-py[agentos]' # + AgentOS Mongo sinks
80
+ pip install 'computer-agent-py[cedar]' # + Cedar policy engine (in-process)
81
+ pip install 'computer-agent-py[all]' # everything
82
+ ```
83
+
84
+ **Prerequisite** — same as upstream: the `claude` CLI binary on `PATH` and Anthropic / Bedrock credentials in the environment.
85
+
86
+ ## Quickstart
87
+
88
+ ```python
89
+ import asyncio
90
+ from computeragent import ClaudeAgentOptions, query
91
+ from computeragent.types import ResultMessage
92
+
93
+ async def main():
94
+ options = ClaudeAgentOptions(
95
+ model="claude-sonnet-4-5",
96
+ system_prompt="You are a helpful assistant.",
97
+ allowed_tools=["Read", "Glob", "Grep"],
98
+ permission_mode="bypassPermissions",
99
+ )
100
+
101
+ async for message in query(prompt="Summarize the README.md in this directory.", options=options):
102
+ if isinstance(message, ResultMessage):
103
+ print(f"answer ({message.num_turns} turns, ${message.total_cost_usd:.4f}):")
104
+ print(message.result)
105
+
106
+ asyncio.run(main())
107
+ ```
108
+
109
+ That's it — same shape as `claude-agent-sdk`. Telemetry is configured from env vars; without anything set, nothing leaves your process.
110
+
111
+ ## Configure telemetry
112
+
113
+ ### Env-driven (zero code change)
114
+
115
+ | Variable | Effect |
116
+ |---|---|
117
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Enables OTLP/HTTP export. Unset → console exporter (debug). |
118
+ | `OTEL_EXPORTER_OTLP_HEADERS` | Comma-separated `key=value` (e.g. `api-key=NRRX-...` for New Relic). |
119
+ | `OTEL_SERVICE_NAME` | `service.name` attribute on every span. Default: `computeragent`. |
120
+ | `COMPUTERAGENT_OTEL` | `disabled` to suppress OtelSink. |
121
+ | `AGENTOS_MONGO_URL` | When set + `[agentos]` installed, attaches AgentOS sinks (registry, logs, sessions, agent_messages, slack_threads). |
122
+ | `AGENTOS_MONGO_DB` | Mongo database name. Default: `agentos`. |
123
+ | `COMPUTERAGENT_CAPTURE_CONTENT` | `1` to include prompts/responses on OTel spans. Default: off. |
124
+ | `COMPUTERAGENT_CAPTURE_CONTENT_MODE` | `events` (default) \| `attributes` \| `both`. |
125
+
126
+ ### Programmatic
127
+
128
+ ```python
129
+ from computeragent import configure, PiiRedactor, GuardrailFilter
130
+ from computeragent.telemetry.sinks import OtelSink, AgentRegistrySink, MongoMessageSink
131
+
132
+ configure(
133
+ middleware=[
134
+ PiiRedactor(strategy="hash", extra_patterns=[r"BADGE-\d{6}"]),
135
+ GuardrailFilter(
136
+ max_attribute_length=4096,
137
+ tool_name_allowlist={"Read", "Glob", "Grep", "mcp__nordassist-tools__*"},
138
+ cost_ceiling_usd=1.50,
139
+ ),
140
+ ],
141
+ sinks=[
142
+ OtelSink(), # picks up env
143
+ AgentRegistrySink(mongo_url="mongodb://..."), # registry + logs + sessions + slack_threads
144
+ MongoMessageSink(mongo_url="mongodb://..."), # per-message archive
145
+ ],
146
+ )
147
+ ```
148
+
149
+ ## Vendor-neutral OTel destinations
150
+
151
+ The package emits standard OTLP — point it at any backend by setting two env vars. No code change.
152
+
153
+ | Destination | `OTEL_EXPORTER_OTLP_ENDPOINT` | `OTEL_EXPORTER_OTLP_HEADERS` |
154
+ |---|---|---|
155
+ | **New Relic** | `https://otlp.nr-data.net` | `api-key=<NR_LICENSE_KEY>` |
156
+ | **Datadog** (via DD Agent OTLP) | `http://localhost:4318` | _(unset; agent handles auth)_ |
157
+ | **Honeycomb** | `https://api.honeycomb.io` | `x-honeycomb-team=<KEY>` |
158
+ | **Grafana Cloud Tempo** | `https://tempo-prod-...grafana.net:443` | `authorization=Basic <base64>` |
159
+ | **Self-hosted Jaeger / Tempo / SigNoz** | `http://<host>:4318` | _(unset)_ |
160
+ | **Local console (debug)** | _(unset)_ | _(unset)_ |
161
+
162
+ Full recipe table — including direct New Relic / Datadog without an OTel collector — is in [`examples/e2e/destinations.md`](examples/e2e/destinations.md).
163
+
164
+ ## Policy-based tool-use authorization
165
+
166
+ For agents that need stronger guardrails than `permission_mode`, attach an external policy engine. Activation is a single new option-field; the rest of the worker code is unchanged.
167
+
168
+ ```python
169
+ from computeragent import ClaudeAgentOptions, PolicyPrincipal, PolicyResource, query
170
+ from computeragent.policy import OpaPolicyEngine, PolicyToolAuthorizer
171
+
172
+ opa = OpaPolicyEngine(
173
+ url="http://opa.platform:8181",
174
+ policy_path="computeragent/tools/allow",
175
+ fail_mode="deny", # default — engine errors deny the call
176
+ )
177
+ authorizer = PolicyToolAuthorizer(
178
+ engine=opa,
179
+ principal_resolver=lambda ctx: PolicyPrincipal(id="alice", groups=["engineer"]),
180
+ resource_resolver=lambda ctx: PolicyResource(agent_name="nordassist", model="claude-sonnet-4-5"),
181
+ context_resolver=lambda ctx: {"env": "prod"},
182
+ )
183
+
184
+ options = ClaudeAgentOptions(
185
+ ...,
186
+ permission_mode="default", # was "bypassPermissions"
187
+ can_use_tool=authorizer,
188
+ )
189
+ ```
190
+
191
+ Swap `OpaPolicyEngine` for `CedarPolicyEngine` (install with `pip install 'computer-agent-py[cedar]'`) and the worker code is identical:
192
+
193
+ ```python
194
+ from computeragent.policy import CedarPolicyEngine
195
+
196
+ cedar = CedarPolicyEngine(
197
+ policies=open("policies/computeragent.cedar").read(),
198
+ fail_mode="deny",
199
+ )
200
+ authorizer = PolicyToolAuthorizer(engine=cedar, principal_resolver=..., ...)
201
+ ```
202
+
203
+ Sample policies are in [`examples/policies/`](examples/policies/) — one Rego file for OPA, one Cedar file. Each policy receives a canonical `PolicyInput` shape (`principal`, `action`, `resource`, `context`) so the engine choice is purely operational.
204
+
205
+ Every authorization decision emits a `policy_decision` telemetry event — `OtelSink` annotates the active `execute_tool` span with `policy.decision`, `policy.reason`, `policy.engine`, and `policy.latency_ms` so security audits and span queries co-locate.
206
+
207
+ ## AgentOS integration
208
+
209
+ When `[agentos]` is installed and `AGENTOS_MONGO_URL` is set, every agent run writes to the Mongo collections the AgentOS frontend already reads:
210
+
211
+ | Collection | Per | What's in it |
212
+ |---|---|---|
213
+ | `agent_registry` | agent name | Identity + harness + model + last-seen; idempotent upsert |
214
+ | `agent_logs` | run | Rolled-up query/reply + tokens + cost + ok/error — drives the Logs tab |
215
+ | `sessions` | session | `entries[]` of `{type, text}` chat-bubble messages — drives the Chat tab transcript |
216
+ | `slack_threads` | session | TS parity row that drives the per-agent `sessionCount` + `lastActivity` aggregates |
217
+ | `agent_messages` | message | Per-event archive (`user_message`, `assistant_message`, `tool_use`, `tool_result`, `usage_snapshot`, `policy_decision`, `system_message`) for replay, RAG, audit |
218
+
219
+ The doc shapes are byte-for-byte compatible with the TypeScript `@open-gitagent/agent-registry-mongo` package — Python-driven agents show up in the same AgentOS UI that hosted TS agents do, with no frontend change.
220
+
221
+ ### Live chat for library-mode agents
222
+
223
+ When the AgentRegistrySink writes its `agent_registry.source` row, it includes a full inline `IdentitySource` with `files: {agent.yaml, CLAUDE.md}` derived from your `ClaudeAgentOptions`. If a user clicks "New Chat" on the agent in the AgentOS SPA, the harness can clone those files into a sandbox workdir and spawn a live conversation — same UX as hosted (git-sourced) agents. The historical transcript stays available in the Chat tab regardless.
224
+
225
+ ### DocumentDB compatibility
226
+
227
+ Prod deployments on AWS DocumentDB work without changes. The sinks use only operators DocumentDB supports — `$set`, `$setOnInsert`, `$push`, `update_one(upsert=True)`, `insert_one`. No aggregation pipelines, transactions, change streams, or TTL indexes. Set `MONGO_URL` with the standard `tls=true&tlsCAFile=...` params and mount the DocumentDB CA bundle.
228
+
229
+ ## Architecture
230
+
231
+ ```
232
+ user code: from computeragent import query, ClaudeAgentOptions
233
+
234
+
235
+ computeragent._proxy.query ──┐
236
+ │ │
237
+ ▼ │ PolicyToolAuthorizer
238
+ claude_agent_sdk → claude CLI subprocess → Bedrock│ (OPA / Cedar)
239
+ │ │ via can_use_tool
240
+ ▼ │
241
+ yielded messages │
242
+ │ │
243
+ ▼ │
244
+ TelemetryPipeline (taps stream) │
245
+ │ │
246
+ ┌──── middleware ─────┐ │
247
+ │ PiiRedactor │ │
248
+ │ GuardrailFilter │ ◄────────────────────┘
249
+ │ <user-defined> │
250
+ └────────┬────────────┘
251
+
252
+ ┌──── fan-out to sinks ───────────────────────────┐
253
+ │ │
254
+ ▼ ▼ ▼ ▼
255
+ OtelSink AgentRegistrySink MongoMessageSink <user>
256
+ │ │ │
257
+ ▼ ▼ ▼
258
+ OTLP backend agent_registry agent_messages
259
+ (NR / DD / agent_logs (per-message
260
+ ClickHouse / sessions archive)
261
+ Tempo …) slack_threads
262
+ (drives AgentOS UI)
263
+ ```
264
+
265
+ The proxy is a pure tap — messages are never modified or reordered. Sinks run as background tasks so a slow exporter never stalls the agent hot path; `query()`'s `finally` block awaits them with a 5 s default timeout. Telemetry never breaks an agent run: middleware and sink exceptions are absorbed and logged.
266
+
267
+ ## Live e2e against AgentOS
268
+
269
+ [`examples/e2e/`](examples/e2e/) contains a recipe for standing up the full TypeScript stack (mongo + clickhouse + otel-collector + harness + agentos-server + SPA) via docker-compose and running this package against it. After ~60s of warm-up plus a 30s Python script run, you'll see the agent appear in the SPA's Agents list with `logCount`, `sessionCount`, `lastActivity`, and `activeSandboxes` populated; the Logs tab will show the rollup; the Chat tab will show the per-message transcript; the Observability tab will show the OTel trace tree. See [`examples/e2e/README.md`](examples/e2e/README.md).
270
+
271
+ ## Examples
272
+
273
+ | File | Demonstrates |
274
+ |---|---|
275
+ | [`examples/pdf_drop_in.py`](examples/pdf_drop_in.py) | The minimum drop-in change |
276
+ | [`examples/with_otel.py`](examples/with_otel.py) | OTel pointed at a local collector |
277
+ | [`examples/with_new_relic.py`](examples/with_new_relic.py) | OTel pointed at New Relic (just env vars) |
278
+ | [`examples/with_datadog.py`](examples/with_datadog.py) | OTel pointed at Datadog |
279
+ | [`examples/with_agentos.py`](examples/with_agentos.py) | AgentOS Mongo writes |
280
+ | [`examples/with_message_archive.py`](examples/with_message_archive.py) | Per-message archive |
281
+ | [`examples/with_pii_redaction.py`](examples/with_pii_redaction.py) | PII middleware in front of every sink |
282
+ | [`examples/with_opa_policy.py`](examples/with_opa_policy.py) | OPA-gated tool use |
283
+ | [`examples/with_cedar_policy.py`](examples/with_cedar_policy.py) | Cedar-gated tool use (in-process) |
284
+ | [`examples/multi_sink.py`](examples/multi_sink.py) | All sinks + all guardrails together |
285
+ | [`examples/e2e/run_live_demo.py`](examples/e2e/run_live_demo.py) | Full live demo against the AgentOS docker-compose stack |
286
+
287
+ ## Upstream pin
288
+
289
+ This release tracks **`claude-agent-sdk` 0.2.x**. The pinned upstream version is recorded in [`CHANGELOG.md`](CHANGELOG.md). Bump deliberately — wire-protocol field additions in upstream get re-exported automatically (identity-preserving), but any behavioral changes need a passthrough audit.
290
+
291
+ ## Development
292
+
293
+ ```bash
294
+ git clone https://github.com/open-gitagent/computer-agent-py
295
+ cd computer-agent-py
296
+ uv sync --all-extras --dev
297
+ uv run ruff check src tests
298
+ uv run ruff format --check src tests
299
+ uv run mypy src
300
+ uv run pytest -q # 120+ unit tests
301
+ uv run pytest -q -m integration # requires ANTHROPIC_API_KEY + claude CLI
302
+ uv build
303
+ ```
304
+
305
+ ## License
306
+
307
+ MIT — see [`LICENSE`](LICENSE).
@@ -0,0 +1,264 @@
1
+ # computer-agent-py
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/computer-agent-py.svg)](https://pypi.org/project/computer-agent-py/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/computer-agent-py.svg)](https://pypi.org/project/computer-agent-py/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
+
7
+ **Drop-in replacement for [`claude-agent-sdk`](https://pypi.org/project/claude-agent-sdk/)** — change the import line, get a proxied telemetry pipeline with PII redaction, configurable OTel export, policy-based tool authorization, and full AgentOS integration for free.
8
+
9
+ ```diff
10
+ - from claude_agent_sdk import ClaudeAgentOptions, query
11
+ - from claude_agent_sdk.types import ResultMessage
12
+ + from computeragent import ClaudeAgentOptions, query
13
+ + from computeragent.types import ResultMessage
14
+ ```
15
+
16
+ Every other line stays identical. `isinstance(msg, ResultMessage)` still works. The `claude` CLI subprocess, AWS Bedrock auth, MCP servers, permission modes, `cwd`, `add_dirs` — all behave exactly as the upstream SDK does.
17
+
18
+ > **Package vs import name** — PyPI distribution is `computer-agent-py` (hyphens for the wheel); the import name is `computeragent` (Python doesn't allow hyphens). So `pip install computer-agent-py` then `from computeragent import …`.
19
+
20
+ ## Why use this
21
+
22
+ Adopting `computer-agent-py` in place of `claude-agent-sdk` gives you, without rewriting your agent code:
23
+
24
+ - **OpenTelemetry traces** following the GenAI Semantic Conventions, vendor-neutral (New Relic, Datadog, ClickHouse, Honeycomb, Tempo, Jaeger — one env-var change).
25
+ - **PII redaction** at the package boundary — email, phone, SSN, credit cards, AWS keys redacted before anything reaches a sink.
26
+ - **Generic guardrails** — attribute truncation, tool allowlists, per-session cost ceilings, content filters.
27
+ - **Policy-based tool-use authorization** — gate every tool call through OPA (remote) or Cedar (in-process). Fail-closed by default.
28
+ - **AgentOS visibility** — write to the same Mongo collections (`agent_registry`, `agent_logs`, `agent_messages`, `sessions`, `slack_threads`) the AgentOS frontend already reads. Library-mode agents show up in the Agents list, Logs tab, Chat transcript, and (with the harness running) live chat sandboxes.
29
+ - **Per-message archive** — every message, tool call, and policy decision archived to `agent_messages` for replay, RAG, and forensic audit.
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ pip install computer-agent-py # core drop-in + OPA policy engine
35
+ pip install 'computer-agent-py[otel]' # + OpenTelemetry sink
36
+ pip install 'computer-agent-py[agentos]' # + AgentOS Mongo sinks
37
+ pip install 'computer-agent-py[cedar]' # + Cedar policy engine (in-process)
38
+ pip install 'computer-agent-py[all]' # everything
39
+ ```
40
+
41
+ **Prerequisite** — same as upstream: the `claude` CLI binary on `PATH` and Anthropic / Bedrock credentials in the environment.
42
+
43
+ ## Quickstart
44
+
45
+ ```python
46
+ import asyncio
47
+ from computeragent import ClaudeAgentOptions, query
48
+ from computeragent.types import ResultMessage
49
+
50
+ async def main():
51
+ options = ClaudeAgentOptions(
52
+ model="claude-sonnet-4-5",
53
+ system_prompt="You are a helpful assistant.",
54
+ allowed_tools=["Read", "Glob", "Grep"],
55
+ permission_mode="bypassPermissions",
56
+ )
57
+
58
+ async for message in query(prompt="Summarize the README.md in this directory.", options=options):
59
+ if isinstance(message, ResultMessage):
60
+ print(f"answer ({message.num_turns} turns, ${message.total_cost_usd:.4f}):")
61
+ print(message.result)
62
+
63
+ asyncio.run(main())
64
+ ```
65
+
66
+ That's it — same shape as `claude-agent-sdk`. Telemetry is configured from env vars; without anything set, nothing leaves your process.
67
+
68
+ ## Configure telemetry
69
+
70
+ ### Env-driven (zero code change)
71
+
72
+ | Variable | Effect |
73
+ |---|---|
74
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Enables OTLP/HTTP export. Unset → console exporter (debug). |
75
+ | `OTEL_EXPORTER_OTLP_HEADERS` | Comma-separated `key=value` (e.g. `api-key=NRRX-...` for New Relic). |
76
+ | `OTEL_SERVICE_NAME` | `service.name` attribute on every span. Default: `computeragent`. |
77
+ | `COMPUTERAGENT_OTEL` | `disabled` to suppress OtelSink. |
78
+ | `AGENTOS_MONGO_URL` | When set + `[agentos]` installed, attaches AgentOS sinks (registry, logs, sessions, agent_messages, slack_threads). |
79
+ | `AGENTOS_MONGO_DB` | Mongo database name. Default: `agentos`. |
80
+ | `COMPUTERAGENT_CAPTURE_CONTENT` | `1` to include prompts/responses on OTel spans. Default: off. |
81
+ | `COMPUTERAGENT_CAPTURE_CONTENT_MODE` | `events` (default) \| `attributes` \| `both`. |
82
+
83
+ ### Programmatic
84
+
85
+ ```python
86
+ from computeragent import configure, PiiRedactor, GuardrailFilter
87
+ from computeragent.telemetry.sinks import OtelSink, AgentRegistrySink, MongoMessageSink
88
+
89
+ configure(
90
+ middleware=[
91
+ PiiRedactor(strategy="hash", extra_patterns=[r"BADGE-\d{6}"]),
92
+ GuardrailFilter(
93
+ max_attribute_length=4096,
94
+ tool_name_allowlist={"Read", "Glob", "Grep", "mcp__nordassist-tools__*"},
95
+ cost_ceiling_usd=1.50,
96
+ ),
97
+ ],
98
+ sinks=[
99
+ OtelSink(), # picks up env
100
+ AgentRegistrySink(mongo_url="mongodb://..."), # registry + logs + sessions + slack_threads
101
+ MongoMessageSink(mongo_url="mongodb://..."), # per-message archive
102
+ ],
103
+ )
104
+ ```
105
+
106
+ ## Vendor-neutral OTel destinations
107
+
108
+ The package emits standard OTLP — point it at any backend by setting two env vars. No code change.
109
+
110
+ | Destination | `OTEL_EXPORTER_OTLP_ENDPOINT` | `OTEL_EXPORTER_OTLP_HEADERS` |
111
+ |---|---|---|
112
+ | **New Relic** | `https://otlp.nr-data.net` | `api-key=<NR_LICENSE_KEY>` |
113
+ | **Datadog** (via DD Agent OTLP) | `http://localhost:4318` | _(unset; agent handles auth)_ |
114
+ | **Honeycomb** | `https://api.honeycomb.io` | `x-honeycomb-team=<KEY>` |
115
+ | **Grafana Cloud Tempo** | `https://tempo-prod-...grafana.net:443` | `authorization=Basic <base64>` |
116
+ | **Self-hosted Jaeger / Tempo / SigNoz** | `http://<host>:4318` | _(unset)_ |
117
+ | **Local console (debug)** | _(unset)_ | _(unset)_ |
118
+
119
+ Full recipe table — including direct New Relic / Datadog without an OTel collector — is in [`examples/e2e/destinations.md`](examples/e2e/destinations.md).
120
+
121
+ ## Policy-based tool-use authorization
122
+
123
+ For agents that need stronger guardrails than `permission_mode`, attach an external policy engine. Activation is a single new option-field; the rest of the worker code is unchanged.
124
+
125
+ ```python
126
+ from computeragent import ClaudeAgentOptions, PolicyPrincipal, PolicyResource, query
127
+ from computeragent.policy import OpaPolicyEngine, PolicyToolAuthorizer
128
+
129
+ opa = OpaPolicyEngine(
130
+ url="http://opa.platform:8181",
131
+ policy_path="computeragent/tools/allow",
132
+ fail_mode="deny", # default — engine errors deny the call
133
+ )
134
+ authorizer = PolicyToolAuthorizer(
135
+ engine=opa,
136
+ principal_resolver=lambda ctx: PolicyPrincipal(id="alice", groups=["engineer"]),
137
+ resource_resolver=lambda ctx: PolicyResource(agent_name="nordassist", model="claude-sonnet-4-5"),
138
+ context_resolver=lambda ctx: {"env": "prod"},
139
+ )
140
+
141
+ options = ClaudeAgentOptions(
142
+ ...,
143
+ permission_mode="default", # was "bypassPermissions"
144
+ can_use_tool=authorizer,
145
+ )
146
+ ```
147
+
148
+ Swap `OpaPolicyEngine` for `CedarPolicyEngine` (install with `pip install 'computer-agent-py[cedar]'`) and the worker code is identical:
149
+
150
+ ```python
151
+ from computeragent.policy import CedarPolicyEngine
152
+
153
+ cedar = CedarPolicyEngine(
154
+ policies=open("policies/computeragent.cedar").read(),
155
+ fail_mode="deny",
156
+ )
157
+ authorizer = PolicyToolAuthorizer(engine=cedar, principal_resolver=..., ...)
158
+ ```
159
+
160
+ Sample policies are in [`examples/policies/`](examples/policies/) — one Rego file for OPA, one Cedar file. Each policy receives a canonical `PolicyInput` shape (`principal`, `action`, `resource`, `context`) so the engine choice is purely operational.
161
+
162
+ Every authorization decision emits a `policy_decision` telemetry event — `OtelSink` annotates the active `execute_tool` span with `policy.decision`, `policy.reason`, `policy.engine`, and `policy.latency_ms` so security audits and span queries co-locate.
163
+
164
+ ## AgentOS integration
165
+
166
+ When `[agentos]` is installed and `AGENTOS_MONGO_URL` is set, every agent run writes to the Mongo collections the AgentOS frontend already reads:
167
+
168
+ | Collection | Per | What's in it |
169
+ |---|---|---|
170
+ | `agent_registry` | agent name | Identity + harness + model + last-seen; idempotent upsert |
171
+ | `agent_logs` | run | Rolled-up query/reply + tokens + cost + ok/error — drives the Logs tab |
172
+ | `sessions` | session | `entries[]` of `{type, text}` chat-bubble messages — drives the Chat tab transcript |
173
+ | `slack_threads` | session | TS parity row that drives the per-agent `sessionCount` + `lastActivity` aggregates |
174
+ | `agent_messages` | message | Per-event archive (`user_message`, `assistant_message`, `tool_use`, `tool_result`, `usage_snapshot`, `policy_decision`, `system_message`) for replay, RAG, audit |
175
+
176
+ The doc shapes are byte-for-byte compatible with the TypeScript `@open-gitagent/agent-registry-mongo` package — Python-driven agents show up in the same AgentOS UI that hosted TS agents do, with no frontend change.
177
+
178
+ ### Live chat for library-mode agents
179
+
180
+ When the AgentRegistrySink writes its `agent_registry.source` row, it includes a full inline `IdentitySource` with `files: {agent.yaml, CLAUDE.md}` derived from your `ClaudeAgentOptions`. If a user clicks "New Chat" on the agent in the AgentOS SPA, the harness can clone those files into a sandbox workdir and spawn a live conversation — same UX as hosted (git-sourced) agents. The historical transcript stays available in the Chat tab regardless.
181
+
182
+ ### DocumentDB compatibility
183
+
184
+ Prod deployments on AWS DocumentDB work without changes. The sinks use only operators DocumentDB supports — `$set`, `$setOnInsert`, `$push`, `update_one(upsert=True)`, `insert_one`. No aggregation pipelines, transactions, change streams, or TTL indexes. Set `MONGO_URL` with the standard `tls=true&tlsCAFile=...` params and mount the DocumentDB CA bundle.
185
+
186
+ ## Architecture
187
+
188
+ ```
189
+ user code: from computeragent import query, ClaudeAgentOptions
190
+
191
+
192
+ computeragent._proxy.query ──┐
193
+ │ │
194
+ ▼ │ PolicyToolAuthorizer
195
+ claude_agent_sdk → claude CLI subprocess → Bedrock│ (OPA / Cedar)
196
+ │ │ via can_use_tool
197
+ ▼ │
198
+ yielded messages │
199
+ │ │
200
+ ▼ │
201
+ TelemetryPipeline (taps stream) │
202
+ │ │
203
+ ┌──── middleware ─────┐ │
204
+ │ PiiRedactor │ │
205
+ │ GuardrailFilter │ ◄────────────────────┘
206
+ │ <user-defined> │
207
+ └────────┬────────────┘
208
+
209
+ ┌──── fan-out to sinks ───────────────────────────┐
210
+ │ │
211
+ ▼ ▼ ▼ ▼
212
+ OtelSink AgentRegistrySink MongoMessageSink <user>
213
+ │ │ │
214
+ ▼ ▼ ▼
215
+ OTLP backend agent_registry agent_messages
216
+ (NR / DD / agent_logs (per-message
217
+ ClickHouse / sessions archive)
218
+ Tempo …) slack_threads
219
+ (drives AgentOS UI)
220
+ ```
221
+
222
+ The proxy is a pure tap — messages are never modified or reordered. Sinks run as background tasks so a slow exporter never stalls the agent hot path; `query()`'s `finally` block awaits them with a 5 s default timeout. Telemetry never breaks an agent run: middleware and sink exceptions are absorbed and logged.
223
+
224
+ ## Live e2e against AgentOS
225
+
226
+ [`examples/e2e/`](examples/e2e/) contains a recipe for standing up the full TypeScript stack (mongo + clickhouse + otel-collector + harness + agentos-server + SPA) via docker-compose and running this package against it. After ~60s of warm-up plus a 30s Python script run, you'll see the agent appear in the SPA's Agents list with `logCount`, `sessionCount`, `lastActivity`, and `activeSandboxes` populated; the Logs tab will show the rollup; the Chat tab will show the per-message transcript; the Observability tab will show the OTel trace tree. See [`examples/e2e/README.md`](examples/e2e/README.md).
227
+
228
+ ## Examples
229
+
230
+ | File | Demonstrates |
231
+ |---|---|
232
+ | [`examples/pdf_drop_in.py`](examples/pdf_drop_in.py) | The minimum drop-in change |
233
+ | [`examples/with_otel.py`](examples/with_otel.py) | OTel pointed at a local collector |
234
+ | [`examples/with_new_relic.py`](examples/with_new_relic.py) | OTel pointed at New Relic (just env vars) |
235
+ | [`examples/with_datadog.py`](examples/with_datadog.py) | OTel pointed at Datadog |
236
+ | [`examples/with_agentos.py`](examples/with_agentos.py) | AgentOS Mongo writes |
237
+ | [`examples/with_message_archive.py`](examples/with_message_archive.py) | Per-message archive |
238
+ | [`examples/with_pii_redaction.py`](examples/with_pii_redaction.py) | PII middleware in front of every sink |
239
+ | [`examples/with_opa_policy.py`](examples/with_opa_policy.py) | OPA-gated tool use |
240
+ | [`examples/with_cedar_policy.py`](examples/with_cedar_policy.py) | Cedar-gated tool use (in-process) |
241
+ | [`examples/multi_sink.py`](examples/multi_sink.py) | All sinks + all guardrails together |
242
+ | [`examples/e2e/run_live_demo.py`](examples/e2e/run_live_demo.py) | Full live demo against the AgentOS docker-compose stack |
243
+
244
+ ## Upstream pin
245
+
246
+ This release tracks **`claude-agent-sdk` 0.2.x**. The pinned upstream version is recorded in [`CHANGELOG.md`](CHANGELOG.md). Bump deliberately — wire-protocol field additions in upstream get re-exported automatically (identity-preserving), but any behavioral changes need a passthrough audit.
247
+
248
+ ## Development
249
+
250
+ ```bash
251
+ git clone https://github.com/open-gitagent/computer-agent-py
252
+ cd computer-agent-py
253
+ uv sync --all-extras --dev
254
+ uv run ruff check src tests
255
+ uv run ruff format --check src tests
256
+ uv run mypy src
257
+ uv run pytest -q # 120+ unit tests
258
+ uv run pytest -q -m integration # requires ANTHROPIC_API_KEY + claude CLI
259
+ uv build
260
+ ```
261
+
262
+ ## License
263
+
264
+ MIT — see [`LICENSE`](LICENSE).