From acf049fd114b7c124a73963c4b3328a699e3a9b6 Mon Sep 17 00:00:00 2001 From: Simon Rosenberg Date: Wed, 11 Mar 2026 17:08:48 -0300 Subject: [PATCH] Add docs for ACPAgent remote runtime example Document examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py in the ACP agent guide page. Co-Authored-By: Claude Opus 4.6 --- sdk/guides/agent-acp.mdx | 107 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/sdk/guides/agent-acp.mdx b/sdk/guides/agent-acp.mdx index 58e999d0..b693d943 100644 --- a/sdk/guides/agent-acp.mdx +++ b/sdk/guides/agent-acp.mdx @@ -159,6 +159,113 @@ cd software-agent-sdk uv run python examples/01_standalone_sdk/40_acp_agent_example.py ``` +## Remote Runtime Example + + +This example is available on GitHub: [examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py) + + +This example shows how to run an ACPAgent in a remote sandboxed environment via the Runtime API, using `APIRemoteWorkspace`: + +```python icon="python" expandable examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py +"""Example: ACPAgent with Remote Runtime via API. + +This example demonstrates running an ACPAgent (Claude Code via ACP protocol) +in a remote sandboxed environment via Runtime API. It follows the same pattern +as 04_convo_with_api_sandboxed_server.py but uses ACPAgent instead of the +default LLM-based Agent. + +Usage: + uv run examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py + +Requirements: + - LLM_BASE_URL: LiteLLM proxy URL (routes Claude Code requests) + - LLM_API_KEY: LiteLLM virtual API key + - RUNTIME_API_KEY: API key for runtime API access +""" + +import os +import time + +from openhands.sdk import ( + Conversation, + RemoteConversation, + get_logger, +) +from openhands.sdk.agent import ACPAgent +from openhands.workspace import APIRemoteWorkspace + + +logger = get_logger(__name__) + + +# ACP agents (Claude Code) route through LiteLLM proxy +llm_base_url = os.getenv("LLM_BASE_URL") +llm_api_key = os.getenv("LLM_API_KEY") +assert llm_base_url and llm_api_key, "LLM_BASE_URL and LLM_API_KEY required" + +# Set ANTHROPIC_* vars so Claude Code routes through LiteLLM +os.environ["ANTHROPIC_BASE_URL"] = llm_base_url +os.environ["ANTHROPIC_API_KEY"] = llm_api_key + +runtime_api_key = os.getenv("RUNTIME_API_KEY") +assert runtime_api_key, "RUNTIME_API_KEY required" + +# If GITHUB_SHA is set (e.g. running in CI of a PR), use that to ensure consistency +# Otherwise, use the latest image from main +server_image_sha = os.getenv("GITHUB_SHA") or "main" +server_image = f"ghcr.io/openhands/agent-server:{server_image_sha[:7]}-python-amd64" +logger.info(f"Using server image: {server_image}") + +with APIRemoteWorkspace( + runtime_api_url=os.getenv("RUNTIME_API_URL", "https://runtime.eval.all-hands.dev"), + runtime_api_key=runtime_api_key, + server_image=server_image, + image_pull_policy="Always", + target_type="binary", # CI builds binary target images + forward_env=["ANTHROPIC_BASE_URL", "ANTHROPIC_API_KEY"], +) as workspace: + agent = ACPAgent( + acp_command=["claude-agent-acp"], # Pre-installed in Docker image + ) + + received_events: list = [] + last_event_time = {"ts": time.time()} + + def event_callback(event) -> None: + received_events.append(event) + last_event_time["ts"] = time.time() + + conversation = Conversation( + agent=agent, workspace=workspace, callbacks=[event_callback] + ) + assert isinstance(conversation, RemoteConversation) + + try: + conversation.send_message( + "List the files in /workspace and describe what you see." + ) + conversation.run() + + while time.time() - last_event_time["ts"] < 2.0: + time.sleep(0.1) + + # Report cost + cost = conversation.conversation_stats.get_combined_metrics().accumulated_cost + print(f"EXAMPLE_COST: {cost:.4f}") + finally: + conversation.close() +``` + +```bash Running the Example +export LLM_BASE_URL="https://your-litellm-proxy.example.com" +export LLM_API_KEY="your-litellm-api-key" +export RUNTIME_API_KEY="your-runtime-api-key" +export RUNTIME_API_URL="https://runtime.eval.all-hands.dev" +cd software-agent-sdk +uv run python examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py +``` + ## Next Steps - **[Creating Custom Agents](/sdk/guides/agent-custom)** — Build specialized agents with custom tool sets and system prompts