Implementation:OpenHands OpenHands SaasNestedConversationManager Create Nested Conversation
| Knowledge Sources | |
|---|---|
| Domains | Distributed_Systems, Conversation_Management |
| Last Updated | 2026-02-11 21:00 GMT |
Overview
Concrete tool for creating a conversation within a nested runtime and polling for its readiness, provided by the OpenHands enterprise conversation management layer.
Description
The _create_nested_conversation method sends an HTTP request to the nested runtime's API to create a new conversation, then delegates to _wait_for_conversation_ready to poll until the nested server confirms the conversation is operational. It constructs a ConversationInitData payload containing the conversation ID, user context, optional initial user message, and optional replay JSON.
The companion method _wait_for_conversation_ready implements a polling loop that repeatedly queries the nested server's conversation status endpoint. It uses a fixed-interval retry strategy with a bounded number of attempts. If the conversation does not reach a ready state within the allotted attempts, the method raises a timeout error.
Together, these two methods represent the final step of the conversation initiation lifecycle: after the runtime is provisioned, tokens are refreshed, and the nested server is configured, a conversation is created inside it and confirmed ready.
Usage
These are private methods called at the end of the maybe_start_agent_loop orchestration. They should not be called directly; the public entry point handles the full lifecycle including distributed locking and error recovery.
Code Reference
Source Location
- Repository: OpenHands
- File:
enterprise/server/saas_nested_conversation_manager.py - Lines: L534-575 (_create_nested_conversation), L577-591 (_wait_for_conversation_ready)
Signature
async def _create_nested_conversation(
self,
client: httpx.AsyncClient,
api_url: str,
sid: str,
user_id: str,
settings: Settings,
initial_user_msg: MessageAction | None,
replay_json: str | None,
) -> None
async def _wait_for_conversation_ready(
self,
client: httpx.AsyncClient,
api_url: str,
sid: str,
) -> None
Import
from enterprise.server.saas_nested_conversation_manager import SaasNestedConversationManager
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| client | httpx.AsyncClient | Yes | An already-instantiated async HTTP client configured with the nested server's base URL and appropriate timeouts. |
| api_url | str | Yes | The base URL of the nested runtime's HTTP API (e.g., http://runtime-conv123:8080).
|
| sid | str | Yes | The conversation session identifier that will be used as the conversation ID in the nested server. |
| user_id | str | Yes | The authenticated user identifier passed to the nested server for permission scoping. |
| settings | Settings | Yes | The application settings (with refreshed tokens) to include in the conversation initialization data. |
| initial_user_msg | None | No | The first user message to inject into the conversation. If None, the conversation starts without an initial prompt. |
| replay_json | None | No | A JSON string of previously recorded events to replay into the conversation for resumption scenarios. |
Outputs
| Name | Type | Description |
|---|---|---|
| (side effect) | None | Both methods return None. The side effect is that a conversation exists in the nested server and is confirmed ready to process agent events. Raises an exception on failure or timeout. |
Usage Examples
Basic Usage
import httpx
from openhands.events.action import MessageAction
api_url = runtime.api_url
async with httpx.AsyncClient(base_url=api_url, timeout=60.0) as client:
# Create the nested conversation with an initial message
initial_msg = MessageAction(content="Fix the login bug in auth.py")
await manager._create_nested_conversation(
client=client,
api_url=api_url,
sid="conv_abc123",
user_id="user_42",
settings=refreshed_settings,
initial_user_msg=initial_msg,
replay_json=None,
)
# At this point the nested conversation is ready
Resuming with Replay
import json
replay_data = json.dumps(saved_event_stream)
async with httpx.AsyncClient(base_url=api_url, timeout=120.0) as client:
await manager._create_nested_conversation(
client=client,
api_url=api_url,
sid="conv_abc123",
user_id="user_42",
settings=refreshed_settings,
initial_user_msg=None,
replay_json=replay_data,
)