-
Notifications
You must be signed in to change notification settings - Fork 217
Enable ACPAgent on RemoteRuntime API #2190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
591485b
Enable ACPAgent on RemoteRuntime API
simonrosenberg a01d2d8
Fix Dockerfile: conditional npm install for non-Node.js base images
simonrosenberg 2fe2ffc
Fix CI: renumber duplicate example, add kind discriminator to test pa…
simonrosenberg aa3bad9
Fix example: use binary target type to match CI-built images
simonrosenberg dd7737b
Fix line length in AgentBase.close() docstring
simonrosenberg c5ef4e0
Add agent_type parameter to run-eval workflow
simonrosenberg dfcf0a5
Fix Dockerfile: install Node.js when base image lacks npm
simonrosenberg d72fd08
feat(acp): emit FinishAction at end of each step
simonrosenberg fb04adc
fix: add managed settings for Claude Code headless permissions
simonrosenberg 9910c88
fix: set bypassPermissions mode for ACPAgent sessions
simonrosenberg 397535f
fix(acp): add timeout to prompt() to prevent indefinite hangs
simonrosenberg 297d31c
fix(acp): increase StreamReader limit to prevent readline deadlock
simonrosenberg 6337423
feat: add Codex ACP support to ACPAgent and eval pipeline
simonrosenberg dfef936
fix: add ACP authenticate step for codex-acp
simonrosenberg 3d9803a
rename agent_type 'acp' to 'acp-claude' for consistency
simonrosenberg 7633846
feat(acp): record response latency and expose agent metadata
simonrosenberg b9c42fd
fix(acp): resolve bypass mode for claude-agent-acp
simonrosenberg c153e80
chore: rename claude-code-acp to claude-agent-acp
simonrosenberg 33aef1b
Merge branch 'main' into feat/acp-remote-runtime
simonrosenberg d23c4dc
keep main branch behavior - dont add await
simonrosenberg ae237b1
Merge branch 'main' into feat/acp-remote-runtime
simonrosenberg b71276c
Add Laminar tracing support for ACPAgent
simonrosenberg cab3618
fix(acp): add claude-login auth method for ACP 0.20.0 compatibility
simonrosenberg 01cf831
revert(acp): remove claude-login from auth method map
simonrosenberg ee5f610
Merge remote-tracking branch 'origin/main' into feat/acp-remote-runtime
simonrosenberg 8a508e1
fix(ci): add kind discriminator to test payloads and fix formatting
simonrosenberg 47a80d5
Merge branch 'main' into feat/acp-remote-runtime
simonrosenberg 63565b9
fix(ci): fix ruff lint errors in api.py and example file
simonrosenberg 848fa92
Route ACP agents through LiteLLM proxy in CI
simonrosenberg 2dd52ae
Add EXAMPLE_COST markers to ACP examples
simonrosenberg 0c4d9cb
Update ACP examples to use LiteLLM routing
simonrosenberg 44f69a9
fix(acp): emit ConversationErrorEvent and re-raise on prompt failure
simonrosenberg e096099
Merge branch 'main' into feat/acp-remote-runtime
simonrosenberg f131e90
Add acp_model field to ACPAgent for model passthrough via _meta
simonrosenberg 524e918
fix: pass _meta content as kwargs to avoid double-nesting
simonrosenberg 0b41c05
Fix test_step_error_sets_error_status to match re-raise behavior
simonrosenberg 3081956
fix: skip LLM-based title generation for ACP agents
simonrosenberg bda77a6
feat(acp): add retry logic for transient connection errors
simonrosenberg fade5af
Fix ruff-format: wrap long assert line in test_acp_agent.py
simonrosenberg 0f438b5
Merge branch 'main' into feat/acp-remote-runtime
simonrosenberg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
examples/02_remote_agent_server/09_acp_agent_with_remote_runtime.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| """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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.