Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 51 additions & 165 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,54 @@
# Roe AI Python SDK

A Python SDK for the [Roe AI](https://www.roe-ai.com/) API.
Python SDK for the [Roe AI](https://www.roe-ai.com/) API.

## Installation

```bash
uv add roe-ai
```

or

```bash
pip install roe-ai
```

## Quick Start

```python
from roe import RoeClient

client = RoeClient(
api_key="your-api-key",
organization_id="your-org-uuid"
organization_id="your-org-uuid",
)

# Run an existing agent
# Run an 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:
Or use environment variables:

```bash
export ROE_ORGANIZATION_API_KEY="your-api-key"
export ROE_ORGANIZATION_ID="your-org-uuid"
```

## Agent Examples

### Multimodal Extraction

Extract structured data from text and images:

```python
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
## Full Example

Extract structured information from PDFs:
Create an agent that extracts structured data from websites:

```python
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
from roe import RoeClient

Extract data from websites with automatic screenshot/HTML/markdown capture:
client = RoeClient()

```python
# Create a Web Insights agent
agent = client.agents.create(
name="Company Analyzer",
engine_class_id="URLWebsiteExtractionEngine",
Expand Down Expand Up @@ -134,128 +80,68 @@ agent = client.agents.create(
job = client.agents.run(agent_id=str(agent.id), url="https://www.roe-ai.com/")
result = job.wait()

# Print results
import json
for output in result.outputs:
print(json.dumps(json.loads(output.value), indent=2))

# Download saved references (screenshots, HTML, markdown)
for ref in result.get_references():
content = client.agents.jobs.download_reference(str(job.id), ref.resource_id)
with open(ref.resource_id, "wb") as f:
f.write(content)
```

### Interactive Web

Navigate websites and perform actions:

```python
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()
# Cleanup
client.agents.delete(str(agent.id))
```

## Running Agents
## API Reference

```python
# 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")
### Agents

# 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()
```python
client.agents.list() # List agents
client.agents.retrieve("agent-uuid") # Get agent
client.agents.create(name="...", ...) # Create agent
client.agents.update("agent-uuid", ...) # Update agent
client.agents.delete("agent-uuid") # Delete agent
client.agents.duplicate("agent-uuid") # Duplicate agent
```

## Agent Management
### Running Agents

```python
# 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
new_agent = client.agents.duplicate("uuid")
client.agents.run(agent_id, **inputs) # Async execution
client.agents.run_sync(agent_id, **inputs) # Sync execution
client.agents.run_many(agent_id, batch_inputs)# Batch execution
client.agents.run_version(agent_id, version_id, **inputs)
```

## Version Management
### Versions

```python
# 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()
client.agents.versions.list(agent_id)
client.agents.versions.retrieve(agent_id, version_id)
client.agents.versions.retrieve_current(agent_id)
client.agents.versions.create(agent_id, ...)
client.agents.versions.update(agent_id, version_id, ...)
client.agents.versions.delete(agent_id, version_id)
```

## Job Management
### Jobs

```python
# 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.retrieve_status(job_id)
client.agents.jobs.retrieve_result(job_id)
client.agents.jobs.download_reference(job_id, resource_id)
client.agents.jobs.delete_data(job_id)
```

## Supported Models

| Model | Value |
|-------|-------|
| GPT-5.2 | `gpt-5.2-2025-12-11` |
| GPT-5.1 | `gpt-5.1-2025-11-13` |
| GPT-5 | `gpt-5-2025-08-07` |
| GPT-5 Mini | `gpt-5-mini-2025-08-07` |
Expand All @@ -265,6 +151,7 @@ client.agents.jobs.delete_data(job_id)
| O3 | `o3-2025-04-16` |
| O4 Mini | `o4-mini-2025-04-16` |
| GPT-4o | `gpt-4o-2024-11-20` |
| Grok 4 | `grok-4-0709` |
| Claude Sonnet 4.5 | `claude-sonnet-4-5-20250929` |
| Claude Sonnet 4 | `claude-sonnet-4-20250514` |
| Claude 3.7 Sonnet | `claude-3-7-sonnet-20250219` |
Expand All @@ -280,7 +167,7 @@ client.agents.jobs.delete_data(job_id)
## Engine Classes

| Engine | ID |
|--------|----|
|--------|-----|
| Multimodal Extraction | `MultimodalExtractionEngine` |
| Document Insights | `PDFExtractionEngine` |
| Document Segmentation | `PDFPageSelectionEngine` |
Expand All @@ -297,5 +184,4 @@ client.agents.jobs.delete_data(job_id)
## Links

- [Roe AI](https://www.roe-ai.com/)
- [API Documentation](https://docs.roe-ai.com)
- [Examples](examples/)
- [API Docs](https://docs.roe-ai.com)
2 changes: 2 additions & 0 deletions examples/run_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ def main():

if __name__ == "__main__":
main()


2 changes: 2 additions & 0 deletions examples/update_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ def main():

if __name__ == "__main__":
main()


2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "roe-ai"
version = "0.2.0"
version = "0.2.1"
authors = [
{ name = "Roe AI", email = "founders@roe-ai.com" },
]
Expand Down
3 changes: 1 addition & 2 deletions src/roe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
)
"""

from roe.version import __version__
from roe.client import RoeClient
from roe.exceptions import (
AuthenticationError,
Expand All @@ -33,8 +34,6 @@
)
from roe.models import FileUpload

__version__ = "0.2.0"

__all__ = [
# Main client
"RoeClient",
Expand Down
3 changes: 2 additions & 1 deletion src/roe/auth.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Authentication handling for the Roe AI SDK."""

from roe.version import __version__
from roe.config import RoeConfig


Expand All @@ -22,5 +23,5 @@ def get_headers(self) -> dict[str, str]:
"""
return {
"Authorization": f"Bearer {self.config.api_key}",
"User-Agent": "roe-python/0.1.0",
"User-Agent": f"roe-python/{__version__}",
}
11 changes: 6 additions & 5 deletions src/roe/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ def from_env(
ValueError: If required parameters are missing.
"""
# Get values from parameters or environment variables
api_key = api_key or os.getenv("ROE_API_KEY")
organization_id = organization_id or os.getenv("ROE_ORGANIZATION_ID")
base_url = base_url or os.getenv("ROE_BASE_URL", "https://api.roe-ai.com")
timeout = timeout or float(os.getenv("ROE_TIMEOUT", "60.0"))
max_retries = max_retries or int(os.getenv("ROE_MAX_RETRIES", "3"))
# Use explicit None checks to allow falsy values like 0
api_key = api_key if api_key is not None else os.getenv("ROE_API_KEY")
organization_id = organization_id if organization_id is not None else os.getenv("ROE_ORGANIZATION_ID")
base_url = base_url if base_url is not None else os.getenv("ROE_BASE_URL", "https://api.roe-ai.com")
timeout = timeout if timeout is not None else float(os.getenv("ROE_TIMEOUT", "60.0"))
max_retries = max_retries if max_retries is not None else int(os.getenv("ROE_MAX_RETRIES", "3"))

if not api_key:
raise ValueError(
Expand Down
7 changes: 7 additions & 0 deletions src/roe/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ class NotFoundError(RoeAPIException):
pass


class RateLimitError(RoeAPIException):
"""429 Too Many Requests - Rate limit exceeded."""

pass


class ServerError(RoeAPIException):
"""500+ Server Error - Internal server errors."""

Expand All @@ -62,6 +68,7 @@ def get_exception_for_status_code(status_code: int) -> type[RoeAPIException]:
402: InsufficientCreditsError,
403: ForbiddenError,
404: NotFoundError,
429: RateLimitError,
}

if status_code in exception_map:
Expand Down
Loading