Principle:OpenHands OpenHands Nested Conversation Creation
| Knowledge Sources | |
|---|---|
| Domains | Distributed_Systems, Conversation_Management |
| Last Updated | 2026-02-11 21:00 GMT |
Overview
Nested conversation creation is the process of initiating a conversation within an already-provisioned nested runtime server and waiting for that conversation to reach a ready state before handing control to the agent loop.
Description
After a nested runtime server has been provisioned and configured, the orchestrator must create a conversation inside that nested server. This is distinct from the outer conversation (managed by the orchestrator) -- the nested conversation is the inner server's representation of the agent session, with its own event stream, agent state machine, and workspace.
The creation process involves two phases:
- Initiation -- The orchestrator sends a request to the nested server to create a new conversation, passing initialization data (conversation ID, user context, initial message, replay data).
- Readiness polling -- The nested server may need time to set up the conversation (loading the agent, initializing the workspace, replaying events). The orchestrator polls a readiness endpoint until the conversation reports itself as ready or a timeout is exceeded.
This two-phase approach decouples the request to create from the confirmation of readiness, which is important because conversation initialization can take variable amounts of time depending on workspace size and replay length.
Usage
Use nested conversation creation:
- As the final step in the conversation initiation lifecycle, after runtime provisioning, token refresh, and server configuration.
- When resuming a conversation that was previously suspended -- the nested server must recreate the conversation from its persisted state.
Theoretical Basis
This pattern follows the async resource readiness model: a create request returns immediately, and the caller polls for readiness with exponential backoff.
Pseudocode:
function create_nested_conversation(client, api_url, conversation_id, init_data):
# Phase 1: Initiate conversation creation
response = client.post(
api_url + "/api/conversations",
json={
"conversation_id": conversation_id,
"initial_message": init_data.initial_message,
"replay_json": init_data.replay_json,
"user_id": init_data.user_id,
},
)
assert response.status_code in (200, 201, 202)
# Phase 2: Poll for readiness
wait_for_conversation_ready(client, api_url, conversation_id)
function wait_for_conversation_ready(client, api_url, conversation_id):
max_attempts = MAX_POLL_ATTEMPTS
delay = INITIAL_POLL_DELAY
for attempt in range(max_attempts):
response = client.get(
api_url + "/api/conversations/" + conversation_id + "/status"
)
if response.json()["status"] == "ready":
return
sleep(delay)
delay = min(delay * BACKOFF_FACTOR, MAX_POLL_DELAY)
raise TimeoutError("Conversation did not become ready within timeout")
Key invariants:
- Bounded waiting -- The polling loop has a maximum number of attempts and a maximum delay cap to prevent indefinite blocking.
- Idempotent creation -- If the creation request is retried (e.g., due to a transient network error), the nested server must handle the duplicate gracefully, either by returning the existing conversation or by being truly idempotent.
- Backoff discipline -- The polling interval increases with each attempt to avoid overwhelming the nested server during slow initializations.