Skip to content
Merged
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
267 changes: 267 additions & 0 deletions openhands/usage/cloud/cloud-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ The `status` field indicates the current state of the conversation startup proce
- `WORKING` - Initial processing
- `WAITING_FOR_SANDBOX` - Waiting for sandbox to be ready
- `PREPARING_REPOSITORY` - Cloning and setting up the repository
- `SETTING_UP_SKILLS` - Configuring agent skills and tools
- `READY` - Conversation is ready to use
- `ERROR` - An error occurred during startup

Expand Down Expand Up @@ -167,6 +168,272 @@ The endpoint streams a JSON array incrementally. Each element represents a statu

Each update is streamed as it occurs, allowing you to provide real-time feedback to users about the conversation startup progress.

### Checking Conversation Status

After starting a conversation, you can check its status to monitor whether the agent has completed its task.

<Note>
The examples below show basic polling patterns. For production use, add proper error handling,
exponential backoff, and handle network failures gracefully.
</Note>

#### Step 1: Check Start Task Status

When you start a conversation, you receive a start task ID. Poll this endpoint until `status` becomes `READY` and `app_conversation_id` is available:

```bash
curl -X GET "https://app.all-hands.dev/api/v1/app-conversations/start-tasks?ids=TASK_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "READY",
"app_conversation_id": "660e8400-e29b-41d4-a716-446655440001",
"sandbox_id": "sandbox-abc123"
}
```

#### Step 2: Check Conversation Execution Status

Once you have the `app_conversation_id`, check whether the agent has finished its task:

<Tabs>
<Tab title="cURL">
```bash
curl -X GET "https://app.all-hands.dev/api/v1/app-conversations?ids=CONVERSATION_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
```
</Tab>
<Tab title="Python (with requests)">
```python
import requests

api_key = "YOUR_API_KEY"
conversation_id = "YOUR_CONVERSATION_ID"

headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}

response = requests.get(
"https://app.all-hands.dev/api/v1/app-conversations",
headers=headers,
params={"ids": conversation_id}
)
response.raise_for_status() # Raise exception for HTTP errors
conversations = response.json()

if conversations:
conv = conversations[0]
print(f"Sandbox Status: {conv.get('sandbox_status')}")
print(f"Execution Status: {conv.get('execution_status')}")
else:
print("Conversation not found")
```
</Tab>
</Tabs>

**Response:**
```json
[
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"sandbox_status": "RUNNING",
"execution_status": "finished",
"selected_repository": "yourusername/your-repo",
"title": "Fix README"
}
]
```

#### Status Fields

**`sandbox_status`** - The state of the sandbox environment:
- `STARTING` - Sandbox is being created. **Action:** Continue polling.
- `RUNNING` - Sandbox is active. **Action:** Check `execution_status` for task progress.
- `PAUSED` - Sandbox is paused (due to rate limits or user action). **Action:** The sandbox will resume automatically when resources are available, or resume manually via the UI.
- `ERROR` - Sandbox encountered an error. **Action:** This is a terminal state. Check conversation details in the UI for error information.
- `MISSING` - Sandbox was deleted. **Action:** This is a terminal state. Start a new conversation if needed.

**`execution_status`** - The state of the agent's task (available when sandbox is `RUNNING`):
- `idle` - Agent is ready to receive tasks. **Action:** Continue polling if task was recently submitted.
- `running` - Agent is actively working. **Action:** Continue polling.
- `paused` - Execution is paused. **Action:** Continue polling; will resume automatically.
- `waiting_for_confirmation` - Agent is waiting for user confirmation. **Action:** This is a blocking state. The agent needs user input via the UI to proceed. Your polling loop should treat this as a terminal state or alert the user.
- `finished` - Agent has completed the task. **Action:** Terminal state. Task is done successfully.
- `error` - Agent encountered an error. **Action:** Terminal state. Check conversation in UI for error details.
- `stuck` - Agent is stuck and unable to proceed. **Action:** Terminal state. Manual intervention may be required.

<Note>
**Terminal states** that should exit your polling loop: `finished`, `error`, `stuck`, `waiting_for_confirmation`.
The `waiting_for_confirmation` state requires user action through the UI before the agent can continue.
</Note>

#### Complete Polling Example

Here's a complete example that starts a conversation and polls until completion:

```python
import requests
import time

api_key = "YOUR_API_KEY"
base_url = "https://app.all-hands.dev"

headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}

# Start a conversation
print("Starting conversation...")
start_response = requests.post(
f"{base_url}/api/v1/app-conversations",
headers=headers,
json={
"initial_message": {
"content": [{"type": "text", "text": "Your task here"}]
},
"selected_repository": "yourusername/your-repo"
}
)
start_response.raise_for_status()
start_task = start_response.json()
task_id = start_task["id"]
print(f"Start task ID: {task_id}")

# Poll start task until conversation is ready (with timeout)
conversation_id = None
max_attempts = 60 # 5 minutes with 5-second intervals
attempts = 0
while not conversation_id and attempts < max_attempts:
task_response = requests.get(
f"{base_url}/api/v1/app-conversations/start-tasks",
headers=headers,
params={"ids": task_id}
)
task_response.raise_for_status()
tasks = task_response.json()

if tasks and tasks[0].get("status") == "READY":
conversation_id = tasks[0].get("app_conversation_id")
print(f"Conversation ready: {base_url}/conversations/{conversation_id}")
elif tasks and tasks[0].get("status") == "ERROR":
print(f"Start task failed: {tasks[0].get('error', 'Unknown error')}")
exit(1)
else:
status = tasks[0].get("status") if tasks else "no response"
print(f"Start task status: {status}")
time.sleep(5)
attempts += 1

if not conversation_id:
print("Timeout waiting for conversation to start")
exit(1)

# Poll conversation until agent finishes (with timeout)
# Terminal states: finished, error, stuck, waiting_for_confirmation
max_attempts = 120 # 1 hour with 30-second intervals
attempts = 0
while attempts < max_attempts:
conv_response = requests.get(
f"{base_url}/api/v1/app-conversations",
headers=headers,
params={"ids": conversation_id}
)
conv_response.raise_for_status()
conversations = conv_response.json()

if not conversations:
print("Warning: Conversation not found")
time.sleep(30)
attempts += 1
continue

conv = conversations[0]
sandbox_status = conv.get("sandbox_status")
exec_status = conv.get("execution_status")

# Check sandbox health first
if sandbox_status in ["ERROR", "MISSING"]:
print(f"Sandbox failed with status: {sandbox_status}")
exit(1)

print(f"Execution status: {exec_status}")

# Check for terminal states
if exec_status in ["finished", "error", "stuck"]:
print(f"Conversation completed with status: {exec_status}")
break
elif exec_status == "waiting_for_confirmation":
print("Agent is waiting for user confirmation in the UI")
print(f"Visit: {base_url}/conversations/{conversation_id}")
break

time.sleep(30)
attempts += 1
else:
print("Timeout waiting for conversation to complete")
exit(1)
```

### Listing All Conversations

To list all your conversations, use the search endpoint:

<Tabs>
<Tab title="cURL">
```bash
curl -X GET "https://app.all-hands.dev/api/v1/app-conversations/search?limit=20" \
-H "Authorization: Bearer YOUR_API_KEY"
```
</Tab>
<Tab title="Python (with requests)">
```python
import requests

api_key = "YOUR_API_KEY"
headers = {"Authorization": f"Bearer {api_key}"}

response = requests.get(
"https://app.all-hands.dev/api/v1/app-conversations/search",
headers=headers,
params={"limit": 20}
)
response.raise_for_status()
result = response.json()

for conv in result.get("items", []):
print(f"ID: {conv['id']}, Status: {conv.get('execution_status')}")
```
</Tab>
</Tabs>

**Response:**
```json
{
"items": [
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"sandbox_status": "RUNNING",
"execution_status": "finished",
"selected_repository": "yourusername/your-repo",
"title": "Fix README"
}
],
"next_page_id": null
}
```

<Note>
The search endpoint returns conversations in the `items` array. Use `next_page_id`
for pagination if you have more conversations than the `limit`.
</Note>

## Rate Limits

If you have too many conversations running at once, older conversations will be paused to limit the number of concurrent conversations.
Expand Down
Loading