Python SDK for building Local Apps that integrate with RealtimeX
Project description
RealtimeX Local App SDK - Python
Python SDK for building Local Apps that integrate with RealtimeX.
Installation
pip install realtimex-sdk
Prerequisites
Before using this SDK, ensure your Supabase database is set up via the Main App:
- Open RealtimeX → Settings → Local Apps
- Create or configure your Local App
- Select Compatible Mode → Login to Supabase → Auto-Setup Schema
Note: Schema setup is handled entirely by the Main App.
Quick Start
import asyncio
from realtimex_sdk import RealtimeXSDK, SDKConfig
async def main():
# Development Mode: Use API key
sdk = RealtimeXSDK(config=SDKConfig(
api_key="sk-abc123..."
))
# OR Production Mode: Declare permissions
sdk = RealtimeXSDK(config=SDKConfig(
permissions=['activities.write', 'webhook.trigger']
))
# Insert activity
activity = await sdk.activities.insert({
"type": "new_lead",
"email": "user@example.com"
})
# Trigger agent (auto-run)
result = await sdk.webhook.trigger_agent(
raw_data=activity,
auto_run=True,
agent_name="lead-processor",
workspace_slug="sales",
thread_slug="general"
)
print(f"Task created: {result['task_uuid']}")
# Or create calendar event for manual review
result = await sdk.webhook.trigger_agent(
raw_data=activity,
auto_run=False
)
asyncio.run(main())
Configuration (Optional)
Override auto-detected values if needed:
from realtimex_sdk import RealtimeXSDK, SDKConfig
sdk = RealtimeXSDK(config=SDKConfig(
url="http://custom-host:3001", # Default: localhost:3001
api_key="sk-abc123...", # Development mode
app_id="registered-id" # Production mode (override)
))
Environment Variables
When your app is started by the Main App, these are auto-set:
| Variable | Description |
|---|---|
RTX_APP_ID |
Your app's unique ID |
RTX_APP_NAME |
Your app's display name |
API Reference
Activities CRUD
# Insert
activity = await sdk.activities.insert({"type": "order", "amount": 100})
# List
pending = await sdk.activities.list(status="pending", limit=50)
# Get
item = await sdk.activities.get("activity-uuid")
# Update
await sdk.activities.update("activity-uuid", {"status": "processed"})
# Delete
await sdk.activities.delete("activity-uuid")
LLM Module
Access AI capabilities through the RealtimeX proxy:
from realtimex_sdk import RealtimeXSDK, SDKConfig, ChatMessage, ChatOptions, VectorRecord
sdk = RealtimeXSDK(config=SDKConfig(
permissions=['llm.chat', 'llm.embed', 'llm.providers', 'vectors.write', 'vectors.read']
))
List Providers & Models
# Get only configured Chat providers (recommended)
chat_res = await sdk.llm.chat_providers()
# chat_res.providers: List of chat providers with models
# Get only configured Embedding providers (recommended)
embed_res = await sdk.llm.embed_providers()
# embed_res.providers: List of embedding providers with models
Chat Completion
# Sync Chat
response = await sdk.llm.chat(
messages=[
ChatMessage(role="system", content="You are a helpful assistant."),
ChatMessage(role="user", content="What is RealtimeX?")
],
options=ChatOptions(
model="gpt-4o", # Optional: specific model
provider="openai", # Optional: specific provider
temperature=0.7, # Optional: 0.0-2.0
max_tokens=1000 # Optional: max response tokens
)
)
print(response.content)
# Multimodal Chat (text + file/image blocks)
multimodal = await sdk.llm.chat(
messages=[
ChatMessage(
role="user",
content=[
{"type": "text", "text": "Summarize the attached document"},
{"type": "input_file", "file_url": "https://example.com/report.pdf"},
{"type": "input_image", "image_url": "https://example.com/chart.png"},
],
)
]
)
print(multimodal.content)
# Streaming Chat
async for chunk in sdk.llm.chat_stream(messages, options=options):
print(chunk.text, end="", flush=True)
Generate Embeddings
embed_result = await sdk.llm.embed(
input=["Hello world", "Goodbye"],
provider="openai", # Optional
model="text-embedding-3-small" # Optional
)
embeddings = embed_result.embeddings # List[List[float]]
dimensions = embed_result.dimensions # int (e.g., 1536)
Vector Store Operations
# Upsert vectors with metadata
await sdk.llm.vectors.upsert(
vectors=[
VectorRecord(
id="chunk-1",
vector=embeddings[0],
metadata={
"text": "Hello world", # Original text (for retrieval)
"documentId": "doc-1", # Logical grouping
"customField": "any value" # Any custom metadata
}
)
],
workspace_id="ws-123" # Optional: physical namespace isolation
)
# Query similar vectors
query_result = await sdk.llm.vectors.query(
vector=embeddings[0],
top_k=5, # Number of results
workspace_id="ws-123", # Optional: search in specific workspace
document_id="doc-1" # Optional: filter by document
)
# returns: VectorQueryResponse with results[]
# List all workspaces for this app
res = await sdk.llm.vectors.list_workspaces()
# returns: VectorListWorkspacesResponse with workspaces=['ws-123', 'default', ...]
# Delete all vectors in a workspace
await sdk.llm.vectors.delete(
delete_all=True,
workspace_id="ws-123"
)
High-Level Helpers
These combine multiple operations for common RAG patterns:
# embed_and_store: Text → Embed → Store (one call)
await sdk.llm.embed_and_store(
texts=["Document text 1", "Document text 2"], # texts to embed
document_id="doc-123", # Optional: logical grouping
workspace_id="ws-456", # Optional: physical isolation
provider="openai", # Optional: embedding provider
model="text-embedding-3-small" # Optional: embedding model
)
# search: Query → Embed → Search (one call)
results = await sdk.llm.search(
query="What is RealtimeX?", # search query (text, not vector)
top_k=5, # Number of results
workspace_id="ws-123", # Optional: search in workspace
document_id="doc-1", # Optional: filter by document
provider="openai", # Optional: embedding provider
model="text-embedding-3-small" # Optional: embedding model
)
# returns: List[dict] with id, score, metadata
Note on Isolation:
workspace_id: Creates physical namespace (sdk_{appId}_{wsId}) - data completely isolateddocument_id: Stored as metadata, filtered after search (post-filter)
Public APIs
# Get available agents in a workspace
agents = await sdk.api.get_agents()
# Get all workspaces
workspaces = await sdk.api.get_workspaces()
# Get threads in a workspace
threads = await sdk.api.get_threads("sales")
# Get task status
task = await sdk.api.get_task("task-uuid")
Contract Discovery
contract = await sdk.contract.get_local_app_v1()
print(contract.get("version")) # local-app-contract/v1
print(contract.get("supported_events"))
print(contract.get("callback", {}).get("signature_header")) # x-rtx-contract-signature
Worker Callback Lifecycle
Use this when worker context includes task_uuid, attempt_id, and callback URL metadata.
sdk.task.configure_contract(
callback_secret=os.environ.get("RTX_CONTRACT_CALLBACK_SECRET"),
sign_callbacks_by_default=True,
)
await sdk.task.claim(
task_uuid,
callback_url=callback_url,
machine_id=machine_id,
attempt_id=attempt_id,
user_email=user_email,
)
await sdk.task.start(
task_uuid,
machine_id=machine_id,
callback_url=callback_url,
attempt_id=attempt_id,
)
await sdk.task.progress(
task_uuid,
{"percent": 50, "message": "Halfway done"},
callback_url=callback_url,
machine_id=machine_id,
attempt_id=attempt_id,
)
await sdk.task.complete(
task_uuid,
{"summary": "Done"},
callback_url=callback_url,
machine_id=machine_id,
attempt_id=attempt_id,
)
TaskModule automatically includes event_id, canonical event, and optional signature header for idempotent/signed callbacks.
Contract Compatibility Check
Run the cross-language harness (Main App endpoint + TypeScript SDK + Python SDK):
RTX_API_KEY=sk-... RTX_CONTRACT_VERIFY_BASE_URL=http://127.0.0.1:3001 node scripts/verify-contract-compat.mjs
Error Handling
The SDK provides specific exception classes for handling LLM-related issues:
from realtimex_sdk import LLMPermissionError, LLMProviderError
try:
async for chunk in sdk.llm.chat_stream(messages):
print(chunk.text, end="")
except LLMPermissionError as e:
# Permission not granted: 'llm.chat' etc.
print(f"Permission required: {e.permission}")
except LLMProviderError as e:
# Provider errors: rate limit, timeout, model unavailable, etc.
print(f"Provider error: {e} (code: {e.code})")
# Common codes: LLM_STREAM_ERROR, RATE_LIMIT, PROVIDER_UNAVAILABLE
| Exception Class | Common Codes | Description |
|---|---|---|
LLMPermissionError |
PERMISSION_REQUIRED |
Missing or denied permission |
LLMProviderError |
LLM_STREAM_ERROR, RATE_LIMIT, PROVIDER_UNAVAILABLE |
AI provider issues |
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 realtimex_sdk-1.3.5rc1.tar.gz.
File metadata
- Download URL: realtimex_sdk-1.3.5rc1.tar.gz
- Upload date:
- Size: 105.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ac81ea142e72d38cf1c19dd0540880c554117efb3e68f79bf213023c812fdfc
|
|
| MD5 |
2112d81ae20fae933f7cde16719c949e
|
|
| BLAKE2b-256 |
005c7e51f674a5a7dcf081eb3880c349c543eced256be2a9032c5b8e047dc109
|
File details
Details for the file realtimex_sdk-1.3.5rc1-py3-none-any.whl.
File metadata
- Download URL: realtimex_sdk-1.3.5rc1-py3-none-any.whl
- Upload date:
- Size: 29.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59836af8b4c19c31b6fa3672ec17762840ef4b9ebde8f29b327bd11f923099ec
|
|
| MD5 |
8ef0d8b22ce4ca252f780db1fe417c2f
|
|
| BLAKE2b-256 |
ba9e1919f99761307a9ac5fb0289fbc34d3e21b3d5d53139f2634ef5c863bd28
|