Skip to content

Commit 4439bc3

Browse files
Sync code blocks with latest agent-sdk examples
Updates code examples in documentation files to match current source files in the agent-sdk repository. Co-authored-by: openhands <openhands@all-hands.dev>
1 parent d6dd9e3 commit 4439bc3

5 files changed

Lines changed: 76 additions & 28 deletions

File tree

sdk/guides/agent-acp.mdx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ This example is available on GitHub: [examples/01_standalone_sdk/40_acp_agent_ex
106106
"""Example: Using ACPAgent with Claude Code ACP server.
107107
108108
This example shows how to use an ACP-compatible server (claude-code-acp)
109-
as the agent backend instead of direct LLM calls.
109+
as the agent backend instead of direct LLM calls. It also demonstrates
110+
``ask_agent()`` — a stateless side-question that forks the ACP session
111+
and leaves the main conversation untouched.
110112
111113
Prerequisites:
112114
- Node.js / npx available
@@ -122,17 +124,25 @@ from openhands.sdk.agent import ACPAgent
122124
from openhands.sdk.conversation import Conversation
123125

124126

125-
agent = ACPAgent(acp_command=["npx", "-y", "claude-code-acp"])
127+
agent = ACPAgent(acp_command=["npx", "-y", "@zed-industries/claude-code-acp"])
126128

127129
try:
128130
cwd = os.getcwd()
129131
conversation = Conversation(agent=agent, workspace=cwd)
130132

133+
# --- Main conversation turn ---
131134
conversation.send_message(
132135
"List the Python source files under openhands-sdk/openhands/sdk/agent/, "
133136
"then read the __init__.py and summarize what agent classes are exported."
134137
)
135138
conversation.run()
139+
140+
# --- ask_agent: stateless side-question via fork_session ---
141+
print("\n--- ask_agent ---")
142+
response = conversation.ask_agent(
143+
"Based on what you just saw, which agent class is the newest addition?"
144+
)
145+
print(f"ask_agent response: {response}")
136146
finally:
137147
# Clean up the ACP server subprocess
138148
agent.close()

sdk/guides/agent-delegation.mdx

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,6 @@ which then merges both analyses into a single consolidated report.
168168

169169
import os
170170

171-
from pydantic import SecretStr
172-
173171
from openhands.sdk import (
174172
LLM,
175173
Agent,
@@ -179,36 +177,32 @@ from openhands.sdk import (
179177
get_logger,
180178
)
181179
from openhands.sdk.context import Skill
180+
from openhands.sdk.subagent import register_agent
182181
from openhands.sdk.tool import register_tool
183182
from openhands.tools.delegate import (
184183
DelegateTool,
185184
DelegationVisualizer,
186-
register_agent,
187185
)
188-
from openhands.tools.preset.default import get_default_tools
186+
from openhands.tools.preset.default import get_default_tools, register_builtins_agents
189187

190188

191189
ONLY_RUN_SIMPLE_DELEGATION = False
192190

193191
logger = get_logger(__name__)
194192

195193
# Configure LLM and agent
196-
# You can get an API key from https://app.all-hands.dev/settings/api-keys
197-
api_key = os.getenv("LLM_API_KEY")
198-
assert api_key is not None, "LLM_API_KEY environment variable is not set."
199-
model = os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929")
200194
llm = LLM(
201-
model=model,
202-
api_key=SecretStr(api_key),
195+
model=os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929"),
196+
api_key=os.getenv("LLM_API_KEY"),
203197
base_url=os.environ.get("LLM_BASE_URL", None),
204198
usage_id="agent",
205199
)
206200

207201
cwd = os.getcwd()
208202

209-
register_tool("DelegateTool", DelegateTool)
210-
tools = get_default_tools(enable_browser=False)
211-
tools.append(Tool(name="DelegateTool"))
203+
tools = get_default_tools(enable_browser=True)
204+
tools.append(Tool(name=DelegateTool.name))
205+
register_builtins_agents()
212206

213207
main_agent = Agent(
214208
llm=llm,
@@ -220,7 +214,7 @@ conversation = Conversation(
220214
visualizer=DelegationVisualizer(name="Delegator"),
221215
)
222216

223-
task_message = (
217+
conversation.send_message(
224218
"Forget about coding. Let's switch to travel planning. "
225219
"Let's plan a trip to London. I have two issues I need to solve: "
226220
"Lodging: what are the best areas to stay at while keeping budget in mind? "
@@ -231,7 +225,6 @@ task_message = (
231225
"They should keep it short. After getting the results, merge both analyses "
232226
"into a single consolidated report.\n\n"
233227
)
234-
conversation.send_message(task_message)
235228
conversation.run()
236229

237230
conversation.send_message(
@@ -240,18 +233,57 @@ conversation.send_message(
240233
conversation.run()
241234

242235
# Report cost for simple delegation example
243-
cost_1 = conversation.conversation_stats.get_combined_metrics().accumulated_cost
244-
print(f"EXAMPLE_COST (simple delegation): {cost_1}")
236+
cost_simple = conversation.conversation_stats.get_combined_metrics().accumulated_cost
237+
print(f"EXAMPLE_COST (simple delegation): {cost_simple}")
245238

246239
print("Simple delegation example done!", "\n" * 20)
247240

248-
249-
# -------- Agent Delegation Second Part: User-Defined Agent Types --------
250-
251241
if ONLY_RUN_SIMPLE_DELEGATION:
242+
# For CI: always emit the EXAMPLE_COST marker before exiting.
243+
print(f"EXAMPLE_COST: {cost_simple}")
252244
exit(0)
253245

254246

247+
# -------- Agent Delegation Second Part: Built-in Agent Types (Explore + Bash) --------
248+
249+
main_agent = Agent(
250+
llm=llm,
251+
tools=[Tool(name=DelegateTool.name)],
252+
)
253+
conversation = Conversation(
254+
agent=main_agent,
255+
workspace=cwd,
256+
visualizer=DelegationVisualizer(name="Delegator (builtins)"),
257+
)
258+
259+
builtin_task_message = (
260+
"Demonstrate SDK built-in sub-agent types. "
261+
"1) Spawn an 'explore' sub-agent and ask it to list the markdown files in "
262+
"openhands-sdk/openhands/sdk/subagent/builtins/ and summarize what each "
263+
"built-in agent type is for (based on the file contents). "
264+
"2) Spawn a 'bash' sub-agent and ask it to run `python --version` in the "
265+
"terminal and return the exact output. "
266+
"3) Merge both results into a short report. "
267+
"Do not use internet access."
268+
)
269+
270+
print("=" * 100)
271+
print("Demonstrating built-in agent delegation (explore + bash)...")
272+
print("=" * 100)
273+
274+
conversation.send_message(builtin_task_message)
275+
conversation.run()
276+
277+
# Report cost for builtin agent types example
278+
cost_builtin = conversation.conversation_stats.get_combined_metrics().accumulated_cost
279+
print(f"EXAMPLE_COST (builtin agents): {cost_builtin}")
280+
281+
print("Built-in agent delegation example done!", "\n" * 20)
282+
283+
284+
# -------- Agent Delegation Third Part: User-Defined Agent Types --------
285+
286+
255287
def create_lodging_planner(llm: LLM) -> Agent:
256288
"""Create a lodging planner focused on London stays."""
257289
skills = [
@@ -349,13 +381,15 @@ conversation.send_message(
349381
conversation.run()
350382

351383
# Report cost for user-defined agent types example
352-
cost_2 = conversation.conversation_stats.get_combined_metrics().accumulated_cost
353-
print(f"EXAMPLE_COST (user-defined agents): {cost_2}")
384+
cost_user_defined = (
385+
conversation.conversation_stats.get_combined_metrics().accumulated_cost
386+
)
387+
print(f"EXAMPLE_COST (user-defined agents): {cost_user_defined}")
354388

355389
print("All done!")
356390

357391
# Full example cost report for CI workflow
358-
print(f"EXAMPLE_COST: {cost_1 + cost_2}")
392+
print(f"EXAMPLE_COST: {cost_simple + cost_builtin + cost_user_defined}")
359393
```
360394

361395
<RunExampleCode path_to_script="examples/01_standalone_sdk/25_agent_delegation.py"/>

sdk/guides/agent-server/local-server.mdx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ This example shows how to programmatically start a local agent server and intera
111111
import os
112112
import subprocess
113113
import sys
114+
import tempfile
114115
import threading
115116
import time
116117

@@ -268,7 +269,9 @@ with ManagedAPIServer(port=8001) as server:
268269

269270
# Create RemoteConversation with callbacks
270271
# NOTE: Workspace is required for RemoteConversation
271-
workspace = Workspace(host=server.base_url)
272+
# Use a temp directory that exists and is accessible in CI environments
273+
temp_workspace_dir = tempfile.mkdtemp(prefix="agent_server_demo_")
274+
workspace = Workspace(host=server.base_url, working_dir=temp_workspace_dir)
272275
result = workspace.execute_command("pwd")
273276
logger.info(
274277
f"Command '{result.command}' completed with exit code {result.exit_code}"

sdk/guides/browser-session-recording.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ browsing session.
4646
The recording will be automatically saved to the persistence directory when
4747
browser_stop_recording is called. You can replay it with:
4848
- rrweb-player: https://github.com/rrweb-io/rrweb/tree/master/packages/rrweb-player
49-
- Online viewer: https://www.rrweb.io/
49+
- Online viewer: https://www.rrweb.io/demo/
5050
"""
5151

5252
import json

sdk/guides/github-workflows/pr-review.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ jobs:
162162
- name: Run PR Review
163163
uses: ./.github/actions/pr-review
164164
with:
165-
# LLM configuration
165+
# LLM model(s) to use. Can be comma-separated for A/B testing
166+
# - one model will be randomly selected per review
166167
llm-model: anthropic/claude-sonnet-4-5-20250929
167168
llm-base-url: ''
168169
# Review style: roasted (other option: standard)

0 commit comments

Comments
 (0)