Skip to main content

Python SDK for SINAS - AI Agent Platform

Project description

SINAS Python SDK

Python SDK for SINAS - AI Agent & Automation Orchestration Platform.

Runtime API Client for executing agents, managing state, running webhooks, and tracking executions.

Installation

pip install sinas

With FastAPI integration:

pip install sinas[fastapi]

Quick Start

Authentication

from sinas import SinasClient

# Initialize client with base URL
client = SinasClient(base_url="http://localhost:51245")

# Step 1: Login with email (sends OTP)
login_response = client.auth.login("user@example.com")
session_id = login_response["session_id"]

# Step 2: Verify OTP and get access + refresh tokens
response = client.auth.verify_otp(session_id, "123456")
# Tokens are automatically set on the client
access_token = response["access_token"]
refresh_token = response["refresh_token"]

# Or use an API key directly
client = SinasClient(
    base_url="http://localhost:51245",
    api_key="your-api-key"
)

Environment Variables

Configure the client using environment variables:

export SINAS_BASE_URL="http://localhost:51245"
export SINAS_API_KEY="your-api-key"
# or
export SINAS_TOKEN="your-jwt-token"
from sinas import SinasClient

# Automatically uses environment variables
client = SinasClient()

Core Features

State Management

Store and retrieve key-value data with namespacing and visibility controls:

# Create/set a state value
state = client.state.set(
    namespace="user_prefs",
    key="theme",
    value={"mode": "dark", "accent": "blue"},
    description="User theme preferences",
    visibility="private"  # private, group, or public
)

# Get a specific state
state = client.state.get(state["id"])
print(state["value"])  # {"mode": "dark", "accent": "blue"}

# List states with filtering
states = client.state.list(
    namespace="user_prefs",
    visibility="private",
    tags="settings",
    search="theme"
)

# Update state
updated = client.state.update(
    state["id"],
    value={"mode": "light", "accent": "green"}
)

# Delete state
client.state.delete(state["id"])

Agent Chats

Create chats with agents and send messages:

# Create a chat with an agent
chat = client.chats.create(
    namespace="customer-support",
    agent_name="cs-agent-v1",
    title="Customer Inquiry",
    input={"customer_id": "12345"}  # Optional input validated by agent
)

# Send a message (blocking)
response = client.chats.send(
    chat_id=chat["id"],
    content="What's the status of my order?"
)
print(response["content"])

# Stream a message (Server-Sent Events)
for chunk in client.chats.stream(
    chat_id=chat["id"],
    content="Tell me about your services"
):
    # Parse SSE data
    import json
    try:
        data = json.loads(chunk)
        if "content" in data:
            print(data["content"], end="", flush=True)
    except:
        pass

# Get chat with all messages
chat_data = client.chats.get(chat["id"])
messages = chat_data["messages"]

# List all chats
chats = client.chats.list()

# Update chat
client.chats.update(chat["id"], title="Updated Title")

# Delete chat
client.chats.delete(chat["id"])

Webhook Execution

Execute webhooks by path:

# Execute a webhook
result = client.webhooks.run(
    path="process-payment",
    method="POST",
    body={"amount": 100, "currency": "USD"},
    headers={"X-Custom-Header": "value"},
    query={"idempotency_key": "abc123"}
)

print(result["execution_id"])  # Track execution
print(result["result"])  # Function output

Executions

Track and manage function executions:

# List recent executions
executions = client.executions.list(
    function_name="payment-processor",
    status="completed",
    limit=10
)

# Get execution details
execution = client.executions.get("execution-id")
print(execution["status"])  # running, completed, failed, awaiting_input
print(execution["output_data"])

# Get execution steps
steps = client.executions.get_steps("execution-id")
for step in steps:
    print(f"{step['step_name']}: {step['status']}")

# Continue a paused execution
result = client.executions.continue_execution(
    "execution-id",
    input={"user_choice": "approve"}
)

Authentication Methods

# Refresh access token
refreshed = client.auth.refresh(refresh_token)
new_access_token = refreshed["access_token"]

# Exchange external OIDC token
response = client.auth.external_auth(external_oidc_token)

# Get current user info
user = client.auth.get_me()
print(user["email"])

# Logout (revoke refresh token)
client.auth.logout(refresh_token)

FastAPI Integration

SINAS provides two powerful approaches for FastAPI integration:

Approach 1: Ready-to-Mount Routers

Mount SINAS Runtime API endpoints directly in your FastAPI app with automatic authentication:

from fastapi import FastAPI
from sinas.integrations.routers import create_runtime_router

app = FastAPI()

# Mount ALL runtime endpoints at once
app.include_router(
    create_runtime_router("http://localhost:51245", include_auth=False),
    prefix="/api/runtime"
)

# This automatically creates endpoints like:
# - GET    /api/runtime/states
# - POST   /api/runtime/states
# - GET    /api/runtime/chats
# - POST   /api/runtime/agents/{namespace}/{agent}/chats
# - POST   /api/runtime/webhooks/{path}
# - GET    /api/runtime/executions

Or mount individual routers:

from sinas.integrations.routers import (
    create_state_router,
    create_chat_router,
    create_webhook_router,
    create_executions_router
)

app.include_router(create_state_router("http://localhost:51245"), prefix="/runtime/states")
app.include_router(create_chat_router("http://localhost:51245"), prefix="/runtime/chats")
app.include_router(create_webhook_router("http://localhost:51245"), prefix="/runtime/webhooks")
app.include_router(create_executions_router("http://localhost:51245"), prefix="/runtime/executions")

Approach 2: Custom Endpoints with SDK Client

Build custom endpoints with business logic using the authenticated client:

from fastapi import FastAPI, Depends
from sinas import SinasClient
from sinas.integrations.fastapi import SinasAuth

app = FastAPI()
sinas = SinasAuth(base_url="http://localhost:51245")

# Include auto-generated auth endpoints
app.include_router(sinas.router, prefix="/auth")

# Custom endpoint with auto-authentication
@app.get("/my-states")
async def get_my_states(client: SinasClient = Depends(sinas)):
    """List user's states with custom filtering."""
    states = client.state.list(limit=10)
    return [{"id": s["id"], "key": s["key"]} for s in states]

# Combine multiple SDK calls
@app.post("/quick-chat")
async def quick_chat(
    agent_namespace: str,
    agent_name: str,
    message: str,
    client: SinasClient = Depends(sinas)
):
    """Create chat and send message in one request."""
    chat = client.chats.create(agent_namespace, agent_name)
    response = client.chats.send(chat["id"], message)
    return {"chat_id": chat["id"], "response": response}

# Permission-protected endpoint
@app.post("/admin/cleanup")
async def cleanup_states(
    namespace: str,
    client: SinasClient = Depends(sinas.require("sinas.contexts.delete:all"))
):
    """Admin-only: Clean up states (requires permission)."""
    states = client.state.list(namespace=namespace)
    for state in states:
        client.state.delete(state["id"])
    return {"deleted": len(states)}

Auto-Generated Auth Endpoints

The sinas.router automatically provides:

  • POST /auth/login - Send OTP to email
  • POST /auth/verify-otp - Verify OTP and get tokens
  • GET /auth/me - Get current authenticated user

Permission-Based Access Control

Use sinas.require() to protect endpoints:

# Require specific permission
@app.delete("/states/{state_id}")
async def delete_state(
    state_id: str,
    client: SinasClient = Depends(sinas.require("sinas.contexts.delete:own"))
):
    client.state.delete(state_id)
    return {"message": "Deleted"}

# Require multiple permissions (OR logic)
@app.post("/admin-action")
async def admin_action(
    client: SinasClient = Depends(
        sinas.require("sinas.admin:all", "sinas.contexts.write:all")
    )
):
    return {"message": "Admin action completed"}

Complete Example

See examples/fastapi_app.py for a complete working example with both approaches.

Run it with:

uvicorn examples.fastapi_app:app --reload

Then visit http://localhost:8000/docs for interactive API documentation.

Context Manager

The client can be used as a context manager for proper resource cleanup:

with SinasClient(base_url="http://localhost:51245") as client:
    states = client.state.list()
    # Client is automatically closed when exiting

Error Handling

from sinas import (
    SinasClient,
    SinasAPIError,
    SinasAuthError,
    SinasNotFoundError,
    SinasValidationError
)

client = SinasClient(base_url="http://localhost:51245")

try:
    state = client.state.get("non-existent-id")
except SinasNotFoundError as e:
    print(f"State not found: {e}")
except SinasAuthError as e:
    print(f"Authentication failed: {e}")
except SinasValidationError as e:
    print(f"Validation error: {e}")
except SinasAPIError as e:
    print(f"API error: {e}")
    print(f"Status code: {e.status_code}")
    print(f"Response: {e.response}")

API Reference

SinasClient

auth

  • login(email) - Send OTP to email
  • verify_otp(session_id, otp_code) - Verify OTP and get tokens
  • external_auth(token) - Exchange external OIDC token
  • refresh(refresh_token) - Refresh access token
  • logout(refresh_token) - Revoke refresh token
  • get_me() - Get current user info

state

  • set(namespace, key, value, ...) - Create/update state
  • get(state_id) - Get state by ID
  • list(namespace?, visibility?, ...) - List states with filters
  • update(state_id, value?, ...) - Update state
  • delete(state_id) - Delete state

chats

  • create(namespace, agent_name, input?, title?) - Create chat with agent
  • send(chat_id, content) - Send message (blocking)
  • stream(chat_id, content) - Send message (streaming SSE)
  • get(chat_id) - Get chat with messages
  • list() - List user's chats
  • update(chat_id, title?) - Update chat
  • delete(chat_id) - Delete chat

webhooks

  • run(path, method?, body?, headers?, query?) - Execute webhook

executions

  • list(function_name?, status?, skip?, limit?) - List executions
  • get(execution_id) - Get execution details
  • get_steps(execution_id) - Get execution steps
  • continue_execution(execution_id, input) - Continue paused execution

FastAPI Integration

SinasAuth(base_url, auto_error=True)

FastAPI dependency for authentication and authorization.

Router Functions

  • create_runtime_router(base_url, include_auth=False) - Complete runtime router
  • create_state_router(base_url, prefix="") - State endpoints
  • create_chat_router(base_url, prefix="") - Chat endpoints
  • create_webhook_router(base_url, prefix="") - Webhook endpoints
  • create_executions_router(base_url, prefix="") - Execution endpoints

Development

Install Development Dependencies

pip install -e ".[dev]"

Run Examples

# Basic usage
python examples/basic_usage.py

# FastAPI app
uvicorn examples.fastapi_app:app --reload

Code Formatting

black sinas
ruff check sinas

License

MIT

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

sinas-0.1.0.tar.gz (24.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sinas-0.1.0-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

Details for the file sinas-0.1.0.tar.gz.

File metadata

  • Download URL: sinas-0.1.0.tar.gz
  • Upload date:
  • Size: 24.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for sinas-0.1.0.tar.gz
Algorithm Hash digest
SHA256 04a38c530d048a644df8487ecf8eaf1ba909310a8da931cdd04c1ce79f7df101
MD5 ee9338e67c46d037330c28d728c96a21
BLAKE2b-256 72268077bc4bc388fe9b21ac68502267975103a73b938ccb4c97c2a3310db06f

See more details on using hashes here.

File details

Details for the file sinas-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: sinas-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 18.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for sinas-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 811cffd13592567957a96a78e06762c87c739d82d43627511d19400dfd9c1116
MD5 46c36db5f82a312c99062d782b081b00
BLAKE2b-256 0c4b124c177dbe5949f635a17b613ababe10afdfc5e6b90dbb4be8b19c37574d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page