Bug Description
After upgrading Hermes to current HEAD, the clarify tool always returns an error in Telegram gateway mode:
{"error": "Clarify tool is not available in this execution context."}
Inline keyboard buttons never appear. The tool works correctly in CLI and TUI modes — the bug is specific to gateway/Telegram.
Steps to Reproduce
- Start Hermes gateway with Telegram platform:
hermes gateway start
- Send any message that causes the agent to call the
clarify tool
- Observe: no inline keyboard appears in Telegram
- The agent receives
{"error": "Clarify tool is not available in this execution context."} and cannot ask the user questions
Reproduces every time — the tool is completely non-functional in gateway mode.
Expected Behavior
The agent sends a Telegram message with inline keyboard buttons showing the choices. User taps a button → choice is returned to the agent.
Actual Behavior
Error returned immediately. No message sent to Telegram. No buttons.
Environment
- Hermes Agent: v0.12.0 (2026.4.30), updated to HEAD (691 commits ahead of tag)
- Platform: Telegram gateway (polling mode)
- Python: 3.11.15
- OS: Linux (systemd user service)
- Gateway started fresh after upgrade
Evidence
Before upgrade (gateway started April 27) — clarify worked:
2026-05-07 07:01:37 gateway.run: clarify pending stored: 16ab104a... choices=[...]
2026-05-07 07:01:46 gateway.platforms.telegram: clarify callback received: cq:16ab104a...:0
2026-05-07 07:01:46 gateway.platforms.telegram: clarify resolved: 16ab104a... idx=0
After upgrade + restart — clarify never fires. No log entries for clarify at all. The tool returns the error above.
Root Cause
AIAgent requires clarify_callback to wire the tool to the platform. In CLI (cli.py) and TUI (tui_gateway/server.py) this callback is passed during agent construction. In the messaging gateway (gateway/run.py) it is never passed — self.clarify_callback remains None, which clarify_tool.py:57 treats as unavailable.
Additionally, the Telegram adapter (gateway/platforms/telegram.py) has no:
_clarify_state dict for storing prompt state
send_clarify_prompt() method
clarify: handler in _handle_callback_query
Impact
Every gateway user on Telegram (and likely other messaging platforms that do not implement their own clarify integration) cannot use the clarify tool. The agent silently fails to ask clarifying questions.
Fix
2 files changed, ~145 insertions. Full diff below.
gateway/run.py — callback + wiring
# After _status_callback_sync block, before run_sync():
def _clarify_callback(question: str, choices=None) -> str:
if not _status_adapter or not _run_still_current():
return ""
import uuid, threading
clarify_id = uuid.uuid4().hex
event = threading.Event()
_status_adapter._clarify_state[clarify_id] = {
"event": event, "choice": None,
"choices": choices or [], "question": question,
}
try:
asyncio.run_coroutine_threadsafe(
_status_adapter.send_clarify_prompt(
chat_id=_status_chat_id,
question=question, choices=choices or [],
clarify_id=clarify_id,
metadata=_status_thread_metadata,
), _loop_for_step,
).result(timeout=10)
except Exception as _e:
logger.error("clarify_callback send error: %s", _e)
_status_adapter._clarify_state.pop(clarify_id, None)
return ""
logger.info("clarify pending stored: %s choices=%s", clarify_id, choices)
event.wait(timeout=120)
state = _status_adapter._clarify_state.pop(clarify_id, {"choice": ""})
return state.get("choice", "")
# After agent.status_callback = _status_callback_sync:
agent.clarify_callback = _clarify_callback
gateway/platforms/telegram.py — adapter support
1. In __init__:
self._clarify_state: Dict[str, dict] = {}
2. New method send_clarify_prompt:
async def send_clarify_prompt(
self, chat_id: str, question: str, choices: list,
clarify_id: str, metadata=None,
) -> SendResult:
if not self._bot:
return SendResult(success=False, error="Not connected")
try:
buttons = []
for i, choice in enumerate(choices):
buttons.append([InlineKeyboardButton(
choice, callback_data=f"clarify:{clarify_id}:{i}")])
buttons.append([InlineKeyboardButton(
"✗ Skip", callback_data=f"clarify:{clarify_id}:skip")])
keyboard = InlineKeyboardMarkup(buttons)
thread_id = metadata.get("thread_id") if metadata else None
msg = await self._bot.send_message(
chat_id=int(chat_id), text=question,
reply_markup=keyboard,
message_thread_id=int(thread_id) if thread_id else None,
**self._link_preview_kwargs(),
)
return SendResult(success=True, message_id=str(msg.message_id))
except Exception as e:
logger.warning("[%s] send_clarify_prompt failed: %s", self.name, e)
return SendResult(success=False, error=str(e))
3. In _handle_callback_query, before update-prompt handler:
# --- Clarify callbacks (clarify:id:idx) ---
if data.startswith("clarify:"):
parts = data.split(":", 2)
if len(parts) == 3:
clarify_id = parts[1]
choice_key = parts[2]
state = self._clarify_state.get(clarify_id)
if not state:
await query.answer(text="This question is no longer active.")
return
if choice_key == "skip":
user_choice = ""
else:
try:
idx = int(choice_key)
except ValueError:
await query.answer(text="Invalid choice.")
return
choices = state.get("choices", [])
if 0 <= idx < len(choices):
user_choice = choices[idx]
else:
await query.answer(text="Invalid choice.")
return
state["choice"] = user_choice
state["event"].set()
user_display = getattr(query.from_user, "first_name", "User")
label = f"Selected: {user_choice}" if user_choice else "Skipped"
await query.answer(text=label)
try:
await query.edit_message_text(
text=f"{state['question']}\n\n*{label}* by {user_display}",
parse_mode=ParseMode.MARKDOWN, reply_markup=None,
)
except Exception:
pass
logger.info(
"[%s] clarify resolved: %s idx=%s choice=%r",
self.name, clarify_id, choice_key, user_choice,
)
return
Notes
- Uses
uuid.uuid4().hex for clarify IDs (no colons) — avoids the split(":", 2) pitfall documented in references/clarify-telegram-buttons.md
- Follows the existing callback pattern from
_status_callback_sync
- Fix has been tested in production — clarify tool works correctly after applying this patch
Bug Description
After upgrading Hermes to current HEAD, the
clarifytool always returns an error in Telegram gateway mode:{"error": "Clarify tool is not available in this execution context."}Inline keyboard buttons never appear. The tool works correctly in CLI and TUI modes — the bug is specific to gateway/Telegram.
Steps to Reproduce
hermes gateway startclarifytool{"error": "Clarify tool is not available in this execution context."}and cannot ask the user questionsReproduces every time — the tool is completely non-functional in gateway mode.
Expected Behavior
The agent sends a Telegram message with inline keyboard buttons showing the choices. User taps a button → choice is returned to the agent.
Actual Behavior
Error returned immediately. No message sent to Telegram. No buttons.
Environment
Evidence
Before upgrade (gateway started April 27) — clarify worked:
After upgrade + restart — clarify never fires. No log entries for clarify at all. The tool returns the error above.
Root Cause
AIAgentrequiresclarify_callbackto wire the tool to the platform. In CLI (cli.py) and TUI (tui_gateway/server.py) this callback is passed during agent construction. In the messaging gateway (gateway/run.py) it is never passed —self.clarify_callbackremainsNone, whichclarify_tool.py:57treats as unavailable.Additionally, the Telegram adapter (
gateway/platforms/telegram.py) has no:_clarify_statedict for storing prompt statesend_clarify_prompt()methodclarify:handler in_handle_callback_queryImpact
Every gateway user on Telegram (and likely other messaging platforms that do not implement their own clarify integration) cannot use the clarify tool. The agent silently fails to ask clarifying questions.
Fix
2 files changed, ~145 insertions. Full diff below.
gateway/run.py — callback + wiring
gateway/platforms/telegram.py — adapter support
1. In
__init__:2. New method
send_clarify_prompt:3. In
_handle_callback_query, before update-prompt handler:Notes
uuid.uuid4().hexfor clarify IDs (no colons) — avoids thesplit(":", 2)pitfall documented inreferences/clarify-telegram-buttons.md_status_callback_sync