hermes - 💡(How to fix) Fix [Feature]: Wire clarify_callback in acp_adapter so clarify works over ACP [1 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

The clarify tool returns {"error": "Clarify tool is not available in this execution context."} whenever hermes runs as an ACP agent (e.g. hermes acp, or via acp-mux). It's still listed in the agent's toolset and the model can choose to call it, but the call short-circuits in tools/clarify_tool.py:57-61 because no callback is wired.

  • tools/clarify_tool.py:23-75clarify_tool(question, choices, callback=None). If callback is None, returns the "not available" error.
  1. Report the tool as unavailable when choices is None — keep the current "not available" error for open-ended only. Multiple-choice clarify becomes available; free-text stays disabled until/unless ACP grows a richer interactive channel.

Root Cause

Related: #12573 (same wiring gap on the gateway surface — comp/gateway). This issue is the ACP-surface parallel; the symptom and root cause are analogous but the code path is different (acp_adapter/ vs gateway/).

Fix Action

Fixed

RAW_BUFFERClick to expand / collapse

Related: #12573 (same wiring gap on the gateway surface — comp/gateway). This issue is the ACP-surface parallel; the symptom and root cause are analogous but the code path is different (acp_adapter/ vs gateway/).

Problem or Use Case

The clarify tool returns {"error": "Clarify tool is not available in this execution context."} whenever hermes runs as an ACP agent (e.g. hermes acp, or via acp-mux). It's still listed in the agent's toolset and the model can choose to call it, but the call short-circuits in tools/clarify_tool.py:57-61 because no callback is wired.

Concretely:

  • tools/clarify_tool.py:23-75clarify_tool(question, choices, callback=None). If callback is None, returns the "not available" error.
  • Callbacks are wired on every non-ACP surface:
    • cli.py _clarify_callback (~line 10647) — prompt_toolkit arrow-key UI, 120s timeout.
    • hermes_cli/oneshot.py:336_oneshot_clarify_callback.
    • gateway/run.py:16456agent.clarify_callback = _clarify_callback_sync.
    • run_agent.py:452clarify_callback=clarify_callback passed into agent init.
  • No clarify_callback is set anywhere in acp_adapter/grep -rn "clarify_callback" acp_adapter/ returns zero matches. The clarify tool is listed in acp_adapter/tools.py:_POLISHED_TOOLS for display polishing only; there's no protocol routing.
  • The ACP spec doesn't have a generic structured-question channel either. The published SDK schema (acp Python package v0.11.2, acp/meta.py) lists exactly nine CLIENT_METHODS: fs/read_text_file, fs/write_text_file, session/request_permission, session/update, terminal/{create,kill,output,release,wait_for_exit}. There's no session/clarify.

End-user impact: any clarifying question the model decides to ask gets swallowed; the agent has to proceed without user input.

Proposed Solution

session/request_permission is semantically the closest existing ACP method to clarify — both are "agent presents user with N labeled options and waits for one to be picked." The mapping is direct:

Clarify fieldsession/request_permission field
questionparams.toolCall.title (or a synthetic ToolCallUpdate whose content carries the question text)
choices[i]params.options[i].name (with option_id = f"clarify-{i}")
chosen answerresult.outcome.option_id → mapped back to choices[i]
user dismissresult.outcome.cancelled

Wire a clarify_callback in acp_adapter/server.py (alongside the existing approval-callback bridge in acp_adapter/permissions.py) that:

  1. Builds a ToolCallUpdate describing the question (kind other, title = the question text, content = text_block(question)).
  2. Builds PermissionOption(option_id=f"clarify-{i}", kind="allow_once", name=choice) per supplied choice.
  3. Schedules the connection's request_permission coroutine via safe_schedule_threadsafe — mirrors make_approval_callback in permissions.py:107.
  4. Maps the returned outcome.option_id back to choices[i] (or returns "" for cancelled, matching the existing CLI fallback behavior).

Most of the plumbing already exists — _build_permission_tool_call, _build_permission_options, the future scheduling — so the adapter is a thin shim over make_approval_callback with a different option-id mapping.

Alternatives Considered

Open-ended (no-choices) clarify is the awkward part. clarify_tool accepts choices=None for free-form questions; in CLI mode that falls through to a freetext prompt. session/request_permission has no free-text field — options[] is the only payload. Two ways to degrade:

  1. Synthetic single option — send a single option like {option_id: "ack", name: "OK"} and treat any reply as "user has been notified but didn't provide an answer." Agent gets no actual signal back; arguably worse than failing.
  2. Report the tool as unavailable when choices is None — keep the current "not available" error for open-ended only. Multiple-choice clarify becomes available; free-text stays disabled until/unless ACP grows a richer interactive channel.

Option 2 expands coverage without faking semantics. Open-ended clarify across all non-CLI surfaces is already a real protocol gap (see #12573); this issue doesn't try to solve that.

Extending ACP with a session/clarify method was considered and rejected as out-of-scope for this issue. Adding to the upstream spec is a separate, longer process; piggybacking on request_permission works today and the option-id mapping is reversible if the spec ever grows a proper field.

Feature Type

Other (ACP adapter wiring — bridges an existing tool to an existing protocol method that already supports the shape).

Scope

Small (single file, < 50 lines) — most of the plumbing is reused from acp_adapter/permissions.py.

Contribution

No (filing for visibility; happy to discuss the option-id mapping or the open-ended degradation if a maintainer wants to take it).

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix [Feature]: Wire clarify_callback in acp_adapter so clarify works over ACP [1 pull requests]