Skip to main content

Roe Python SDK

A Python SDK for the Roe API.

v1.1.14 - SDK operation coverage is synchronized across Python, TypeScript, and Go. See SDK_EXAMPLES.md for copy-ready examples and use cases.

v1.0.0 - The SDK delegates transport and type details to the generated OpenAPI client behind stable public methods such as client.agents and client.policies. 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:

try:
    client.agents.retrieve("00000000-0000-0000-0000-000000000000")
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.

SDK Operation Groups

Common operations are available directly on the SDK client.

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-5.5-2026-04-23",
        "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-5.5-2026-04-23",
        "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-5.5-2026-04-23",
        "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 submissions
  • client.agents.jobs.retrieve_status_many() — batch status checks
  • client.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()

# Skip the job-result cache and force a fresh run
# (available on run, run_sync, run_many, run_version, run_version_sync;
# the fresh result still refreshes the cache)
job = client.agents.run(agent_id="uuid", skip_cache=True, text="input")

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",
)

# Reuse a retrieved agent id when building the run request
agent = client.agents.retrieve("agent-uuid")
job = client.agents.run(
    agent_id=str(agent.id),
    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.5 Pro gpt-5.5-pro-2026-04-23
GPT-5.5 gpt-5.5-2026-04-23
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.8 claude-opus-4-8
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
Research ResearchEngine
Maps Search GoogleMapsEntityExtractionEngine
Social Media SocialScraperEngine
Marketplace Storefront Analysis MarketplaceStorefrontAnalysisEngine
Product Compliance ProductPolicyEngine
Merchant Risk MerchantRiskEngine
AML Investigation AMLInvestigationEngine
Fraud Investigation FraudInvestigationEngine

Development

Before opening a PR, format and lint the codebase by running:

./roe-cli format

CI runs the same checks (ruff check and ruff format --check) on every pull request and on merges to main, and they must pass before a PR can be merged.

Links

Metadata

Release files for roe-ai 1.1.14

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for roe-ai 1.1.14
File Size Uploaded Provenance
roe_ai-1.1.14.tar.gz 107.4 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for roe-ai 1.1.14
File Interpreter ABI Platform
roe_ai-1.1.14-py3-none-any.whl Python 3 none any Details

Total release size: 436.8 kB

Release files / roe_ai-1.1.14.tar.gz

Download URL roe_ai-1.1.14.tar.gz
Size 107.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8eec59e9ed8a7f5ba003f85f0f46da29a4bf86347a6d5d33baace9b471a2ba4d
BLAKE2b-256 checksum
How to use checksums
def54fd8607419c0b0b2370d73d92dda3ccf59a3c397e6e1c5a90c5aee3dacd4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.

Transparency log

Release files / roe_ai-1.1.14-py3-none-any.whl

Download URL roe_ai-1.1.14-py3-none-any.whl
Size 329.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f7b84816af4976c1f3b9b6212bd10372bc8e75319eea8671ea9846ca2f3a0bf2
BLAKE2b-256 checksum
How to use checksums
c11bff57d8212fa13c2418ffcb468221f5956642d9e8e0e0662e435ec53403c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.

Transparency log

Security for roe-ai 1.1.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for roe_ai-1.1.14.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

1.1.14 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page