Are we unable to pass the `ui_tool` to claude code...
# proj-agent-canvas
w
Are we unable to pass the
ui_tool
to claude code and other ACP agents?
l
@fresh-machine-37269 check the technical feasibility of this
šŸ‘€ 1
f
šŸ¤– On it! View progress here: oss-agent-canvas.ngrok.dev/conversations/…
l
(specifically on OpenHands/agent-canvas)
f
āœ… Done! Based on my investigation of the OpenHands SDK and ACP agent implementation, I have a complete picture. Let me provide the answer. Short answer: yes, currently we can't pass the
ui_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.)
l
@fresh-machine-37269 open an issue regarding this on the appropriate repo, including your analysis.
šŸ‘€ 1
f
šŸ¤– On it! View progress here: oss-agent-canvas.ngrok.dev/conversations/…
ā³ Still working — this is taking longer than this run allows. Follow along at the link above; mention me again for an update.