Metadata-Version: 2.4
Name: akhu-observer
Version: 1.2.0
Summary: AKHU Observer SDK — Evidence infrastructure adapter for AI systems
License: AKHU Observer SDK License Notice
        
        Copyright (c) 2025-2026 AKHU Technologies — Nehuén Eluney Mercado.
        All Rights Reserved.
        
        This package is source-available commercial software, not open source or free
        software. Possession, installation or access does not grant production-use,
        redistribution, sublicensing, derivative-work or competitive-use rights.
        Authorized use is governed by the applicable written agreement with AKHU
        Technologies. If no such agreement applies, no production-use right is granted.
        
        Contact AKHU Technologies for the complete applicable license terms.
License-File: LICENSE
Keywords: ai,audit,compliance,eu-ai-act,evidence,observability
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
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
Classifier: Typing :: Typed
Requires-Python: >=3.10
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.20.0; extra == 'anthropic'
Provides-Extra: dev
Requires-Dist: hypothesis>=6.0; extra == 'dev'
Requires-Dist: pytest-timeout>=2.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == 'openai'
Description-Content-Type: text/markdown

# akhu-observer (Python)

**AKHU Observer SDK** — evidence instrumentation for AI systems.

Zero-runtime-dependency Python SDK for connecting applications to the AKHU evidence ledger.

## Install

```bash
pip install akhu-observer
```

With provider support:

```bash
pip install "akhu-observer[openai]"      # OpenAI wrapper
pip install "akhu-observer[anthropic]"   # Anthropic wrapper
```

## Quick Start

### Direct Client

```python
from akhu_observer import AkhuClient

client = AkhuClient(
    url="http://akhu-api:3000",
    channel_id="commissioned-system-slot",
)
client.observe("DOCUMENT_PROCESSED", {"doc_id": "abc-123", "pages": 12})
```

### OpenAI Wrapper

```python
from openai import OpenAI
from akhu_observer import observe_openai

client = observe_openai(
    OpenAI(),
    akhu_url="http://akhu-api:3000",
    channel_id="commissioned-openai-slot",
)
response = client.chat.completions.create(model="gpt-4o", messages=[...])
# Observation sent automatically — response unmodified
```

### Anthropic Wrapper

```python
from anthropic import Anthropic
from akhu_observer import observe_anthropic

client = observe_anthropic(
    Anthropic(),
    akhu_url="http://akhu-api:3000",
    channel_id="commissioned-anthropic-slot",
)
response = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=1024, messages=[...])
```

Sync and async provider clients are supported. OpenAI instrumentation covers Chat Completions and Responses. Streams remain caller-driven and are not pre-consumed.

Provider wrappers record `MODEL_TOOL_REQUEST_OBSERVED` when a model requests a tool. That is not proof of execution. Instrument the actual boundary when execution matters:

```python
from akhu_observer import observe_executor, observe_mcp_client, observe_mcp_handler

observed_handler = observe_executor(handler, akhu=client, handler_name="review_case")
session = observe_mcp_client(session, akhu=client)
server_handler = observe_mcp_handler(server_handler, akhu=client, tool_name="review_case")
```

MCP support is structural and does not add an MCP SDK dependency. It observes only calls made through the configured client or handler.

Provider and MCP wrappers are delegating views over the original objects; they do not patch the supplied client. Sync and async return behavior, context-manager use and caller-driven stream consumption remain under application control.

Provider wrappers own an internal delivery client. Call `close_provider_observer(client)` during application shutdown to drain it without closing the provider client.

### Environment Variables

```bash
export AKHU_URL="http://akhu-api:3000"
export AKHU_CHANNEL_ID="my-channel"
```

```python
# No config needed — reads from environment
client = AkhuClient()
```


## Commissioning contract

`channel_id` is not a free-form registration request. It must identify a channel slot in the signed Evidence Scope installed on the target AKHU instance. The SDK never creates, deletes, or changes channels. The API rejects observations whose slot, transport, or event type is outside that scope.

Each observation receives a stable delivery identifier before its first send. Retries reuse that identifier so an ambiguous network outcome cannot create a second fact. `on_flush` runs only after AKHU confirms a durable receipt; callback failures never trigger redelivery. `on_error` and `on_flush` are isolated from the observed application.
## Architecture

### Operational outcomes and framing

Batches are framed by observation count and exact encoded body bytes. Local ceilings
are 5,000 observations and 1,048,576 bytes, reduced by smaller effective installation
declarations read from `/api/v1/system/operational-envelope`. That best-effort read is
cached for 60 seconds. Older or unavailable introspection retains local ceilings;
the HTTP outcome and confirmed durable receipt remain authoritative.

Retries reuse the same serialized material and stable delivery identifiers. A known
refusal before admission can reduce framing and resend only the refused portion.
Previously confirmed chunks are not resent. A non-retryable evaluation deferral is
not retried merely because its HTTP status is 503.

`AkhuProtocolError` exposes `status_code`, `code`, validated `operational` facts,
`request_id`, `retry_after_s` and `retryable`; arbitrary response fields are discarded.
`AkhuClientBoundaryError` exposes `observed_bytes` and `max_request_bytes` for local
framing refusal without an invented HTTP response or L0 receipt. Both inherit
`ValueError`. Asynchronous delivery reports failures through `on_error`; the explicit
blocking `observe_sync` operation can raise. `on_flush` concerns only confirmed
durable receipts. Earlier chunks may be confirmed before a later failure.

Privacy preprocessing has separate local bounds: 10,000 Unicode characters per
string, 1,000 items per collection and bounded nesting. Truncation markers describe
omitted material. These transformations do not increase runtime admission capacity.
See the [runtime contract](../../docs/operational-envelope.md) for scopes and persistence.

- **Zero required runtime dependencies** — core delivery uses only Python stdlib (`http.client`, `threading`, `json`)
- **Fail-open** — observation failures never affect the observed system
- **Privacy by default** — content redacted unless explicitly opted in
- **Credential redaction** — forbidden credential values are replaced even with `capture_content=True`
- **Thread-safe** — one background worker drains observations without creating a thread per event

The exported client surface is defined in
[`src/akhu_observer/client.py`](./src/akhu_observer/client.py); provider wrappers
are isolated under [`src/akhu_observer/wrappers`](./src/akhu_observer/wrappers/).

## Development

```bash
cd packages/observer-python
pip install -e ".[dev]"
pytest
pytest tests/invariants/       # Property-based tests
pytest tests/adversarial/      # Injection/attack resistance
```
