Metadata-Version: 2.4
Name: criticalbridge
Version: 1.0.0
Summary: Python SDK for building governed external agents on CriticalBridge — boots the conformance sidecar, dispatches A2A tasks to your handlers, auto-emits decision lineage.
Project-URL: Homepage, https://criticalbridge.ai
Project-URL: Repository, https://github.com/fburkitt/CriticalBridgeApp
Project-URL: Issues, https://github.com/fburkitt/CriticalBridgeApp/issues
Author: CriticalBridge.AI
License: Apache-2.0
License-File: LICENSE
Keywords: a2a,agent-sdk,criticalbridge,governance,managed-agents,naic
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: cb-conformance<2,>=1.0.0
Requires-Dist: requests>=2.31
Provides-Extra: adk
Requires-Dist: google-adk>=1.0; extra == 'adk'
Provides-Extra: all
Requires-Dist: autogen-agentchat>=0.4; extra == 'all'
Requires-Dist: crewai>=0.80; extra == 'all'
Requires-Dist: google-adk>=1.0; extra == 'all'
Requires-Dist: haystack-ai>=2.5; extra == 'all'
Requires-Dist: langchain-core>=0.3; extra == 'all'
Requires-Dist: marvin>=3.0; extra == 'all'
Requires-Dist: semantic-kernel>=1.0; extra == 'all'
Provides-Extra: autogen
Requires-Dist: autogen-agentchat>=0.4; extra == 'autogen'
Provides-Extra: crewai
Requires-Dist: crewai>=0.80; extra == 'crewai'
Provides-Extra: dev
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Requires-Dist: types-requests>=2.31; extra == 'dev'
Provides-Extra: haystack
Requires-Dist: haystack-ai>=2.5; extra == 'haystack'
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.3; extra == 'langchain'
Provides-Extra: marvin
Requires-Dist: marvin>=3.0; extra == 'marvin'
Provides-Extra: semantic-kernel
Requires-Dist: semantic-kernel>=1.0; extra == 'semantic-kernel'
Description-Content-Type: text/markdown

# criticalbridge

> Python SDK for building governed external agents on **CriticalBridge**. Boots the conformance sidecar in-process via subprocess, dispatches A2A `/tasks` to your handlers, and auto-emits decision lineage to the Brain. The Python side of the integration described in the [External Agent Integration Guide](https://github.com/fburkitt/CriticalBridgeApp/blob/main/docs/EXTERNAL_AGENT_INTEGRATION_GUIDE.md).

## Install

```bash
pip install criticalbridge
```

**v0.1 requires Node.js (>=20)** on `PATH` — the SDK spawns the TypeScript sidecar (`@criticalbridge/conformance-sidecar`) as a subprocess via `npx`. v0.2 will ship a standalone binary that removes this dependency.

## Hello-world agent

```python
import os
from criticalbridge import ManagedAgent

agent = ManagedAgent(
    brain_base_url="https://api.criticalbridge.ai",
    enrollment_token=os.environ["CB_ENROLLMENT_TOKEN"],
    entity_id="acme-corp",
    agent_id="customer-support-langchain-v2",
    vendor="langchain",
    public_url="https://sidecar.acme.example.com",   # HTTPS, what the Brain dispatches to
)

agent.start()  # boots the sidecar; blocks until /healthz green

@agent.handler("customer.read")
def lookup_customer(request, context):
    # business logic — call your model, your CRM, whatever
    customer = {"id": request["customer_id"], "name": "Sample"}
    return agent.respond(
        action="return_customer_info",
        payload=customer,
        model_invocation={"model": "gpt-4o", "promptTokens": 412, "completionTokens": 87},
        risk_tier="low",
    )

agent.serve()  # blocks until SIGINT
```

## What the SDK gives you

- **Sidecar lifecycle** — spawn, wait-for-ready, graceful teardown on SIGINT / `atexit`
- **`/tasks` dispatcher** — local HTTP server, routes A2A envelopes to the right `@handler`
- **`respond()`** — builds the A2A response AND queues a decision-lineage emit (NAIC V2 wire shape via [`cb-conformance`](https://pypi.org/project/cb-conformance/))
- **Live session** — `agent.session` reads the registration JWT fresh from the sidecar each time (so E2 token refreshes are picked up without a restart)

## Configuration

`ManagedAgent(...)` accepts these kwargs (validated at construction time; bad config raises `BadConfigError` before any I/O):

| Field | Required | Notes |
|---|---|---|
| `brain_base_url` | yes | e.g. `https://api.criticalbridge.ai` |
| `entity_id` | yes | Your CriticalBridge entity |
| `enrollment_token` | yes | One-time token from Portal `/dashboard/managed-agents/enrollment-tokens` |
| `agent_id` | yes | Durable per-agent ID within the entity |
| `vendor` | no | One of `langchain` / `autogen` / `crewai` / `semantic-kernel` / `haystack` / `other`. Default `other`. |
| `public_url` | no | HTTPS URL the Brain dispatches to the sidecar. Required for production deploys. |
| `sidecar_port` | no | Sidecar's listen port (default 8080) |
| `local_port` | no | Local /tasks server port (default ephemeral) |
| `display_name` | no | Label in the Portal fleet view |
| `capability_tags` | no | List of capability strings |

## Logging

```python
import logging
logging.getLogger("criticalbridge").setLevel(logging.DEBUG)         # everything
logging.getLogger("criticalbridge.sidecar").setLevel(logging.WARNING)  # quiet sidecar passthrough
```

Set `CB_LOG_LEVEL=DEBUG` in the environment as a shortcut.

## License

Apache-2.0 © Frank Burkitt and CriticalBridge.AI contributors.
