Skip to content
Draft
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
1 change: 1 addition & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@
"sdk/guides/convo-fork",
"sdk/guides/convo-pause-and-resume",
"sdk/guides/convo-custom-visualizer",
"sdk/guides/convo-client-context",
"sdk/guides/convo-send-message-while-running",
"sdk/guides/convo-async",
"sdk/guides/convo-ask-agent",
Expand Down
53 changes: 53 additions & 0 deletions llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ Send a message to the agent.
message origin in multi-agent scenarios. For example, when
one agent delegates to another, the sender can be set to
identify which agent is sending the message.
* `client_context` – Hidden context appended to the message for LLM input.

#### abstractmethod set_confirmation_policy()

Expand Down Expand Up @@ -1061,6 +1062,7 @@ Send a message to the agent.
message origin in multi-agent scenarios. For example, when
one agent delegates to another, the sender can be set to
identify which agent is sending the message.
* `client_context` – Hidden context appended to the message for LLM input.

#### set_confirmation_policy()

Expand Down Expand Up @@ -1218,6 +1220,7 @@ Send a message to the agent.
message origin in multi-agent scenarios. For example, when
one agent delegates to another, the sender can be set to
identify which agent is sending the message.
* `client_context` – Hidden context appended to the message for LLM input.

#### set_confirmation_policy()

Expand Down Expand Up @@ -14754,6 +14757,56 @@ Now that you understand custom visualizers, explore these related topics:
- **[Send Messages While Running](/sdk/guides/convo-send-message-while-running)** - Interactive conversations with real-time updates
- **[Pause and Resume](/sdk/guides/convo-pause-and-resume)** - Control agent execution flow with custom logic

### Client Message Context
Source: https://docs.openhands.dev/sdk/guides/convo-client-context.md

Use `client_context` when an SDK client needs to provide current environment details with a user turn. The context is persisted in the user `MessageEvent.extended_content` and included when that event is converted to LLM input. The original message content remains separate.

```python
from openhands.sdk import TextContent

conversation.send_message(
"Inspect the running services.",
client_context=[
TextContent(
text="<RUNTIME_SERVICES>API: http://runtime:8000</RUNTIME_SERVICES>"
)
],
)
```

This is useful for context owned by the client rather than the agent configuration, such as:

- Runtime URLs that may change after a conversation moves.
- UI capabilities available for the current session.
- Workspace or deployment metadata relevant to the next turn.

Attach the context to the first applicable user message. If the environment changes later, attach the updated context to the next user message.

<Warning>
`client_context` is not a security boundary. It is stored with the conversation and should not contain secrets.
</Warning>

## Remote Agent Server

The same field is available on the initial message in `POST /api/conversations` and on later messages in `POST /api/conversations/{conversation_id}/events`:

```json
{
"role": "user",
"content": [{ "type": "text", "text": "Inspect the running services." }],
"client_context": [
{
"type": "text",
"text": "<RUNTIME_SERVICES>API: http://runtime:8000</RUNTIME_SERVICES>"
}
],
"run": true
}
```

The server maps `client_context` to `MessageEvent.extended_content`. Consumers that render the visible message should continue to use `MessageEvent.llm_message.content`; LLM conversion includes both fields.

### Fork a Conversation
Source: https://docs.openhands.dev/sdk/guides/convo-fork.md

Expand Down
1 change: 1 addition & 0 deletions llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ from the OpenHands Software Agent SDK.
- [Assign Reviews](https://docs.openhands.dev/sdk/guides/github-workflows/assign-reviews.md): Automate PR management with intelligent reviewer assignment and workflow notifications using OpenHands Agent
- [Browser Session Recording](https://docs.openhands.dev/sdk/guides/browser-session-recording.md): Record and replay your agent's browser sessions using rrweb.
- [Browser Use](https://docs.openhands.dev/sdk/guides/agent-browser-use.md): Enable web browsing and interaction capabilities for your agent.
- [Client Message Context](https://docs.openhands.dev/sdk/guides/convo-client-context.md): Attach client-generated context to a user message without changing its visible content.
- [Condenser](https://docs.openhands.dev/sdk/arch/condenser.md): High-level architecture of the conversation history compression system
- [Context Condenser](https://docs.openhands.dev/sdk/guides/context-condenser.md): Manage agent memory by condensing conversation history to save tokens.
- [Conversation](https://docs.openhands.dev/sdk/arch/conversation.md): High-level architecture of the conversation orchestration system
Expand Down
12 changes: 10 additions & 2 deletions openapi/agent-sdk.json
Original file line number Diff line number Diff line change
Expand Up @@ -9137,7 +9137,7 @@
},
"type": "array",
"title": "Extended Content",
"description": "List of content added by agent context"
"description": "Hidden context appended to the message for LLM input"
},
"sender": {
"anyOf": [
Expand Down Expand Up @@ -10548,6 +10548,14 @@
"type": "array",
"title": "Content"
},
"client_context": {
"items": {
"$ref": "#/components/schemas/TextContent"
},
"type": "array",
"title": "Client Context",
"description": "Hidden client context appended to the message for LLM input"
},
"run": {
"type": "boolean",
"title": "Run",
Expand Down Expand Up @@ -12676,4 +12684,4 @@
}
}
}
}
}
3 changes: 3 additions & 0 deletions sdk/api-reference/openhands.sdk.conversation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

Initialize the base conversation with span tracking.

#### abstractmethod ask_agent()

Check warning on line 36 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L36

Did you really mean 'abstractmethod'?

Ask the agent a simple, stateless question and get a direct LLM response.

Expand All @@ -48,18 +48,18 @@
* Returns:
A string response from the agent

#### abstractmethod close()

Check warning on line 51 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L51

Did you really mean 'abstractmethod'?

#### static compose_callbacks()

Compose multiple callbacks into a single callback function.

* Parameters:
`callbacks` – An iterable of callback functions

Check warning on line 58 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L58

Did you really mean 'iterable'?
* Returns:
A single callback function that calls all provided callbacks

#### abstractmethod condense()

Check warning on line 62 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L62

Did you really mean 'abstractmethod'?

Force condensation of the conversation history.

Expand All @@ -74,7 +74,7 @@
`ValueError` – If no condenser is configured or the condenser doesn’t
handle condensation requests.

#### abstractmethod execute_tool()

Check warning on line 77 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L77

Did you really mean 'abstractmethod'?

Execute a tool directly without going through the agent loop.

Expand All @@ -92,7 +92,7 @@
- Testing tool behavior outside the agent loop

* Parameters:
* `tool_name` – The name of the tool to execute (e.g., “sleeptime_compute”)

Check warning on line 95 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L95

Did you really mean 'sleeptime_compute'?
* `action` – The action to pass to the tool executor
* Returns:
The observation returned by the tool execution
Expand All @@ -100,7 +100,7 @@
* `KeyError` – If the tool is not found in the agent’s tools
* `NotImplementedError` – If the tool has no executor

#### abstractmethod generate_title()

Check warning on line 103 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L103

Did you really mean 'abstractmethod'?

Generate a title for the conversation based on the first user message.

Expand All @@ -125,18 +125,18 @@
String path to the conversation-specific persistence directory.
Always returns a normalized string path even if a Path was provided.

#### abstractmethod pause()

Check warning on line 128 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L128

Did you really mean 'abstractmethod'?

#### abstractmethod reject_pending_actions()

Check warning on line 130 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L130

Did you really mean 'abstractmethod'?

#### abstractmethod run()

Check warning on line 132 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L132

Did you really mean 'abstractmethod'?

Execute the agent to process messages and perform actions.

This method runs the agent until it finishes processing the current
message or reaches the maximum iteration limit.

#### abstractmethod send_message()

Check warning on line 139 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L139

Did you really mean 'abstractmethod'?

Send a message to the agent.

Expand All @@ -147,16 +147,17 @@
message origin in multi-agent scenarios. For example, when
one agent delegates to another, the sender can be set to
identify which agent is sending the message.
* `client_context` – Hidden context appended to the message for LLM input.

#### abstractmethod set_confirmation_policy()

Check warning on line 152 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L152

Did you really mean 'abstractmethod'?

Set the confirmation policy for the conversation.

#### abstractmethod set_security_analyzer()

Check warning on line 156 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L156

Did you really mean 'abstractmethod'?

Set the security analyzer for the conversation.

#### abstractmethod update_secrets()

Check warning on line 160 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L160

Did you really mean 'abstractmethod'?

### class Conversation

Expand Down Expand Up @@ -212,7 +213,7 @@

#### STUCK = 'stuck'

#### WAITING_FOR_CONFIRMATION = 'waiting_for_confirmation'

Check warning on line 216 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L216

Did you really mean 'waiting_for_confirmation'?

#### is_terminal()

Expand Down Expand Up @@ -276,7 +277,7 @@

Persistently record a hook-blocked user message.

#### classmethod create()

Check warning on line 280 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L280

Did you really mean 'classmethod'?

Create a new conversation state or resume from persistence.

Expand All @@ -284,14 +285,14 @@
from persisted state.

New conversation:
The provided Agent is used directly. Pydantic validation happens via the

Check warning on line 288 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L288

Did you really mean 'Pydantic'?
cls() constructor.

Restored conversation:
The provided Agent is validated against the persisted agent using
agent.load(). Tools must match (they may have been used in conversation
history), but all other configuration can be freely changed: LLM,
agent_context, condenser, system prompts, etc.

Check warning on line 295 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L295

Did you really mean 'agent_context'?

* Parameters:
* `id` – Unique conversation identifier
Expand All @@ -308,7 +309,7 @@
ConversationState ready for use
* Raises:
* `ValueError` – If conversation ID or tools mismatch on restore
* `ValidationError` – If agent or other fields fail Pydantic validation

Check warning on line 312 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L312

Did you really mean 'Pydantic'?

#### static get_unmatched_actions()

Expand All @@ -328,7 +329,7 @@

Return True if the lock is currently held by any thread.

#### model_config = (configuration object)

Check warning on line 332 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L332

Did you really mean 'model_config'?

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Expand Down Expand Up @@ -383,12 +384,12 @@
1. Create a visualizer instance:

viz = MyVisualizer()
1. Pass it to Conversation: conv = Conversation(agent, visualizer=viz)

Check warning on line 387 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L387

Did you really mean 'conv'?
2. Conversation automatically calls viz.initialize(state) to attach the state

You can also pass the uninstantiated class if you don’t need extra args

Check warning on line 390 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L390

Did you really mean 'uninstantiated'?
: for initialization, and Conversation will create it:
: conv = Conversation(agent, visualizer=MyVisualizer)

Check warning on line 392 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L392

Did you really mean 'conv'?

Conversation will then calls MyVisualizer() followed by initialize(state)

Expand Down Expand Up @@ -435,7 +436,7 @@
* Parameters:
`state` – The conversation state object

#### abstractmethod on_event()

Check warning on line 439 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L439

Did you really mean 'abstractmethod'?

Handle a conversation event.

Expand Down Expand Up @@ -499,11 +500,11 @@

#### get_id()

Return the event_id for a given index.

Check warning on line 503 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L503

Did you really mean 'event_id'?

#### get_index()

Return the integer index for a given event_id.

Check warning on line 507 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L507

Did you really mean 'event_id'?

### class EventsListBase

Expand All @@ -516,7 +517,7 @@

#### Methods

#### abstractmethod append()

Check warning on line 520 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L520

Did you really mean 'abstractmethod'?

Add a new event to the list.

Expand All @@ -531,7 +532,7 @@
- `delete_on_close`: bool = True
- `id`: UUID
Get the unique ID of the conversation.
- `llm_registry`: LLMRegistry

Check warning on line 535 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L535

Did you really mean 'LLMRegistry'?
- `max_iteration_per_run`: int
- `resolved_plugins`: list[ResolvedPluginSource] | None
Get the resolved plugin sources after plugins are loaded.
Expand Down Expand Up @@ -560,15 +561,15 @@
Can be a string path, Path object, or LocalWorkspace instance.
* `plugins` – Optional list of plugins to load. Each plugin is specified
with a source (github:owner/repo, git URL, or local path),
optional ref (branch/tag/commit), and optional repo_path for

Check warning on line 564 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L564

Did you really mean 'repo_path'?
monorepos. Plugins are loaded in order with these merge

Check warning on line 565 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L565

Did you really mean 'monorepos'?
semantics: skills override by name (last wins), MCP config
override by key (last wins), hooks concatenate (all run).
* `persistence_dir` – Directory for persisting conversation state and events.
Can be a string path or Path object.
* `conversation_id` – Optional ID for the conversation. If provided, will
be used to identify the conversation. The user might want to
suffix their persistent filestore with this ID.

Check warning on line 572 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L572

Did you really mean 'filestore'?
* `callbacks` – Optional list of callback functions to handle events
* `token_callbacks` – Optional list of callbacks invoked for streaming deltas
* `hook_config` – Optional hook configuration to auto-wire session hooks.
Expand All @@ -584,8 +585,8 @@
* `stuck_detection` – Whether to enable stuck detection
* `stuck_detection_thresholds` – Optional configuration for stuck detection
thresholds. Can be a StuckDetectionThresholds instance or
a dict with keys: ‘action_observation’, ‘action_error’,

Check warning on line 588 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L588

Did you really mean 'action_observation'?

Check warning on line 588 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L588

Did you really mean 'action_error'?
‘monologue’, ‘alternating_pattern’. Values are integers

Check warning on line 589 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L589

Did you really mean 'alternating_pattern'?
representing the number of repetitions before triggering.
* `cipher` – Optional cipher for encrypting/decrypting secrets in persisted
state. If provided, secrets are encrypted when saving and
Expand Down Expand Up @@ -620,7 +621,7 @@

Raises ValueError if no compatible condenser exists.

#### property conversation_stats

Check warning on line 624 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L624

Did you really mean 'conversation_stats'?

#### execute_tool()

Expand All @@ -640,7 +641,7 @@
- Testing tool behavior outside the agent loop

* Parameters:
* `tool_name` – The name of the tool to execute (e.g., “sleeptime_compute”)

Check warning on line 644 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L644

Did you really mean 'sleeptime_compute'?
* `action` – The action to pass to the tool executor
* Returns:
The observation returned by the tool execution
Expand Down Expand Up @@ -677,7 +678,7 @@
Reject all pending actions from the agent.

This is a non-invasive method to reject actions between run() calls.
Also clears the agent_waiting_for_confirmation flag.

Check warning on line 681 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L681

Did you really mean 'agent_waiting_for_confirmation'?

#### run()

Expand All @@ -703,6 +704,7 @@
message origin in multi-agent scenarios. For example, when
one agent delegates to another, the sender can be set to
identify which agent is sending the message.
* `client_context` – Hidden context appended to the message for LLM input.

#### set_confirmation_policy()

Expand All @@ -717,8 +719,8 @@
Add secrets to the conversation.

* Parameters:
`secrets` – Dictionary mapping secret keys to values or no-arg callables.

Check warning on line 722 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L722

Did you really mean 'callables'?
SecretValue = str | Callable[[], str]. Callables are invoked lazily

Check warning on line 723 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L723

Did you really mean 'Callables'?
when a command references the secret key.

### class RemoteConversation
Expand Down Expand Up @@ -746,15 +748,15 @@
* `agent` – Agent configuration (will be sent to the server)
* `workspace` – The working directory for agent operations and tool execution.
* `plugins` – Optional list of plugins to load on the server. Each plugin
is a PluginSource specifying source, ref, and repo_path.

Check warning on line 751 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L751

Did you really mean 'repo_path'?
* `conversation_id` – Optional existing conversation id to attach to
* `callbacks` – Optional callbacks to receive events (not yet streamed)
* `max_iteration_per_run` – Max iterations configured on server
* `stuck_detection` – Whether to enable stuck detection on server
* `stuck_detection_thresholds` – Optional configuration for stuck detection
thresholds. Can be a StuckDetectionThresholds instance or
a dict with keys: ‘action_observation’, ‘action_error’,

Check warning on line 758 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L758

Did you really mean 'action_observation'?

Check warning on line 758 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L758

Did you really mean 'action_error'?
‘monologue’, ‘alternating_pattern’. Values are integers

Check warning on line 759 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L759

Did you really mean 'alternating_pattern'?
representing the number of repetitions before triggering.
* `hook_config` – Optional hook configuration for session hooks
* `visualizer` –
Expand Down Expand Up @@ -803,7 +805,7 @@
* Raises:
`HTTPError` – If the server returns an error (e.g., no condenser configured).

#### property conversation_stats

Check warning on line 808 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L808

Did you really mean 'conversation_stats'?

#### execute_tool()

Expand All @@ -825,7 +827,7 @@
Generate a title for the conversation based on the first user message.

* Parameters:
* `llm` – Optional LLM to use for title generation. If provided, its usage_id

Check warning on line 830 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L830

Did you really mean 'usage_id'?
will be sent to the server. If not provided, uses the agent’s LLM.
* `max_length` – Maximum length of the generated title.
* Returns:
Expand Down Expand Up @@ -860,6 +862,7 @@
message origin in multi-agent scenarios. For example, when
one agent delegates to another, the sender can be set to
identify which agent is sending the message.
* `client_context` – Hidden context appended to the message for LLM input.

#### set_confirmation_policy()

Expand All @@ -869,7 +872,7 @@

Set the security analyzer for the remote conversation.

#### property stuck_detector

Check warning on line 875 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L875

Did you really mean 'stuck_detector'?

Stuck detector for compatibility.
Not implemented for remote conversations.
Expand All @@ -890,7 +893,7 @@
Secret sources will redact / encrypt their sensitive values as appropriate when
serializing, depending on the content of the context. If a context is present
and contains a ‘cipher’ object, this is used for encryption. If it contains a
boolean ‘expose_secrets’ flag set to True, secrets are dunped in plain text.

Check warning on line 896 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L896

Did you really mean 'expose_secrets'?

Check warning on line 896 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L896

Did you really mean 'dunped'?
Otherwise secrets are redacted.

Additionally, it tracks the latest exported values to enable consistent masking
Expand Down Expand Up @@ -926,14 +929,14 @@
Mask secret values in the given text.

This method uses both the current exported values and attempts to get
fresh values from callables to ensure comprehensive masking.

Check warning on line 932 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L932

Did you really mean 'callables'?

* Parameters:
`text` – The text to mask secrets in
* Returns:
Text with secret values replaced by `<secret-hidden>`

#### model_config = (configuration object)

Check warning on line 939 in sdk/api-reference/openhands.sdk.conversation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/api-reference/openhands.sdk.conversation.mdx#L939

Did you really mean 'model_config'?

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Expand Down
51 changes: 51 additions & 0 deletions sdk/guides/convo-client-context.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: Client Message Context
description: Attach client-generated context to a user message without changing its visible content.
---

Use `client_context` when an SDK client needs to provide current environment details with a user turn. The context is persisted in the user `MessageEvent.extended_content` and included when that event is converted to LLM input. The original message content remains separate.

```python
from openhands.sdk import TextContent

conversation.send_message(
"Inspect the running services.",
client_context=[
TextContent(
text="<RUNTIME_SERVICES>API: http://runtime:8000</RUNTIME_SERVICES>"
)
],
)
```

This is useful for context owned by the client rather than the agent configuration, such as:

- Runtime URLs that may change after a conversation moves.
- UI capabilities available for the current session.
- Workspace or deployment metadata relevant to the next turn.

Attach the context to the first applicable user message. If the environment changes later, attach the updated context to the next user message.

<Warning>
`client_context` is not a security boundary. It is stored with the conversation and should not contain secrets.
</Warning>

## Remote Agent Server

The same field is available on the initial message in `POST /api/conversations` and on later messages in `POST /api/conversations/{conversation_id}/events`:

```json
{
"role": "user",
"content": [{ "type": "text", "text": "Inspect the running services." }],
"client_context": [

Check warning on line 41 in sdk/guides/convo-client-context.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

sdk/guides/convo-client-context.mdx#L41

Did you really mean 'client_context'?
{
"type": "text",
"text": "<RUNTIME_SERVICES>API: http://runtime:8000</RUNTIME_SERVICES>"
}
],
"run": true
}
```

The server maps `client_context` to `MessageEvent.extended_content`. Consumers that render the visible message should continue to use `MessageEvent.llm_message.content`; LLM conversion includes both fields.
Loading