Skip to content

Comments

Add ask_agent support to ACPAgent via fork_session#2145

Merged
simonrosenberg merged 1 commit intomainfrom
feat/acp-agent-ask-agent
Feb 21, 2026
Merged

Add ask_agent support to ACPAgent via fork_session#2145
simonrosenberg merged 1 commit intomainfrom
feat/acp-agent-ask-agent

Conversation

@simonrosenberg
Copy link
Collaborator

@simonrosenberg simonrosenberg commented Feb 20, 2026

The ask_agent API (stateless question answering) failed for ACPAgent because its sentinel LLM can't make real LLM calls. This uses the ACP protocol's fork_session to create a temporary copy of the session, prompt it, collect the response, and discard the fork — preserving read-only semantics.

  • Add AgentBase.ask_agent() default method (returns None → use LLM path)
  • Override in ACPAgent with fork_session logic + token usage tracking
  • Add fork text routing in _OpenHandsACPClient.session_update()
  • Dispatch agent override in LocalConversation.ask_agent()
  • Add 7 tests for ask_agent and fork text routing

Summary

[fill in a summary of this PR]

Checklist

  • If the PR is changing/adding functionality, are there tests to reflect this?
  • If there is an example, have you run the example to make sure that it works?
  • If there are instructions on how to run the code, have you followed the instructions and made sure that it works?
  • If the feature is significant enough to require documentation, is there a PR open on the OpenHands/docs repository with the same branch name?
  • Is the github CI passing?

Agent Server images for this PR

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python amd64, arm64 nikolaik/python-nodejs:python3.12-nodejs22 Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:0729c45-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-0729c45-python \
  ghcr.io/openhands/agent-server:0729c45-python

All tags pushed for this build

ghcr.io/openhands/agent-server:0729c45-golang-amd64
ghcr.io/openhands/agent-server:0729c45-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:0729c45-golang-arm64
ghcr.io/openhands/agent-server:0729c45-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:0729c45-java-amd64
ghcr.io/openhands/agent-server:0729c45-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:0729c45-java-arm64
ghcr.io/openhands/agent-server:0729c45-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:0729c45-python-amd64
ghcr.io/openhands/agent-server:0729c45-nikolaik_s_python-nodejs_tag_python3.12-nodejs22-amd64
ghcr.io/openhands/agent-server:0729c45-python-arm64
ghcr.io/openhands/agent-server:0729c45-nikolaik_s_python-nodejs_tag_python3.12-nodejs22-arm64
ghcr.io/openhands/agent-server:0729c45-golang
ghcr.io/openhands/agent-server:0729c45-java
ghcr.io/openhands/agent-server:0729c45-python

About Multi-Architecture Support

  • Each variant tag (e.g., 0729c45-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 0729c45-python-amd64) are also available if needed

@github-actions
Copy link
Contributor

github-actions bot commented Feb 20, 2026

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-sdk/openhands/sdk/agent
   acp_agent.py2735480%113–115, 165–168, 170–171, 181–182, 184, 195–196, 201, 268, 329–330, 351, 361, 366, 377–380, 393–395, 398–400, 402, 404–405, 407, 409, 414, 422–423, 427–428, 432, 439, 442–443, 445, 447–449, 484, 488–489, 600–601
   base.py1911990%200, 289, 293–297, 345–347, 357, 367, 375–376, 486, 523–524, 534–535
openhands-sdk/openhands/sdk/conversation/impl
   local_conversation.py3321994%277, 282, 310, 375, 417, 563–564, 567, 713, 721, 723, 734, 736–738, 763, 925, 932–933
TOTAL18599562369% 

@simonrosenberg simonrosenberg force-pushed the feat/acp-agent branch 4 times, most recently from d5c43b1 to 506a50a Compare February 20, 2026 19:28
Base automatically changed from feat/acp-agent to main February 20, 2026 22:06
@simonrosenberg simonrosenberg force-pushed the feat/acp-agent-ask-agent branch from 684bc6e to 39f6a03 Compare February 20, 2026 22:25
@simonrosenberg simonrosenberg marked this pull request as ready for review February 20, 2026 22:26
Copy link
Collaborator

@all-hands-bot all-hands-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Good taste - Clean solution that leverages fork_session to implement stateless Q&A. The design is pragmatic: uses the protocol's native capability rather than fighting the sentinel LLM limitation. Session-based routing keeps concerns separated (client handles dispatch, agent handles business logic). Well-tested with comprehensive coverage of error cases, token tracking, and cleanup. LGTM! 👍

@simonrosenberg simonrosenberg force-pushed the feat/acp-agent-ask-agent branch 2 times, most recently from d1a3a65 to 8788f63 Compare February 20, 2026 22:32
Copy link
Collaborator

@malhotra5 malhotra5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@simonrosenberg
Copy link
Collaborator Author

simonrosenberg commented Feb 20, 2026

@malhotra5 will make an issue to see if ask_agent on the the agent class itself could make sense and have it do fork + regular question answering
but perhaps its over-engineering it for nothing (we only have 2 agent classes anyway...)

@simonrosenberg simonrosenberg force-pushed the feat/acp-agent-ask-agent branch from 8788f63 to 12daf31 Compare February 20, 2026 23:01
@simonrosenberg
Copy link
Collaborator Author

@OpenHands /codereview-roasted read the PR diff

@openhands-ai
Copy link

openhands-ai bot commented Feb 20, 2026

I'm on it! simonrosenberg can track my progress at all-hands.dev

@openhands-ai
Copy link

openhands-ai bot commented Feb 20, 2026

Summary

I performed a Linus Torvalds-style code review of PR #2145 "Add ask_agent support to ACPAgent via fork_session" as requested with /codereview-roasted.

Review Verdict: 🟡 Acceptable - ✅ Worth Merging

The PR solves a real problem correctly: ACPAgent's sentinel LLM can't make real LLM calls, so using the ACP protocol's fork_session to implement ask_agent() is the right architectural approach.

Key Feedback Provided:

Critical Issues:

  1. _record_usage uses hasattr/Any typing - Should properly type the response rather than duck-typing defensively
  2. Magic double-sleep for notification draining - Hardcoded timing (await asyncio.sleep(0) + _NOTIFICATION_DRAIN_DELAY) is fragile; needs documentation or a proper protocol-level drain mechanism

Improvement Opportunities:

  1. Fork state stored on persistent object - _fork_session_id and _fork_accumulated_text on the client is non-reentrant; concurrent ask_agent() calls would collide
  2. Error message could be more specific - Tell the user which field is None (_conn vs _session_id)
  3. Base class docstring is verbose - Could be reduced to one sentence

Testing: Tests are thorough at the unit level but heavily mocked. Acknowledged that true integration testing of subprocess/ACP protocol is difficult.

No Code Changes Made

This was a review-only task per the /codereview-roasted skill instructions: "DO NOT modify the code; only provide specific, actionable feedback."

The ask_agent API (stateless question answering) failed for ACPAgent
because its sentinel LLM can't make real LLM calls. This uses the ACP
protocol's fork_session to create a temporary copy of the session,
prompt it, collect the response, and discard the fork — preserving
read-only semantics.

- Add AgentBase.ask_agent() default method (returns None → use LLM path)
- Override in ACPAgent with fork_session logic + token usage tracking
- Add fork text routing in _OpenHandsACPClient.session_update()
- Dispatch agent override in LocalConversation.ask_agent()
- Add 7 tests for ask_agent and fork text routing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@simonrosenberg simonrosenberg force-pushed the feat/acp-agent-ask-agent branch from af8df4e to 2f59de1 Compare February 20, 2026 23:14
@simonrosenberg simonrosenberg merged commit 43ee32f into main Feb 21, 2026
26 of 27 checks passed
@simonrosenberg simonrosenberg deleted the feat/acp-agent-ask-agent branch February 21, 2026 09:43
simonrosenberg added a commit that referenced this pull request Feb 21, 2026
Resolve conflicts between TCP transport feature and upstream changes
(ACPAgent refactoring from #2133, ask_agent from #2145).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants