Python SDK for the Roe AI API
Project description
Roe AI Python SDK
A Python SDK for the Roe AI API.
v1.0.802 — Version synchronization across the public SDKs: roe-ai (Python), roe-typescript, and roe-golang. The public SDK packages now share a single 1.0.x patch counter, driven by the SDK OpenAPI spec. Python friendly wrappers are generated from
openapi/wrappers.yml; current generated facades includeclient.discoveryandclient.tables.
v1.0.0 — The SDK delegates to OpenAPI-generated types and transports (
roe._generated); ergonomic wrappers onclient.agentsandclient.policiesremain. Noteworthy API and behavioral changes compared to earlier releases are listed in CHANGELOG.md.
Installation
uv add roe-ai
Quick Start
from roe import RoeClient
client = RoeClient(
api_key="your-api-key",
organization_id="your-org-uuid"
)
# Run an existing agent
job = client.agents.run(agent_id="agent-uuid", text="Analyze this text")
result = job.wait()
for output in result.outputs:
print(f"{output.key}: {output.value}")
Or set environment variables:
export ROE_API_KEY="your-api-key"
export ROE_ORGANIZATION_ID="your-org-uuid"
Job Result Inspection
After waiting for a job, inspect its outcome using the JobStatus enum.
The terminal status and error message are stuffed into the generated
response's additional_properties and accessed via subscript:
from roe import JobStatus
result = job.wait()
# Check job outcome
if result["status"] in (JobStatus.SUCCESS, JobStatus.CACHED):
for output in result.outputs:
print(f"{output.key}: {output.value}")
elif result["status"] == JobStatus.CANCELLED:
print("Job was cancelled")
elif result["status"] == JobStatus.FAILURE:
print("Error:", result["error_message"])
# Available fields
result.outputs # list[AgentDatum] (direct attribute on the generated model)
result["status"] # JobStatus code (int) — set by Job.wait()
result["error_message"] # Error string or None — set by Job.wait()
Errors
Non-2xx responses raise typed exceptions from roe.exceptions, all
subclasses of RoeAPIException. Use them to handle expected failures
without parsing error strings:
from roe.exceptions import (
RoeAPIException,
BadRequestError, # 400 — validation / bad input
AuthenticationError, # 401 — missing or invalid API key
InsufficientCreditsError, # 402 — plan limit / billing
ForbiddenError, # 403 — feature or resource forbidden
NotFoundError, # 404 — resource not found
ServerError, # 5xx — server-side
)
try:
client.agents.retrieve("00000000-0000-0000-0000-000000000000")
except NotFoundError as exc:
print(exc.status_code, exc.message)
Every RoeAPIException also carries exc.headers (lowercase-keyed dict
of the upstream response headers). Use it to read Retry-After on 429s
or X-Request-Id for support tickets, without falling back to the raw
httpx layer. Retry-After is preserved exactly as sent, so it may be
numeric seconds or an HTTP-date:
except RoeAPIException as exc:
if exc.status_code == 429 and exc.headers:
retry_after = exc.headers.get("retry-after")
job.wait() does not raise on agent-side failures — instead the returned
result carries result["status"] == JobStatus.FAILURE and
result["error_message"]. Transport / HTTP errors hit the typed
hierarchy above.
Raw API Access
When the ergonomic wrappers don't expose an endpoint you need, the generated
client is available as client.raw and the operation modules live under
roe._generated.api.<tag>.<operation_id>. Submodule names follow the
upstream OpenAPI tags + operationIds and may shift across releases, so the
portable form uses client.raw.get_httpx_client() to send a request through
the same auth-configured httpx.Client:
from roe import RoeClient
client = RoeClient(api_key="your-api-key", organization_id="your-org-uuid")
response = client.raw.get_httpx_client().get("/v1/users/current_user/")
print(response.status_code)
For typed request/response models, call the generated operation module
directly — see roe/_generated/api/ for the current surface.
Generated Friendly APIs
This block is synced from roe-main/roe-sdk/sdk_contract.yml during SDK fan-out.
engines = client.discovery.list_agent_engine_types()
models = client.discovery.list_supported_models(capability="text")
upload = client.tables.upload(
table_name="customers",
file="customers.csv",
with_headers=True,
)
Agent Examples
Multimodal Extraction
Extract structured data from text and images:
agent = client.agents.create(
name="Listing Analyzer",
engine_class_id="MultimodalExtractionEngine",
input_definitions=[
{"key": "text", "data_type": "text/plain", "description": "Item description"},
],
engine_config={
"model": "gpt-4.1-2025-04-14",
"text": "${text}",
"instruction": "Analyze this product listing. Is it counterfeit?",
"output_schema": {
"type": "object",
"properties": {
"is_counterfeit": {"type": "boolean", "description": "Whether likely counterfeit"},
"confidence": {"type": "number", "description": "Confidence score 0-1"},
"reasoning": {"type": "string", "description": "Explanation"},
}
}
}
)
job = client.agents.run(
agent_id=str(agent.id),
text="Authentic Louis Vuitton bag, brand new, $50"
)
result = job.wait()
Document Insights
Extract structured information from PDFs:
agent = client.agents.create(
name="Resume Parser",
engine_class_id="PDFExtractionEngine",
input_definitions=[
{"key": "pdf_files", "data_type": "application/pdf", "description": "Resume PDF"},
],
engine_config={
"model": "gpt-4.1-2025-04-14",
"pdf_files": "${pdf_files}",
"instructions": "Extract candidate information from this resume.",
"output_schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
"skills": {"type": "array", "items": {"type": "string"}},
}
}
}
)
job = client.agents.run(agent_id=str(agent.id), pdf_files="resume.pdf")
result = job.wait()
Web Insights
Extract data from websites with automatic screenshot/HTML/markdown capture:
agent = client.agents.create(
name="Company Analyzer",
engine_class_id="URLWebsiteExtractionEngine",
input_definitions=[
{"key": "url", "data_type": "text/plain", "description": "Website URL"},
],
engine_config={
"url": "${url}",
"model": "gpt-4.1-2025-04-14",
"instruction": "Extract company information from this website.",
"vision_mode": False,
"crawl_config": {
"save_html": True,
"save_markdown": True,
"save_screenshot": True,
},
"output_schema": {
"type": "object",
"properties": {
"company_name": {"type": "string"},
"description": {"type": "string"},
"products": {"type": "array", "items": {"type": "string"}},
}
}
}
)
# Run the agent
job = client.agents.run(agent_id=str(agent.id), url="https://www.roe-ai.com/")
result = job.wait()
for output in result.outputs:
print(f"{output.key}: {output.value}")
Interactive Web
Navigate websites and perform actions:
agent = client.agents.create(
name="Meeting Booker",
engine_class_id="InteractiveWebExtractionEngine",
input_definitions=[
{"key": "url", "data_type": "text/plain", "description": "Website URL"},
{"key": "action", "data_type": "text/plain", "description": "Action to perform"},
],
engine_config={
"url": "${url}",
"action": "${action}",
"output_schema": {
"type": "object",
"properties": {
"calendar_link": {"type": "string", "description": "Booking link found"},
"steps_taken": {"type": "array", "items": {"type": "string"}},
}
}
}
)
job = client.agents.run(
agent_id=str(agent.id),
url="https://www.roe-ai.com/",
action="Find the founder's calendar link to book a meeting"
)
result = job.wait()
Rori Agents (Agentic Workflows)
Rori agents are autonomous investigation agents that follow policies (SOPs), use tools, and produce structured verdicts. Unlike extraction engines which transform data, Rori agents reason over evidence, apply policy rules, and return dispositions. All Rori agents are policy-aware — you define the rules, they run the investigation.
Policies
Policies define the rules, instructions, and disposition classifications that Rori agents follow. Creating a policy atomically creates the policy and its first version in one call:
policy = client.policies.create(
name="AML Investigation Policy",
content={
"guidelines": {
"categories": [
{
"title": "Structuring",
"rules": [
{
"title": "Cash structuring below reporting thresholds",
"description": "Multiple deposits just under $10,000 within short timeframes",
"flag": "RED_FLAG",
}
],
},
{
"title": "Layering",
"rules": [
{
"title": "Rapid movement between accounts",
"description": "Funds transferred through multiple accounts to obscure origin",
"flag": "RED_FLAG",
"sub_rules": [
{"title": "Cross-border wire transfers with no business purpose"},
{"title": "Shell company intermediaries"},
],
}
],
},
]
},
"instructions": "Investigate the alert against each category. Use available data sources to gather evidence.",
"dispositions": {
"classifications": [
{"name": "Suspicious", "description": "Activity warrants SAR filing"},
{"name": "Not Suspicious", "description": "Activity has legitimate explanation"},
{"name": "Needs Escalation", "description": "Requires senior analyst review"},
]
},
"summary_template": {
"template": "Investigation of {{subject}} found {{verdict}} based on {{findings_count}} findings."
},
},
)
Iterate on policies by creating new versions:
# Create a new version (automatically becomes the current version)
new_version = client.policies.versions.create(
policy_id=str(policy.id),
content={...}, # Updated policy content
version_name="v2 - added layering rules",
)
# List all versions
versions = client.policies.versions.list(policy_id=str(policy.id))
# Retrieve a specific version
version = client.policies.versions.retrieve(str(policy.id), str(new_version.id))
# Update policy metadata
client.policies.update(str(policy.id), name="Updated Policy Name")
# List all policies
policies = client.policies.list()
# Delete a policy
client.policies.delete(str(policy.id))
Policy Content Reference
| Field | Type | Description |
|---|---|---|
guidelines |
object | Categories → Rules → Sub-rules hierarchy |
guidelines.categories[].title |
string | Category name |
guidelines.categories[].rules[].title |
string | Rule name |
guidelines.categories[].rules[].description |
string | Rule details |
guidelines.categories[].rules[].flag |
string | "RED_FLAG" or "GREEN_FLAG" |
guidelines.categories[].rules[].sub_rules[].title |
string | Sub-rule name |
instructions |
string | Free-text investigation instructions |
dispositions.classifications[].name |
string | Outcome label (e.g., "Suspicious") |
dispositions.classifications[].description |
string | When to apply this outcome |
summary_template.template |
string | Handlebars template for report generation |
optional.sar_narrative_template.template |
string | SAR narrative template (AML-specific) |
Product Compliance
Analyze product listings against your compliance policy:
agent = client.agents.create(
name="Product Compliance",
engine_class_id="ProductPolicyEngine",
input_definitions=[
{"key": "product_listings", "data_type": "text/plain", "description": "Product listing to analyze"},
],
engine_config={
"policy_version_id": str(policy.current_version_id),
"product_listings": "${product_listings}",
},
)
result = client.agents.run_sync(
agent_id=str(agent.id),
product_listings="Nike Air Max 90, brand new, $45 — ships from Shenzhen",
)
AML Investigation
Investigate anti-money laundering alerts:
agent = client.agents.create(
name="AML Investigation",
engine_class_id="AMLInvestigationEngine",
input_definitions=[
{"key": "alert_data", "data_type": "text/plain", "description": "Alert data and context"},
],
engine_config={
"policy_version_id": str(policy.current_version_id),
"alert_data": "${alert_data}",
},
)
job = client.agents.run(
agent_id=str(agent.id),
alert_data="Customer John Doe, 5 cash deposits of $9,500 in 3 days",
)
result = job.wait()
Fraud Investigation
Investigate fraud alerts and suspicious activity:
agent = client.agents.create(
name="Fraud Investigation",
engine_class_id="FraudInvestigationEngine",
input_definitions=[
{"key": "alert_data", "data_type": "text/plain", "description": "Alert data and context"},
],
engine_config={
"policy_version_id": str(policy.current_version_id),
"alert_data": "${alert_data}",
},
)
job = client.agents.run(
agent_id=str(agent.id),
alert_data="Chargeback spike: 47 disputes in 24h from merchant ACME-1234",
)
result = job.wait()
Merchant Risk
Analyze merchant risk profiles:
agent = client.agents.create(
name="Merchant Risk Analysis",
engine_class_id="MerchantRiskEngine",
input_definitions=[
{"key": "merchant_context", "data_type": "text/plain", "description": "Merchant name and context"},
],
engine_config={
"policy_version_id": str(policy.current_version_id),
"merchant_context": "${merchant_context}",
},
)
job = client.agents.run(
agent_id=str(agent.id),
merchant_context="ACME Corp - Online electronics retailer, MCC 5732",
)
result = job.wait()
Agent Configuration Options
All Rori agents accept these options in engine_config:
| Option | Type | Default | Description |
|---|---|---|---|
policy_version_id |
string | — | Policy version UUID (required) |
context_sources |
list | [] |
External data sources (SQL connections, APIs) |
enable_planning |
bool | true |
Enable autonomous tool-use planning |
enable_memory |
bool | false |
Retain context across runs for the same entity |
reasoning_effort |
string | "medium" |
"low", "medium", or "high" |
Example with advanced configuration:
agent = client.agents.create(
name="AML Investigation (Advanced)",
engine_class_id="AMLInvestigationEngine",
input_definitions=[
{"key": "alert_data", "data_type": "text/plain", "description": "Alert data and context"},
],
engine_config={
"policy_version_id": str(policy.current_version_id),
"alert_data": "${alert_data}",
"reasoning_effort": "high",
"context_sources": [
{"type": "sql", "name": "Transactions DB", "connection_id": "conn-uuid"},
],
},
)
Retry Behavior
Transient failures are retried with exponential backoff capped at about 10
seconds per attempt. By default there are up to 3 retries (configurable via
max_retries or ROE_MAX_RETRIES):
client = RoeClient(
api_key="your-api-key",
organization_id="your-org-uuid",
max_retries=5, # default: 3
)
Retried: HTTP statuses 408, 429, and any 5xx, plus transport errors
(for example disconnects and timeouts). JSON POST bodies may be replayed;
multipart agent-run calls (run, run_sync, …) opt out via
x-roe-skip-retry so they are not automatically retried at the transport layer.
Not retried immediately: Typical client/auth responses (401, 403,
404, validation 422, …) — surfaced as typed exceptions matching the SDK’s
usual error mapping.
Batch Processing
When batch operations exceed 1,000 items, the SDK automatically chunks requests. A configurable delay (default: 10 seconds) is applied between chunks to avoid overwhelming the API. This applies to:
client.agents.run_many()— job submissionsclient.agents.jobs.retrieve_status_many()— batch status checksclient.agents.jobs.retrieve_result_many()— batch result retrieval
Single-chunk batches (≤1,000 items) are unaffected.
You can configure the delay via the batch_chunk_delay parameter or the ROE_BATCH_CHUNK_DELAY environment variable:
client = RoeClient(
api_key="your-api-key",
organization_id="your-org-uuid",
batch_chunk_delay=2.0, # default: 10.0
)
Running Agents
# Async (recommended)
job = client.agents.run(agent_id="uuid", text="input")
result = job.wait()
# Sync
outputs = client.agents.run_sync(agent_id="uuid", text="input")
# With files (auto-uploaded)
job = client.agents.run(agent_id="uuid", document="file.pdf")
# Batch processing
batch = client.agents.run_many(
agent_id="uuid",
batch_inputs=[{"text": "input1"}, {"text": "input2"}]
)
results = batch.wait()
Metadata
You can attach arbitrary metadata to any job when running an agent. Metadata is a dictionary of key-value pairs that gets stored with the job, useful for tracking, filtering, or correlating jobs with your own internal records.
# Attach metadata to an async job
job = client.agents.run(
agent_id="agent-uuid",
metadata={"customer_id": "cust-123", "request_source": "api"},
url="https://example.com",
)
result = job.wait()
# Attach metadata to a sync job
outputs = client.agents.run_sync(
agent_id="agent-uuid",
metadata={"batch": "2026-02-12", "priority": "high"},
url="https://example.com",
)
# Attach metadata to a batch of jobs (applied to all jobs in the batch)
batch = client.agents.run_many(
agent_id="agent-uuid",
batch_inputs=[{"url": "https://a.com"}, {"url": "https://b.com"}],
metadata={"campaign": "weekly-scan"},
)
results = batch.wait()
# Attach metadata when running a specific version
job = client.agents.run_version(
agent_id="agent-uuid",
version_id="version-uuid",
metadata={"experiment": "v2-prompt"},
url="https://example.com",
)
# Also works directly on agent and version models
agent = client.agents.retrieve("agent-uuid")
job = agent.run(metadata={"source": "sdk"}, url="https://example.com")
Agent Management
# List / Retrieve
agents = client.agents.list()
agent = client.agents.retrieve("uuid")
# Update / Delete
client.agents.update("uuid", name="New Name")
client.agents.delete("uuid")
# Duplicate
#
# Note: client.agents.duplicate(...) returns an AgentVersion (the new agent's
# first version), not a BaseAgent. The new agent's ID is reachable on the
# returned object as `.base_agent.id`:
duplicated_version = client.agents.duplicate("uuid")
new_agent_id = duplicated_version.base_agent.id
Version Management
# List and retrieve versions
versions = client.agents.versions.list("agent-uuid")
current = client.agents.versions.retrieve_current("agent-uuid")
version = client.agents.versions.retrieve("agent-uuid", "version-uuid")
# Create, update, delete versions
version = client.agents.versions.create(
agent_id="agent-uuid",
version_name="v2",
input_definitions=[...],
engine_config={...}
)
client.agents.versions.update("agent-uuid", "version-uuid", version_name="v2-updated")
client.agents.versions.delete("agent-uuid", "version-uuid")
# Run specific versions
job = client.agents.run_version("agent-uuid", "version-uuid", text="input")
result = job.wait()
Job Management
# Retrieve job status and results
status = client.agents.jobs.retrieve_status(job_id)
result = client.agents.jobs.retrieve_result(job_id)
# Batch operations
statuses = client.agents.jobs.retrieve_status_many([job_id1, job_id2])
results = client.agents.jobs.retrieve_result_many([job_id1, job_id2])
# Download references from jobs (screenshots, HTML, markdown)
content = client.agents.jobs.download_reference(job_id, resource_id)
# Delete job data
client.agents.jobs.delete_data(job_id)
Supported Models
| Model | Value |
|---|---|
| GPT-5.4 Pro | gpt-5.4-pro-2026-03-05 |
| GPT-5.4 | gpt-5.4-2026-03-05 |
| GPT-5.4 Mini | gpt-5.4-mini-2026-03-17 |
| GPT-5.4 Nano | gpt-5.4-nano-2026-03-17 |
| GPT-5.2 | gpt-5.2-2025-12-11 |
| GPT-5 | gpt-5-2025-08-07 |
| GPT-4.1 | gpt-4.1-2025-04-14 |
| Claude Opus 4.7 | claude-opus-4-7 |
| Claude Opus 4.6 | claude-opus-4-6 |
| Claude Sonnet 4.6 | claude-sonnet-4-6 |
| Claude Haiku 4.5 | claude-haiku-4-5-20251001 |
| Gemini 3.1 Pro | gemini-3.1-pro-preview |
| Gemini 3 Flash | gemini-3-flash-preview |
| Grok 4.20 Reasoning | grok-4.20-0309-reasoning |
Engine Classes
| Engine | ID |
|---|---|
| Multimodal Extraction | MultimodalExtractionEngine |
| Document Insights | PDFExtractionEngine |
| Document Segmentation | PDFPageSelectionEngine |
| Web Insights | URLWebsiteExtractionEngine |
| Interactive Web | InteractiveWebExtractionEngine |
| Web Search | URLFinderEngine |
| Perplexity Search | PerplexitySearchEngine |
| Maps Search | GoogleMapsEntityExtractionEngine |
| LinkedIn Crawler | LinkedInScraperEngine |
| Social Media | SocialScraperEngine |
| Product Compliance | ProductPolicyEngine |
| Merchant Risk | MerchantRiskEngine |
| AML Investigation | AMLInvestigationEngine |
| Fraud Investigation | FraudInvestigationEngine |
Links
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 roe_ai-1.0.802.tar.gz.
File metadata
- Download URL: roe_ai-1.0.802.tar.gz
- Upload date:
- Size: 53.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30cd634654522db918f2f51c3749d8ed5ca293a52af79d028615f445948828aa
|
|
| MD5 |
e03e2aa751c4aba36fa81392344f114f
|
|
| BLAKE2b-256 |
0bcdd62fbb84ddba62369bab4ba3c0792cef661e93f4b72e59160b3bd361f83a
|
Provenance
The following attestation bundles were made for roe_ai-1.0.802.tar.gz:
Publisher:
publish.yml on roe-ai/roe-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
roe_ai-1.0.802.tar.gz -
Subject digest:
30cd634654522db918f2f51c3749d8ed5ca293a52af79d028615f445948828aa - Sigstore transparency entry: 1635418501
- Sigstore integration time:
-
Permalink:
roe-ai/roe-python@ebc878fac76b8e8590d482e070e1844722a0ce99 -
Branch / Tag:
refs/tags/v1.0.802 - Owner: https://github.com/roe-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ebc878fac76b8e8590d482e070e1844722a0ce99 -
Trigger Event:
push
-
Statement type:
File details
Details for the file roe_ai-1.0.802-py3-none-any.whl.
File metadata
- Download URL: roe_ai-1.0.802-py3-none-any.whl
- Upload date:
- Size: 141.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46240dd8674ca6387dae4d3f7d003d3a2d2dd21abb4c39bcade5da2117cd58c7
|
|
| MD5 |
cd9454e9566d2963ffa66420b1136c5e
|
|
| BLAKE2b-256 |
ebf9442add804f26cac8e3b33f85eddea1595abcb08fdc954fe07a447d0e07bc
|
Provenance
The following attestation bundles were made for roe_ai-1.0.802-py3-none-any.whl:
Publisher:
publish.yml on roe-ai/roe-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
roe_ai-1.0.802-py3-none-any.whl -
Subject digest:
46240dd8674ca6387dae4d3f7d003d3a2d2dd21abb4c39bcade5da2117cd58c7 - Sigstore transparency entry: 1635418518
- Sigstore integration time:
-
Permalink:
roe-ai/roe-python@ebc878fac76b8e8590d482e070e1844722a0ce99 -
Branch / Tag:
refs/tags/v1.0.802 - Owner: https://github.com/roe-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ebc878fac76b8e8590d482e070e1844722a0ce99 -
Trigger Event:
push
-
Statement type: