Metadata-Version: 2.4
Name: pipbit
Version: 0.3.0
Summary: Python SDK for connecting text-based agents to the Pipbit platform.
Author-email: Pipbit <pipbit@pipworks.ai>
License-Expression: MIT
Project-URL: Homepage, https://developer.pipbit.ai
Project-URL: Documentation, https://developer.pipbit.ai/python-sdk.html
Keywords: pipbit,ai,agent,sdk,flask
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
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: Framework :: Flask
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Flask<4.0,>=3.0
Requires-Dist: requests<3.0,>=2.31
Provides-Extra: dev
Requires-Dist: build<2.0,>=1.2; extra == "dev"
Requires-Dist: twine<7.0,>=6.2; extra == "dev"
Dynamic: license-file

# Pipbit Python SDK

`pipbit` is the Python SDK for building text-based developer agents that Pip can hand conversations to.

Pipbit keeps the voice stack on the platform side:
- microphone and speaker handling
- speech-to-text and text-to-speech
- device transport
- request signing
- handoff session management

Your agent stays text-first and only needs to implement a webhook handler.

## Installation

```bash
pip install pipbit
```

For local package work:

```bash
pip install -e '.[dev]'
```

## Hello world

```python
from pipbit import Agent, CONNECT_INTRO_UTTERANCE

agent = Agent(
    name="george",
    secret="pb_live_sk_XXXXXXXXXXXXXXXX",
    base_url="https://api.pipbit.ai",
)

@agent.handle
def handle(req):
    if req.is_connect_intro():
        return "George here. How can I help with your home DIY today?"
    return f"You said: {req.text}"

agent.run(host="0.0.0.0", port=3000)
```

Pipbit sends signed JSON requests to:

```text
POST /pipbit/agent
```

`CONNECT_INTRO_UTTERANCE` is exported for agent authors who want the raw token,
but `req.is_connect_intro()` is the preferred helper.

## Request model

Each inbound request is exposed as a `Request` object:

```python
req.id
req.reply_token
req.session_id
req.text
req.conversation
req.subject_id
req.agent_session_id
req.device_shadow
req.is_connect_intro()
```

- `subject_id` is the stable Pipbit subject id for the current user/device binding.
- `session_id` is the request/reply conversation id.
- `agent_session_id` is the higher-level Pip-managed handoff session.

## Reply modes

Immediate reply:

```python
@agent.handle
def handle(req):
    return "Hi. How can I help?"
```

Deferred reply:

```python
@agent.handle
def handle(req):
    queue_work(req)
    return req.defer()
```

Later:

```python
agent.push_reply(
    reply_token=req.reply_token,
    text="Your report is ready.",
)
```

Proactive message:

```python
agent.push_message(
    subject_id=req.subject_id,
    text="You have a new update.",
)
```

## Health checks

The SDK exposes:

- `GET /health`
- `GET /pipbit/health`

The response is structured and readiness-aware. The SDK includes:

- a required `agent_secret` check
- a non-required `platform_health` check against `GET {base_url}/health`

Add your own checks for agent-specific dependencies:

```python
import os

from pipbit import Agent

agent = Agent(name="george", secret="pb_live_sk_...", base_url="https://api.pipbit.ai")

agent.add_health_check(
    "openai_api_key",
    lambda: (bool(os.getenv("OPENAI_API_KEY")), "Set OPENAI_API_KEY."),
    required=True,
)
```

Example health response:

```json
{
  "status": "ok",
  "ready": true,
  "agent_name": "george",
  "api_version": "v1",
  "base_url": "https://api.pipbit.ai",
  "checks": [
    {"name": "agent_secret", "ok": true, "required": true, "message": "ok"},
    {"name": "platform_health", "ok": true, "required": false, "message": "ok"}
  ]
}
```

If any required check fails, `/health` returns `503`.

## Metrics

The SDK exposes:

- `GET /metrics`
- `GET /pipbit/metrics`

Current counters include:

- `webhook_requests_total`
- `webhook_success_total`
- `webhook_immediate_replies_total`
- `webhook_deferred_replies_total`
- `webhook_auth_failures_total`
- `webhook_invalid_requests_total`
- `webhook_configuration_errors_total`
- `webhook_handler_errors_total`
- `push_reply_calls_total`
- `push_message_calls_total`
- `platform_health_checks_total`
- `platform_health_check_errors_total`

## Local development

Run your Flask app locally:

```bash
python app.py
```

For local testing, expose your server so Pipbit can reach `POST /pipbit/agent`.

The spoken voice is configured on the Pipbit platform record for your agent; it
is not chosen inside the Python SDK. The preferred platform contract is:

- `voice_request`: developer-supplied abstract preference like presentation, tone, role
- `voice_binding`: platform-selected locked concrete voice
- `voice_id`: bridge-compatible compatibility field derived from the binding

Legacy explicit `voice_id` registration still works, but new agents should
prefer `voice_request`.

## Contract test

This repo includes an SDK contract test that exercises the basic developer flow:

- register agent
- bind device/subject
- connect the agent
- send the handoff intro turn
- send one normal user turn
- end the agent session

Run it from the repo root:

```bash
PYTHONPATH=SDK/pipbit_sdk:HOST/pipbit_platform_service \
python3 -m unittest SDK.pipbit_sdk.tests.test_contract -v
```

## Packaging for PyPI

Build the sdist and wheel:

```bash
cd SDK/pipbit_sdk
python3 -m build
twine check dist/*
```

The repo also includes a `RELEASE.md` checklist for version bumps and publish steps.

## Error handling

The SDK exposes:

- `AuthenticationError`
- `InvalidRequestError`
- `ConfigurationError`

Inbound webhook failures return JSON error bodies with sensible HTTP status codes.
