Python SDK for connecting text-based agents to the Pipbit platform.
Project description
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
pip install pipbit
For local package work:
pip install -e '.[dev]'
Hello world
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:
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:
req.id
req.reply_token
req.session_id
req.text
req.conversation
req.subject_id
req.agent_session_id
req.device_id
req.device_shadow
req.handoff_context
req.environment_event
req.is_connect_intro()
req.is_environment_event()
subject_idis the stable Pipbit subject id for the current user/device binding.session_idis the request/reply conversation id.agent_session_idis the higher-level Pip-managed handoff session.
Reply modes
Immediate reply:
@agent.handle
def handle(req):
return "Hi. How can I help?"
Deferred reply:
@agent.handle
def handle(req):
queue_work(req)
return req.defer()
Later:
agent.push_reply(
reply_token=req.reply_token,
text="Your report is ready.",
)
Proactive message:
agent.push_message(
subject_id=req.subject_id,
text="You have a new update.",
)
Environment events
Agents can subscribe to real-time environment events (audio scene, sensor
data, etc.) by including event_subscriptions during registration:
{"event_subscriptions": ["audio_scene"]}
Events arrive as normal webhook calls with a sentinel utterance:
@agent.handle
def handle(req):
if req.is_environment_event():
event = req.environment_event # {"type": "audio_scene", "data": {...}, "timestamp": ...}
if req.agent_session_id:
return "I heard something." # active session — reply directly
else:
agent.push_message( # background — signal Pip
text="Alert from my agent.",
device_id=req.device_id,
)
return ""
# ... normal handler
Additional request fields for environment events:
req.environment_event— structured event dict (type,data,timestamp)req.device_id— the device identifier (always present for events)req.is_environment_event()— returnsTruefor event requests
ENVIRONMENT_EVENT_UTTERANCE is exported for agents that want the raw
sentinel token.
OAuth account-linking
Connect a user's third-party account (Sonos, Spotify, Google, ...) to your
agent. Your agent owns the tokens — the platform never sees them. Because a
Pipbit device is voice-only, the user can't consent on the device; instead the
agent hands off to a second screen (the same way Alexa/Google "account linking"
works): you generate a link, deliver it to the user out of band, they consent in
a browser, and the SDK's built-in callback stores the token under their
subject_id.
from pipbit import Agent, OAuth2Config, FileTokenStore
agent = Agent(
name="sonos",
secret="pb_live_sk_...",
oauth=OAuth2Config(
authorize_url="https://api.sonos.com/login/v3/oauth",
token_url="https://api.sonos.com/login/v3/oauth/access",
client_id="...",
client_secret="...",
redirect_uri="https://my-agent.example.com/pipbit/oauth/callback",
scope="playback-control-all",
token_endpoint_auth="basic", # or "post"
),
token_store=FileTokenStore("tokens.json"), # MemoryTokenStore() for dev
)
@agent.handle
def handle(req):
token = agent.get_oauth_token(req.subject_id) # auto-refreshes; None if unlinked
if token is None:
link = agent.account_link_url(req.subject_id)
deliver_to_user(link) # your channel: SMS / email / companion app
return "I've sent you a link to connect your account — open it, sign in, and tap allow."
return do_something(token.access_token)
When oauth= is set, the SDK automatically serves the callback:
GET /pipbit/oauth/callback
so your redirect_uri must point there (and HTTPS). The state parameter is
HMAC-signed with your agent secret and time-limited, so a third party can't
forge a callback to link the wrong identity.
Helpers:
agent.account_link_url(subject_id)— the URL to deliver to the user.agent.get_oauth_token(subject_id)— a validOAuth2Token(refreshed if needed), orNoneif not linked / no longer refreshable.agent.is_linked(subject_id)/agent.unlink(subject_id).on_account_link=(anAgentkwarg) firesfn(subject_id, token)after a successful link — handy topush_messagethe user a confirmation.
Delivering the link is your responsibility — a spoken URL is useless, so send it over SMS, email, or a companion app. (On the Pipbit platform, an out-of-band SMS delivery primitive is provided separately.)
Health checks
The SDK exposes:
GET /healthGET /pipbit/health
The response is structured and readiness-aware. The SDK includes:
- a required
agent_secretcheck - a non-required
platform_healthcheck againstGET {base_url}/health
Add your own checks for agent-specific dependencies:
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:
{
"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 /metricsGET /pipbit/metrics
Current counters include:
webhook_requests_totalwebhook_success_totalwebhook_immediate_replies_totalwebhook_deferred_replies_totalwebhook_auth_failures_totalwebhook_invalid_requests_totalwebhook_configuration_errors_totalwebhook_handler_errors_totalpush_reply_calls_totalpush_message_calls_totalplatform_health_checks_totalplatform_health_check_errors_total
Local development
Run your Flask app locally:
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, rolevoice_binding: platform-selected locked concrete voicevoice_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:
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:
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:
AuthenticationErrorInvalidRequestErrorConfigurationError
Inbound webhook failures return JSON error bodies with sensible HTTP status codes.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pipbit-0.6.0.tar.gz.
File metadata
- Download URL: pipbit-0.6.0.tar.gz
- Upload date:
- Size: 28.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ddb75ba6fb3d4aa3fcf7676bd17cacd45ab4a00aa3497fa42fea3fd6ccfa0957
|
|
| MD5 |
5ad943af55c507435c7a0a7b9496c129
|
|
| BLAKE2b-256 |
f57af7715817615f2ae0261d1e01187d65c4041d27dab5699ebd01077df83afd
|
File details
Details for the file pipbit-0.6.0-py3-none-any.whl.
File metadata
- Download URL: pipbit-0.6.0-py3-none-any.whl
- Upload date:
- Size: 23.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dff131a323458de410c1e9445972aac65dd7655141873df9134ebc2af1b0808d
|
|
| MD5 |
71c0d266b4ab516d5b3ed3ca6264cfcc
|
|
| BLAKE2b-256 |
ebd4f1ba6a6a98e2a21be2c6ca9dd3d71a50aae0af2c3768078c532b5e749592
|