Python SDK
Configure the Python client, query data, paginate, close resources, and handle errors.
Install and configure
Install from the private registry configured for your organization:
python -m pip install combined-contextUse the client as a context manager so its HTTP connection pool is always closed:
import os
from combined_context import ContextOS
with ContextOS(
token=os.environ["COMBINED_TOKEN"],
base_url=os.environ["COMBINED_API_URL"],
timeout=30.0,
) as context:
accounts = context.accounts.list()If you do not pass token or base_url, the client reads COMBINED_TOKEN and COMBINED_API_URL. Call context.close() when you cannot use a context manager. A custom httpx.BaseTransport is supported for testing or controlled networking.
Discover and query
with ContextOS() as context:
catalogue = context.catalog.list(account_id)
result = context.sql.query(
account_id,
"""
SELECT channel_name, COUNT(*) AS messages
FROM slack_messages
WHERE sent_at >= ?
GROUP BY channel_name
ORDER BY messages DESC
LIMIT 20
""",
parameters=["2026-08-01T00:00:00Z"],
max_rows=20,
)
print(result["columns"], result["rows"], result["truncated"])Pagination
cursor = None
while True:
page = context.sources.list(account_id, cursor=cursor, limit=100)
for source in page.data:
print(source["name"], source["state"])
cursor = page.next_cursor
if cursor is None:
breakThe Page dataclass exposes data, next_cursor, has_more, and correlation_id. Restart from the first page if filters change. Never construct or decode a cursor.
Request options
Pass RequestOptions to control idempotency keys. The SDK generates a secure key for mutations when one is omitted. Reuse a supplied idempotency_key only for an identical request.
from combined_context import RequestOptions
context.sources.run(
account_id,
source_id,
trigger="manual",
options=RequestOptions(idempotency_key="run-20260816-001"),
)Error handling
from combined_context import ContextOSError
try:
result = context.sql.query(account_id, sql, parameters=parameters)
except ContextOSError as error:
print(error.status, error.code, error.correlation_id, error.details)
raiseThe client validates required envelope and model fields. An invalid upstream envelope is raised as a 502 invalid_response, rather than returning partially trusted data.