Metadata-Version: 2.4
Name: agentblit
Version: 0.1.0
Summary: Agentic SDK for LLM agents with AgentBlit tools
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: openai>=1.40.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0

# AgentBlit Python SDK

Build LLM agents that combine AgentBlit remote tools with optional local Python tools. The SDK supports streaming output, approval-gated tools, and short-term memory with automatic summarization.

It now also includes automatic event tracking (`agent_init`, `user_prompt`, `llm_call`, `tool_call`, and `tools_updated`) sent as asynchronous batches so agent output is not blocked by analytics delivery.

## Upcoming Changes (Next Release)

The upcoming release includes these user-facing updates:

- Agent initialization now supports a complete runtime contract in one place:
  - `approval_callback` for non-interactive approval flows
  - `custom_tools` for registering local tools at construction time
  - `max_tool_rounds` to cap recursive tool-call loops safely
- `model` parsing now requires `vendor/model` format.
- System instructions now always include a default tool-usage hint unless already present:
  - `Use tools when they help answer accurately.`
- Timeout behavior is consistent across LLM calls and AgentBlit tool HTTP calls via a single `timeout` config.
- Auto event tracking sends asynchronous `POST /api/events/batch` calls after each run loop.

## Requirements

- Python 3.10+
- A supported LLM provider key (OpenAI, Anthropic, Gemini, or OpenRouter)
- An AgentBlit server exposing:
  - `GET /api/tools/list` with `X-API-Key`
  - `POST /api/tools/call` with body `{ "tool_calls": [...] }`
  - `POST /api/events/batch` with body `{ "events": [...] }`

## Install

```bash
cd agentblit-python
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt
```

## Run Tests

```bash
.venv/bin/python -m pytest -q
```

## Agent Initialization

```python
import asyncio
from agentblit import Agent

async def main() -> None:
    agent = Agent(
        model="openai/gpt-4o-mini",
        api_key="YOUR_LLM_KEY",
        agentblit_api_key="YOUR_AGENTBLIT_KEY",
        system_prompt="You are a helpful assistant.",
        max_history=5,
        debug=False,
        timeout=30.0,
        approval_callback=None,
        custom_tools=[],
        max_tool_rounds=25,
    )

    print("agent_id:", agent.agent_id)
    print("session_id:", agent.session_id)

    async for chunk in agent.run("What is 200 + 30? Use tools if needed."):
        print(chunk, end="")
    print()

asyncio.run(main())
```

### Parameters

- `model`: LLM id in `vendor/model` format, for example:
  - `openai/gpt-4o-mini`
  - `anthropic/claude-sonnet-4-0`
  - `gemini/gemini-2.0-flash`
  - `openrouter/openai/gpt-4o-mini`
- `api_key`: API key for the LLM provider.
- `agentblit_url`: Optional AgentBlit base URL (default `https://console.agentblit.com`).
- `agentblit_api_key`: API key for AgentBlit (`X-API-Key` header). Required.
- `system_prompt`: Optional custom system instruction.
- `max_history`: Recent turns to keep verbatim before summarization (default `5`).
- `debug`: Enable verbose logs for LLM and tool activity (default `False`).
- `timeout`: Timeout in seconds for both LLM and tool HTTP calls (default `30.0`).
- `approval_callback`: Optional async callback `async (tool_name, args_dict) -> bool`.
- `custom_tools`: Optional list of local `@tool` functions.
- `max_tool_rounds`: Maximum tool/LLM round-trips per `run()` call (default `25`).
- `agent_id`: Auto-generated UUID created once per `Agent` instance.
- `session_id`: Auto-generated UUID used across events for that `Agent` instance.

## Features

- Vendor-based model routing from `model`.
- Agentblit remote tool discovery and execution.
- Local custom tools via `@tool` + `custom_tools` or `register_tool`.
- Approval flow for `needs_approval` tools.
- Streaming assistant output with `async for`.
- Memory summarization when history exceeds `max_history`.
- Debug logging for requests, tool calls, and tool results.
- Automatic batched event tracking at end of each loop.

## Tool Decorator

```python
from agentblit import tool

@tool(description="Add two integers.")
def add(a: int, b: int) -> int:
    return a + b

@tool(name="risky_email_send", permission_mode="needs_approval")
def send_email(to: str, body: str) -> str:
    ...
```

Schemas are inferred from Python type hints.

## Quick Usage Pattern

1. Create `Agent(...)`.
2. Optionally register custom tools.
3. Call `agent.run(user_message)` and stream chunks.
4. Reuse the same agent instance to preserve short-term memory.

## Event Tracking

The SDK automatically tracks and batches these events:

- `agent_init` (sent once per `Agent` instance, includes `system_prompt` + current tools)
- `user_prompt`
- `llm_call` (includes compact request + response JSON, `tokens`, `latency_ms`)
- `tool_call` (includes request + response JSON, `latency_ms`)
- `tools_updated` (sent when tool list changes in a later `run()` call)

For `llm_call` events, request payloads are intentionally compact:

- `system_prompt` is not repeated in each call
- `tools` are not repeated in each call
- Only the latest message is included
- If chat history was summarized, payload includes the summary message + latest message

The batch is posted to:

- `POST {AGENTBLIT_URL}/api/events/batch`
- Headers include `X-API-Key: AGENTBLIT_API_KEY`

If event delivery fails, agent execution still completes and the SDK logs a debug message when `debug=True`.

### Custom Events

You can queue custom events that are flushed with the next `run()` batch:

```python
agent.track("purchase_started", {"plan": "pro", "source": "checkout"})
```

## Examples

- `[examples/basic_agent.py](examples/basic_agent.py)`: Remote tools with environment config.
- `[examples/custom_tools.py](examples/custom_tools.py)`: Local tools + remote tools.

## AgentBlit API Reference

- List tools: `GET /api/tools/list` with `X-API-Key`.
- Call tools: `POST /api/tools/call` with:

```json
{
  "tool_calls": [
    {
      "id": "call_1",
      "type": "function",
      "function": {
        "name": "fastmcp_add",
        "arguments": "{\"a\":200,\"b\":30}"
      }
    }
  ]
}
```

- Batch events: `POST /api/events/batch` with:

```json
{
  "events": [
    {
      "id": "evt_001",
      "session_id": "sess_123",
      "agent_id": "abc1",
      "timestamp": "2026-04-21T10:30:00.123Z",
      "type": "llm_call",
      "data": {
        "request": {
          "model": "gpt-5"
        },
        "response": {
          "content": "Hello"
        }
      },
      "tokens": 245,
      "latency_ms": 240
    }
  ]
}
```

## Troubleshooting

If you see `RemoteProtocolError: Server disconnected without sending a response`, verify protocol alignment:

- Use `https://...` if the server expects TLS.
- Use `http://...` only for plain HTTP servers.

If you see `UnicodeEncodeError` when calling AgentBlit (tools list, tools call, or events), your `AGENTBLIT_API_KEY` likely contains non-ASCII characters (often curly “smart quotes” from copy/paste). HTTP headers require ASCII—fix the key in your environment (plain quotes and ASCII-only characters).

If event ingestion returns `400` with “Invalid option” for `events[].type`, your AgentBlit backend must accept the event types this SDK sends (`agent_init`, `user_prompt`, `llm_call`, `tool_call`, `tools_updated`, `agent_loop_error`, and custom types from `track()`). Upgrade or configure the console/API accordingly; the SDK does not downgrade or split batches.

## Extensibility

- Providers: switch provider/model by changing `model`.
- Multimodal-ready shape: message flow is compatible with future image/audio additions.
- Minimal API surface: `Agent`, `tool`, and `register_tool`.

## License

Use and modify as needed for your project.
