feat: implement Agent Client Protocol (ACP) server#574
feat: implement Agent Client Protocol (ACP) server#574
Conversation
- Add complete ACP implementation with JSON-RPC 2.0 transport over stdio - Implement baseline methods: initialize, authenticate, session/new, session/prompt - Map ACP session methods to existing REST API endpoints - Add comprehensive test coverage (24 tests) - Include CLI entry point for ACP server mode - Add example client and documentation - Integrate with existing ConversationService and agent infrastructure Fixes #573 Co-authored-by: openhands <openhands@all-hands.dev>
0b01887 to
b2d59dc
Compare
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
- Implemented proper event subscription using PubSub system - Added event streaming with timeout handling - Fixed PromptResponse to only include stopReason (no content field) - Added support for both string and array prompt formats - Events are now properly converted to LLM messages and streamed back - Server correctly processes JSON-RPC 2.0 requests and returns responses The server was working correctly - the issue was user sending raw JSON instead of proper JSON-RPC 2.0 format with jsonrpc/id/method/params. Co-authored-by: openhands <openhands@all-hands.dev>
Key fixes: - Added proper LLM configuration with API key detection (LITELLM_API_KEY/OPENAI_API_KEY) - Configured agent with get_default_agent() and proper tools (cli_mode=True) - Added asyncio.create_task(event_service.run()) to actually start agent processing - Fixed agent to use litellm_proxy model when LITELLM_API_KEY is available The server now sends real agent responses via streaming updates: - User sends: 'What is 2+2? Just give me the number.' - Agent responds: '4' (streamed via session/update notifications) - Final response includes stopReason: 'end_turn' Verified with test - agent gives legitimate mathematical responses. Co-authored-by: openhands <openhands@all-hands.dev>
- Add comprehensive event handling for ActionEvent and ObservationEvent - Stream tool executions (bash commands, file operations) with formatted display - Stream tool results with proper formatting and truncation - Use safe attribute access to prevent type errors - All tool events sent as agent_message_chunk sessionUpdate notifications - Verified working with test showing bash commands and results streaming correctly Co-authored-by: openhands <openhands@all-hands.dev>
… configuration - Add _llm_config storage field to OpenHandsACPAgent class - Enhance initialize() method to advertise 'llm_config' authentication capability via AuthMethod object - Implement authenticate() method to parse and validate LLM configuration from _meta field - Create _validate_llm_config() method supporting 30+ LLM parameters including: * Core: model, api_key, base_url, api_version * AWS: aws_access_key_id, aws_secret_access_key, aws_region_name * Performance: temperature, top_p, top_k, max_output_tokens, timeout * Advanced: custom_llm_provider, ollama_base_url, reasoning_effort, seed - Enhance _create_llm_from_config() method to use authenticated config with proper type handling - Maintain backward compatibility with environment variable fallback - Add 6 comprehensive test cases covering authentication scenarios, validation, and LLM creation - Add demo script showing complete authentication workflow - All 9 ACP server tests passing with proper type checking and formatting Clients can now authenticate with methodId='llm_config' and pass LLM configuration via _meta field for complete control over agent LLM behavior. Co-authored-by: openhands <openhands@all-hands.dev>
- Replace complex timeout-based event processing with direct sessionUpdate calls in event handler - Send all LLMConvertibleEvent events directly via sessionUpdate without buffering - Remove unnecessary event queue, timeout logic, and fallback handling - Cleaner, more efficient implementation that streams events immediately - Proper type checking for TextContent vs ImageContent - All tests still passing This addresses the feedback that the previous implementation with timeout loops was not ideal. Co-authored-by: openhands <openhands@all-hands.dev>
- Enhanced event streaming to send ALL LLM content including images - Added support for ContentBlock2 (image) in addition to ContentBlock1 (text) - Handle multiple image URLs from ImageContent.image_urls array - Properly distinguish between URI images (http/https) and base64 data - Send each content item as separate sessionUpdate for better streaming - Added comprehensive test for content handling with mixed text/image content - All 10 ACP server tests passing This ensures ACP clients receive complete LLM responses including any images generated or referenced by the agent, supporting the full ACP content model. Co-authored-by: openhands <openhands@all-hands.dev>
|
@OpenHands please fix the failing actions on PR #574 at branch |
|
I'm on it! xingyaoww can track my progress at all-hands.dev |
- Fix module level import placement with noqa comments - Fix line length issue by splitting long f-string - Fix incorrect attribute access (responseId -> stopReason) - Format code according to ruff standards Co-authored-by: openhands <openhands@all-hands.dev>
|
I successfully fixed the failing GitHub Actions on PR #574 for the Issues Fixed:
Verification:
The GitHub Actions should now pass, allowing the ACP implementation PR to proceed with the merge process. The fixes were minimal and targeted, addressing only the specific failing issues without affecting the core functionality. |
- Split Linux and macOS test steps to handle platform differences - Remove timeout command usage on macOS (not available by default) - Keep timeout functionality on Linux for proper process management - Both platforms still test help command and server startup Co-authored-by: openhands <openhands@all-hands.dev>
… handling - Add SessionUpdate4/SessionUpdate5 support for tool_call and tool_call_update notifications - Implement ActionEvent → tool_call mapping with proper tool kind detection - Add ObservationEvent → tool_call_update mapping with status and content handling - Support all event types: ActionEvent, ObservationEvent, UserRejectObservation, AgentErrorEvent - Add comprehensive test coverage for tool-calls functionality - Ensure proper ACP schema compliance with ToolCallContent1 and ContentBlock1 objects Co-authored-by: openhands <openhands@all-hands.dev>
- Added 5 new tests based on ACP documentation examples - test_acp_tool_call_creation_example: Verifies ActionEvent→tool_call notifications - test_acp_tool_call_update_example: Verifies ObservationEvent→tool_call_update notifications - test_acp_tool_kinds_mapping: Tests tool name to ACP kind mapping - test_acp_tool_call_error_handling: Tests error status handling - test_acp_tool_call_user_rejection: Tests user rejection handling - All tests verify actual implementation behavior matches ACP specification - Total ACP test coverage: 16 tests (all passing) - Fixed linting issues: removed unused variables, proper type handling Co-authored-by: openhands <openhands@all-hands.dev>
…sses and utilities - Reduced server.py from 607 to 296 lines (51% reduction) - Extracted 3 new modules for better maintainability: - utils.py: Tool kind mapping utilities (get_tool_kind function) - llm_config.py: LLM configuration validation and creation - events.py: EventSubscriber class with full event handling logic - Updated server.py to use extracted modules with proper imports - Fixed workspace field issue in newSession method - Updated all test imports to use new module structure - All 16 ACP tests passing, functionality preserved Co-authored-by: openhands <openhands@all-hands.dev>
- Consolidated both workflows into a single server.yml workflow - Build both agent-server and acp-server binaries for Ubuntu and macOS - Removed Windows binary builds as requested - Added binary artifact upload and consolidation logic - Updated PR description generation to include binary download links - Binaries are displayed in a table format similar to Docker images - Removed the separate acp-server.yml workflow file Co-authored-by: openhands <openhands@all-hands.dev>
- Remove llm_config.py module and use LLM class directly - Update server.py to create LLM instances directly with required service_id - Update tests to reflect new parameter storage (_llm_params instead of _llm_config) - Remove test functions for deleted utility functions - Fix line length issues for code style compliance This simplifies the codebase by using the existing LLM Pydantic model directly instead of creating wrapper utilities. Co-authored-by: openhands <openhands@all-hands.dev>
- Make authentication optional when API keys are available in environment - Only advertise authMethods when authentication is actually required - Add environment variable detection for OPENAI_API_KEY, ANTHROPIC_API_KEY, LITELLM_API_KEY - Update tests to cover both authenticated and non-authenticated scenarios - Fix 'Could not find object' error by allowing session creation without auth This resolves the ACP client compatibility issue where clients couldn't handle custom authentication methods and expected to work without auth when API keys are available. Co-authored-by: openhands <openhands@all-hands.dev>
- Enable MCP capabilities in initialize response (http=True, sse=True) - Process MCP servers from session/new requests - Convert ACP MCP server configs to OpenHands agent format - Support command-line MCP servers (McpServer3) - Log warnings for unsupported HTTP/SSE MCP servers - Add comprehensive tests for MCP functionality - Update ACP README with detailed MCP documentation Fixes #573 Co-authored-by: openhands <openhands@all-hands.dev>
…ize content, locations, and action.title property - Separate thoughts from tool calls: Send reasoning_content and thought as agent_message_chunk before tool_call - Use action.visualize and observation.visualize for rich content rendering - Extract file locations from action properties (str_replace_editor, repomix) for IDE integration - Add generalized .title property to ActionBase class (similar to .visualize pattern) - Implement .title for ExecuteBashAction: shows 'execute `command`' format with truncation - Implement .title for StrReplaceEditorAction: shows operation and filename (e.g., 'view config.py [10-20]') - Update ACP event handler to use action.title for better UI display Co-authored-by: openhands <openhands@all-hands.dev>
- Add loadSession method to load existing conversation sessions - Stream conversation history as user_message_chunk and agent_message_chunk - Handle session not found and conversation not found errors - Use correct SessionUpdate types (SessionUpdate1 for user, SessionUpdate2 for agent) - Add comprehensive tests for loadSession functionality - Enable loadSession capability in AgentCapabilities Co-authored-by: openhands <openhands@all-hands.dev>
|
@OpenHands please fix these tests: openhands/agent_server/utils.py 3 1 67% 6
|
|
I'm on it! xingyaoww can track my progress at all-hands.dev |
Co-authored-by: openhands <openhands@all-hands.dev>
SummaryI successfully fixed the failing ACP server tests that were requested. Here's what was accomplished: ✅ Request Completion Checklist
🔧 Key Changes Made1. Fixed Critical Bug in EventSubscriber Implementation
2. Updated Test Structure
📊 Results
🎯 ImpactThe fixes ensure that the Agent Client Protocol (ACP) implementation works correctly with editors like Zed, enabling proper JSON-RPC communication over stdin/stdout for the baseline methods (initialize, authenticate, session/new, session/prompt, session/cancel). All changes have been committed and pushed to the |
|
@OpenHands please fix the failing actions on PR #574 at branch |
|
I'm on it! xingyaoww can track my progress at all-hands.dev |
The ACP server module requires the agent-client-protocol package to import the ACP protocol classes. This dependency was missing from the dev dependencies, causing import failures in GitHub Actions. Co-authored-by: openhands <openhands@all-hands.dev>
Summary: Fixed Failing GitHub Actions on PR #574I successfully resolved the failing GitHub Actions on PR #574 for the ✅ Issue Identified and Resolved
✅ Changes MadeThe fix involved only two files with minimal, targeted changes:
✅ Verification Completed
✅ Changes DeployedThe fix has been committed and pushed to the PR branch. The GitHub Actions should now pass since the missing dependency has been resolved, allowing the ACP implementation to properly import all required classes from the The PR is now ready with all tests passing and builds working correctly. |
|
Looks like there are a few issues preventing this PR from being merged!
If you'd like me to help, just leave a comment, like or Feel free to include any additional details that might help me get this PR into a better state. You can manage your notification settings |
|
[Automatic Post]: It has been a while since there was any activity on this PR, are you still working on it? |
|
[Automatic Post]: It has been a while since there was any activity on this PR. @xingyaoww, are you still working on it? If so, please go ahead, if not then please request review, close it, or request that someone else follow up. |
1 similar comment
|
[Automatic Post]: It has been a while since there was any activity on this PR. @xingyaoww, are you still working on it? If so, please go ahead, if not then please request review, close it, or request that someone else follow up. |
0c776aa to
d531c4b
Compare
|
[Automatic Post]: It has been a while since there was any activity on this PR. @xingyaoww, are you still working on it? If so, please go ahead, if not then please request review, close it, or request that someone else follow up. |
1 similar comment
|
[Automatic Post]: It has been a while since there was any activity on this PR. @xingyaoww, are you still working on it? If so, please go ahead, if not then please request review, close it, or request that someone else follow up. |
|
This is already implemented in OpenHands/OpenHands-CLI |



Update: ACP changes has been moved to https://github.com/All-Hands-AI/OpenHands/pull/11226/files
This PR only contains the core SDK changes
Agent Server images for this PR
• GHCR package: https://github.com/All-Hands-AI/agent-sdk/pkgs/container/agent-server
Variants & Base Images
golang:1.21-bookwormeclipse-temurin:17-jdknikolaik/python-nodejs:python3.12-nodejs22Pull (multi-arch manifest)
Run
All tags pushed for this build
The
79fac09tag is a multi-arch manifest (amd64/arm64); your client pulls the right arch automatically.