diff --git a/docs.json b/docs.json
index f7bc49654..b4704011e 100644
--- a/docs.json
+++ b/docs.json
@@ -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",
diff --git a/llms-full.txt b/llms-full.txt
index dc0149eaf..285d310f7 100644
--- a/llms-full.txt
+++ b/llms-full.txt
@@ -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()
@@ -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()
@@ -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()
@@ -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="API: http://runtime:8000"
+ )
+ ],
+)
+```
+
+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.
+
+
+ `client_context` is not a security boundary. It is stored with the conversation and should not contain secrets.
+
+
+## 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": "API: http://runtime:8000"
+ }
+ ],
+ "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
diff --git a/llms.txt b/llms.txt
index 73e74da8f..d6b3486cf 100644
--- a/llms.txt
+++ b/llms.txt
@@ -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
diff --git a/openapi/agent-sdk.json b/openapi/agent-sdk.json
index 166f9daed..364c006d1 100644
--- a/openapi/agent-sdk.json
+++ b/openapi/agent-sdk.json
@@ -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": [
@@ -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",
@@ -12676,4 +12684,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/sdk/api-reference/openhands.sdk.conversation.mdx b/sdk/api-reference/openhands.sdk.conversation.mdx
index b5e99911f..4266b996f 100644
--- a/sdk/api-reference/openhands.sdk.conversation.mdx
+++ b/sdk/api-reference/openhands.sdk.conversation.mdx
@@ -147,6 +147,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()
@@ -703,6 +704,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()
@@ -860,6 +862,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()
diff --git a/sdk/guides/convo-client-context.mdx b/sdk/guides/convo-client-context.mdx
new file mode 100644
index 000000000..61c4ca010
--- /dev/null
+++ b/sdk/guides/convo-client-context.mdx
@@ -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="API: http://runtime:8000"
+ )
+ ],
+)
+```
+
+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.
+
+
+ `client_context` is not a security boundary. It is stored with the conversation and should not contain secrets.
+
+
+## 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": "API: http://runtime:8000"
+ }
+ ],
+ "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.