Async-first Python SDK for On-Demand APIs
Project description
OnDemand Python SDK
Async-first, dual-mode (sync + async) client for interacting with On-Demand APIs.
Installation
pip install ondemand
Python ≥ 3.9 required.
Environment Variables
| Variable | Required | Description |
|---|---|---|
ONDEMAND_API_KEY |
✅ | API key for On-Demand |
Core Concepts
Client
- Single entrypoint:
OnDemandClient - Manages authentication, HTTP lifecycle, and resources
Resources
Each API domain is exposed as a resource:
sessions→ chat sessionsmedia→ file uploadschat→ query + streaming responses
Execution Modes
- Sync: blocking, simple scripts
- Async: non-blocking, scalable services
Both share the same API surface.
Quick Start (Sync)
from ondemand import OnDemandClient
client = OnDemandClient.from_env()
session_id = client.sessions.create(
external_user_id="user-1",
agents=["agent-123"],
context={"role": "admin"},
)
for event in client.chat.stream(
session_id=session_id,
query="Hello",
agents=["agent-123"],
endpoint="predefined-xai-grok4.1-fast",
):
print(event)
client.close()
Quick Start (Async)
from ondemand import OnDemandClient
async with OnDemandClient.aio() as client:
session_id = await client.sessions.create(
external_user_id="user-1",
agents=["agent-123"],
context={"role": "admin"},
)
async for event in client.chat.stream(
session_id=session_id,
query="Hello",
agents=["agent-123"],
endpoint="predefined-xai-grok4.1-fast",
):
print(event)
Client Lifecycle
Sync
client = OnDemandClient.from_env()
...
client.close()
Async
async with OnDemandClient.aio() as client:
...
Always close the client to release HTTP resources.
Configuration
OnDemandConfig
from ondemand.config import OnDemandConfig
cfg = OnDemandConfig.from_env()
| Field | Description |
|---|---|
api_key |
API key (required) |
chat_base_url |
Chat API base URL |
media_base_url |
Media API base URL |
timeout |
HTTP timeout (seconds) |
Configuration is immutable.
Sessions API
Create Session
session_id = client.sessions.create(
external_user_id="user-1",
agents=["agent-a", "agent-b"],
context={"userId": "1", "name": "John"},
)
Parameters
external_user_id(str) – caller identityagents(List[str]) – agent/plugin IDscontext(Dict[str, str]) – session metadata
Returns
session_id(str)
Media API
Upload File
media = client.media.upload(
path="image.png",
name="image.png",
session_id=session_id,
agents=["agent-x"],
)
Parameters
path– local file pathname– file name exposed to APIsession_id– owning sessionagents– agents allowed to process the file
Returns
- dict containing
id,url, metadata
Chat API
Stream Response (Sync)
for event in client.chat.stream(
session_id=session_id,
query="Explain this",
agents=["agent-a"],
endpoint="predefined-xai-grok4.1-fast",
):
print(event)
Stream Response (Async)
async for event in client.chat.stream(...):
print(event)
Event format
{
"eventType": "fulfillment",
"answer": "..."
}
Streaming ends when [DONE] is received.
Error Handling
All SDK errors inherit from OnDemandError.
Common Errors
from ondemand.errors import HTTPError, ConfigurationError
| Error | Meaning |
|---|---|
ConfigurationError |
Missing / invalid config |
HTTPError |
Non-2xx HTTP response |
Example
try:
client.sessions.create(...)
except HTTPError as e:
print(e.status_code)
print(e.body)
Errors are never swallowed.
Thread & Async Safety
- Async client uses
httpx.AsyncClient - Sync client safely bridges async via
anyio - No global state
- Safe for multi-request workflows
Design Guarantees
- One client → all resources
- No duplicated logic between sync/async
- Predictable lifecycle
- Minimal abstractions
- Extendable (
client.workflows,client.metrics, etc.)
Non-Goals
- No implicit retries
- No background threads
- No hidden state
- No auto-pagination magic
These can be layered on if needed.
Extending the SDK
Add a new resource:
client.workflows.execute(...)
Pattern:
- resource file
- async method
- exposed via
OnDemandClient
Versioning & Stability
- Backward-compatible minor releases
- Breaking changes only in major versions
- Explicit API surface
If you want next:
- workflow API integration
- retry + backoff policy
- CLI wrapper
- FastAPI dependency injection
- pydantic models
Say what you want to build on top.
Project details
Release history Release notifications | RSS feed
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 ondemand_wrapper-0.1.3.tar.gz.
File metadata
- Download URL: ondemand_wrapper-0.1.3.tar.gz
- Upload date:
- Size: 5.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
107ecfa44af140b79ddcc19717e05e62e4096f7ca7f0504247b39dd7aa94c387
|
|
| MD5 |
2d7bce274607f84506b717d6c715e2ca
|
|
| BLAKE2b-256 |
93d5ca27d0e30ddaef2d79d7f0b25d4ddfbced0393115b737de6c44968e4d9d0
|
File details
Details for the file ondemand_wrapper-0.1.3-py3-none-any.whl.
File metadata
- Download URL: ondemand_wrapper-0.1.3-py3-none-any.whl
- Upload date:
- Size: 5.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
95e03eb397997f60af4adca50e2d6d2a1f9dc1b1fb264227cb6ee18b1d9c13fc
|
|
| MD5 |
1a59b4937888d944aa4d5935ec00b234
|
|
| BLAKE2b-256 |
5c4c5be8d3419337ab765e1e3de698019308c6b3889c83f9c996b2a7e72b2a54
|