Metadata-Version: 2.4
Name: watchllm
Version: 0.4.0
Summary: WatchLLM Python SDK for tracing and replaying AI agent flights
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: langchain-core>=0.2; extra == 'langchain'
Provides-Extra: all
Requires-Dist: crewai>=0.1; extra == 'all'
Requires-Dist: langchain-core>=0.2; extra == 'all'
Provides-Extra: crewai
Requires-Dist: crewai>=0.1; extra == 'crewai'
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.2; extra == 'langchain'
Description-Content-Type: text/markdown

# WatchLLM Python SDK

WatchLLM gives you flight-recorder visibility into AI agent runs.
With one decorator or callback, you can stream thought steps, tool calls, and outcomes to your WatchLLM dashboard.

## Installation

```bash
pip install watchllm
```

Optional integrations:

```bash
pip install "watchllm[langchain]"
pip install "watchllm[crewai]"
pip install "watchllm[all]"
```

## 30-second quick start

```python
from watchllm import watch

@watch(project_key="sk_proj_xxx", agent_name="research_agent")
def run():
    print("Planning search strategy")
    print("Calling web_search tool")
    print("Summarizing findings")
    return "done"

if __name__ == "__main__":
    run()
```

What this does:
- Starts a flight (`event_type=start`) when `run()` begins.
- Captures `print()` calls as `thought` steps.
- Ends the flight (`event_type=end`) on return/exception.
- Prints the replay URL after completion.

## Environment variable alternative

Instead of passing `project_key` directly, set:

```bash
export WATCHLLM_API_KEY=sk_proj_xxx
# Windows PowerShell:
# $env:WATCHLLM_API_KEY="sk_proj_xxx"
```

Then:

```python
from watchllm import watch

@watch(agent_name="env_key_agent")
def run():
    print("Using WATCHLLM_API_KEY")
```

You can also set API host with:

```bash
export WATCHLLM_BASE_URL=http://localhost:3000
```

## LangChain integration

```python
from watchllm import FlightSession, WatchLLMClient
from watchllm.integrations.langchain import WatchLLMLangChainCallback

client = WatchLLMClient(base_url="http://localhost:3000")
session = FlightSession(
    client=client,
    project_key="sk_proj_xxx",
    agent_name="langchain_agent",
)
session.start()

callback = WatchLLMLangChainCallback(session)

# Pass callback into your LangChain runnable / agent
# agent.invoke({"input": "..."}, config={"callbacks": [callback]})

session.end(success=True)
client.close()
```

Implemented callback hooks:
- `on_llm_start`
- `on_llm_end`
- `on_tool_start`
- `on_tool_end`
- `on_chain_start`
- `on_chain_end`
- `on_agent_action`
- `on_agent_finish`

`on_tool_end` tracks pending tool output and marks `was_result_used` based on whether that output appears in the next `on_llm_start` input.

## CrewAI integration

```python
from watchllm import FlightSession, WatchLLMClient
from watchllm.integrations.crewai import WatchLLMCrewAICallback

client = WatchLLMClient(base_url="http://localhost:3000")
session = FlightSession(
    client=client,
    project_key="sk_proj_xxx",
    agent_name="crewai_agent",
)
session.start()

callback = WatchLLMCrewAICallback(session)

# Attach callback to your CrewAI flow depending on your runtime setup.
# The callback emits thought/tool/memory/output steps to WatchLLM.

session.end(success=True)
client.close()
```

## Session manager behavior

`FlightSession` includes a background daemon poller:
- Polls `GET /api/flight/{id}/status` every 500ms.
- When status is `paused`, main event emission waits.
- If correction payload is present, it stores it for next callback context and attempts to set status back to `live`.

## Error handling

The SDK client uses `httpx` with resilient retry behavior:
- Retries `5xx` with exponential backoff (`3` retries).
- On `429`, waits using `Retry-After` before retrying.
- On `401`, raises:

```python
WatchLLMAuthError("Invalid SDK key. Check your project settings.")
```
