Metadata-Version: 2.4
Name: ollybot
Version: 0.1.0
Summary: Ollybot monitoring SDK for AI agent operations.
License-Expression: LicenseRef-Proprietary
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.10
Requires-Dist: opentelemetry-sdk>=1.39.0
Requires-Dist: traceloop-sdk>=0.46.0
Provides-Extra: claude-agent
Requires-Dist: claude-agent-sdk==0.1.65; extra == 'claude-agent'
Provides-Extra: deep-agents
Requires-Dist: langchain-core==1.3.2; extra == 'deep-agents'
Provides-Extra: google-adk
Requires-Dist: google-adk==1.32.0; extra == 'google-adk'
Provides-Extra: langchain-langgraph
Requires-Dist: langchain-core==1.3.2; extra == 'langchain-langgraph'
Requires-Dist: langchain==1.2.17; extra == 'langchain-langgraph'
Requires-Dist: langgraph==1.1.10; extra == 'langchain-langgraph'
Provides-Extra: openai-agents
Requires-Dist: openai-agents==0.15.0; extra == 'openai-agents'
Provides-Extra: pydanticai
Requires-Dist: openai==2.32.0; extra == 'pydanticai'
Requires-Dist: pydantic-ai-slim[openai]==1.84.1; extra == 'pydanticai'
Description-Content-Type: text/markdown

# Ollybot Python SDK

Ollybot is the monitoring SDK for AI agent operations. It captures agent sessions, tool activity, user traits, traces, and bugs through a best-effort delivery path that should never break the host application.

Install from PyPI as `ollybot` and import it as `olly`:

```python
import ollybot as olly

client = olly.init(
    api_key="olly_...",
    project_id=42,
    capture_exceptions=True,
)
```

`init()` also supports environment/config bootstrap for deploy-time setup:

```bash
export OLLY_API_KEY="olly_..."
export OLLY_PROJECT_ID="42"
export OLLY_ENVIRONMENT="production"
export OLLY_RELEASE="2026.05.07"
# Optional: override the auto-discovered service name.
export OLLY_SERVICE_NAME="support-agent"
```

If `service_name` is omitted, Olly discovers one from `pyproject.toml` or the
current directory name. `OLLY_REPO` is optional source-repository metadata
(for example `github.com/acme/support-agent`); when no service name is set, it
can also serve as a fallback name and is attached as bug context. `OLLY_TIMEOUT`,
`OLLY_INGEST_URL`, and `OLLY_CONFIG` are also read when present. Explicit
`init(...)` arguments always win.

## Manual Interaction

```python
import ollybot as olly

client = olly.init(api_key="olly_...", project_id=42)

with client.begin("refund workflow", user_id="user_123", user_traits={"plan": "pro"}) as interaction:
    interaction.record_tool(
        name="lookup_order",
        input={"order_id": "A-17"},
        output={"status": "shipped"},
    )
    interaction.finish(output="Order A-17 ships Friday.")
```

`flush()` is available for tests, CLIs, and graceful shutdown, but normal application control flow should not depend on telemetry delivery succeeding.

## Harness Integrations

The supported quick paths stay small and follow the harness seam that the upstream SDK already exposes.

```python
import agents
import ollybot as olly

client = olly.init(api_key="olly_...", project_id=42)
client.openai_agents.setup(agents)

# Run OpenAI Agents normally. Olly receives trace-processor lifecycle callbacks.
```

```python
from pydantic_ai import Agent
import ollybot as olly

client = olly.init(api_key="olly_...", project_id=42)
agent = client.pydantic_ai.wrap(Agent("openai:gpt-5.4-mini"))

result = agent.run_sync("Help this customer")
```

```python
from google.adk.runners import Runner
import ollybot as olly

client = olly.init(api_key="olly_...", project_id=42)
client.google_adk.setup()

# Or patch one runner:
runner = Runner(app_name="refund-app", agent=agent, session_service=session_service)
runner = client.google_adk.wrap(runner)
```

```python
from langchain_core.runnables import RunnableLambda
import ollybot as olly

client = olly.init(api_key="olly_...", project_id=42)
runnable = client.langchain.wrap(RunnableLambda(lambda value: {"answer": value}))

result = runnable.invoke("Help this customer")
```

For Deep Agents and lower-level callback wiring, pass Olly's callback handler through the normal LangChain config path:

```python
handler = client.deep_agents.handler()
agent.invoke({"messages": [...]}, config={"callbacks": [handler]})
```

Claude Agent SDK support is also available through `client.claude_agent.wrap(...)`
for the current Python `query(...)` seam.

## Bug Capture

```python
import ollybot as olly

client = olly.init(
    api_key="olly_...",
    project_id=42,
    capture_exceptions=True,
)

try:
    run_agent()
except Exception as exc:
    olly.capture_exception(exc)
    raise
```

Bug capture is independent from ordinary harness telemetry. It should not swallow, wrap, replace, or mask the application exception.

`before_send=` is available for last-mile redaction or dropping telemetry before it leaves the process. The hook is best-effort: if it raises, Olly drops that telemetry write and keeps the host app running.

For ASGI/FastAPI services, `ollybot.integrations.fastapi.setup_fastapi(app, client=client)` adds safe request context to bug reports without capturing request bodies.

## Delivery And Tracing Posture

Delivery is intentionally best-effort. The SDK buffers writes locally, batches opportunistically, gzips larger writes, drops telemetry under pressure, and records diagnostics instead of raising through customer code.

Tracing is Traceloop/OpenTelemetry-backed. Olly configures the substrate, reads the active OTel context, and attaches Olly attributes; it does not hand-roll trace IDs, span IDs, exporters, or span lifecycle machinery.

## Package Status

This is an alpha release. Public APIs may change before general availability.

## License

This package is proprietary and is not licensed as open source.
