wooden-umbrella-84098
08/05/2026, 3:29 PMui_tool to claude code and other ACP agents?limited-student-10747
08/05/2026, 3:55 PMfresh-machine-37269
08/05/2026, 3:55 PMlimited-student-10747
08/05/2026, 3:55 PMfresh-machine-37269
08/05/2026, 4:05 PMui_tool (canvas_ui_control) to Claude Code / Codex / Gemini ACP agents ā and it's a fundamental ACP-design constraint, not a simple bug.
Here's the technical breakdown:
Why it doesn't work today
⢠ACPAgent.supports_openhands_tools returns False ("the ACP server manages its own toolset"). In init_state(), if self.tools is non-empty it raises NotImplementedError("ACPAgent does not support custom tools; the ACP server manages its own tools").
⢠The UI tool is a client tool (ClientToolSpec ā injected into agent.tools at conversation start). For an ACP agent that path is dead-on-arrival ā OpenHands is just a relay; the ACP server (Claude Code etc.) owns the LLM loop and its toolset. There's no hook to hand it an extra tool.
What is feasible (the realistic options)
1. Expose the UI tool as an MCP server and forward it via mcp_config. This is the cleanest path and the protocol already supports it: _mcp_config_to_acp_servers() translates OpenHands MCP servers into ACP `McpServerStdio`/`HttpMcpServer`/`SseMcpServer` objects passed to the subprocess at session creation. Claude Code, Codex, and Gemini CLI all advertise MCP capabilities, so they'd pick canvas_ui_control up as a native tool. Catch: the current executor is a no-op whose real effect is a client-side WebSocket `ActionEvent`; an MCP-server wrapper would have to bridge that ActionEvent to the frontend ā wiring work, but no protocol blocker.
2. Prompt-only instruction via agent_context. We can append text to the user message (system suffix) telling the agent to emit structured UI directives that the frontend parses. Fragile / not a real tool, so I'd treat it as a stopgap only.
Not feasible
⢠Direct tool injection (the normal `client_tools`/`tools` path). That's architecturally off the table for ACP ā the server owns its tools, and supports_openhands_tools=False is by design.
Recommendation: if this is something we want, go the MCP-server route (option 1). It's the only approach that gives the ACP agent a real callable tool and reuses the existing MCP-forwarding plumbing. The main work is building a thin MCP server around canvas_ui_control that still emits the frontend ActionEvent. Want me to scope that out in more detail?
(This reply was written by an AI agent (OpenHands) on behalf of the user.)limited-student-10747
08/05/2026, 4:21 PMfresh-machine-37269
08/05/2026, 4:21 PMfresh-machine-37269
08/05/2026, 4:50 PM