Skip to content

bug: exec quick commands routed to agent as text when agent is mid-turn #25783

@TerminalSausage

Description

@TerminalSausage

Summary

When the agent is actively processing (mid-turn, tool calls in flight), exec-type quick commands (type: exec) are not executed by the gateway's quick command dispatcher. Instead, the command text is routed to the agent as a regular incoming message.

Expected Behavior

Exec quick commands should always execute their shell command immediately, regardless of agent state. They bypass the LLM entirely by design — the gateway intercepts them, runs the subprocess, and returns the output directly.

Actual Behavior

If the agent is mid-turn (tool calls active, gateway is processing), the quick command falls through to the agent loop and appears as raw text in the conversation (e.g., the agent sees /note remember to buy milk as a user message instead of the gateway executing daily-note.sh "remember to buy milk").

Reproduction

  1. Set up an exec quick command in config.yaml:
    quick_commands:
      note:
        type: exec
        command: bash ~/.hermes/scripts/daily-note.sh "{args}"
  2. Start a conversation with the agent and trigger a multi-tool-call turn
  3. While the agent is actively processing tool calls, type /note test message in Discord/CLI
  4. Observe: the agent receives /note test message as a plain text message instead of the script executing

Impact

  • Notes/commands silently fail (no execution, no error)
  • Agent sees raw command text that it shouldn't see
  • User gets no feedback that the command was swallowed

Environment

  • Hermes v0.13.0
  • Discord gateway
  • Config: quick_commands.<name>.type: exec

Suggested Fix

The quick command dispatch in _process_event() (gateway/run.py) should happen before any agent-turn queuing logic, or at minimum, exec-type quick commands should be short-circuited regardless of _draining or active session state. Since exec commands don't touch the LLM or the session, there's no reason they should be blocked by agent activity.

The relevant dispatch code is around line 6479 in gateway/run.py:

# User-defined quick commands (bypass agent loop, no LLM call)
if command:
    quick_commands = ...
    if command in quick_commands:
        qcmd = quick_commands[command]
        if qcmd.get("type") == "exec":
            # This block should be unreachable by agent state
            # but appears to be bypassed when agent is mid-turn

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/gatewayGateway runner, session dispatch, deliverytype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions