Bug
When the agent is connected via the gateway (e.g. Telegram), calling the session_search tool returns:
{"error": "session_search must be handled by the agent loop"}
Root Cause
gateway/run.py creates AIAgent(...) without passing session_db=, so self._session_db is None in the agent instance.
The tool dispatch in run_agent.py has this condition:
elif function_name == "session_search" and self._session_db:
When _session_db is None, the branch is skipped entirely and execution falls through to handle_function_call() in model_tools.py, which returns
the generic error for all tools in _AGENT_LOOP_TOOLS:
_AGENT_LOOP_TOOLS = {"todo", "memory", "session_search", "delegate_task"}
def handle_function_call(...):
if function_name in _AGENT_LOOP_TOOLS:
return json.dumps({"error": f"{function_name} must be handled by the agent loop"})
The CLI path works because cli.py initializes and passes the DB:
from hermes_state import SessionDB
self._session_db = SessionDB()
...
agent = AIAgent(..., session_db=self._session_db)
Fix
Two changes needed:
- gateway/run.py — Pass session_db to AIAgent
Initialize SessionDB in GatewayRunner.init():
self._session_db = None
try:
from hermes_state import SessionDB
self._session_db = SessionDB()
except Exception as e:
logger.debug("SQLite session store not available: %s", e)
And pass it in run_sync():
agent = AIAgent(
...,
session_db=self._session_db,
)
- run_agent.py — Defensive fallback when _session_db is None
Change the dispatch branch to always intercept session_search and return a clear error if the DB is unavailable, instead of falling through:
elif function_name == "session_search":
if not self._session_db:
function_result = json.dumps({"success": False, "error": "Session database not available."})
else:
from tools.session_search_tool import session_search as _session_search
function_result = _session_search(
query=function_args.get("query", ""),
role_filter=function_args.get("role_filter"),
limit=function_args.get("limit", 3),
db=self._session_db,
)
Affected Files
- gateway/run.py — GatewayRunner.init() and run_sync()
- run_agent.py — tool dispatch block (~line 1462)
Bug
When the agent is connected via the gateway (e.g. Telegram), calling the session_search tool returns:
{"error": "session_search must be handled by the agent loop"}
Root Cause
gateway/run.py creates AIAgent(...) without passing session_db=, so self._session_db is None in the agent instance.
The tool dispatch in run_agent.py has this condition:
elif function_name == "session_search" and self._session_db:
When _session_db is None, the branch is skipped entirely and execution falls through to handle_function_call() in model_tools.py, which returns
the generic error for all tools in _AGENT_LOOP_TOOLS:
_AGENT_LOOP_TOOLS = {"todo", "memory", "session_search", "delegate_task"}
def handle_function_call(...):
if function_name in _AGENT_LOOP_TOOLS:
return json.dumps({"error": f"{function_name} must be handled by the agent loop"})
The CLI path works because cli.py initializes and passes the DB:
from hermes_state import SessionDB
self._session_db = SessionDB()
...
agent = AIAgent(..., session_db=self._session_db)
Fix
Two changes needed:
Initialize SessionDB in GatewayRunner.init():
self._session_db = None
try:
from hermes_state import SessionDB
self._session_db = SessionDB()
except Exception as e:
logger.debug("SQLite session store not available: %s", e)
And pass it in run_sync():
agent = AIAgent(
...,
session_db=self._session_db,
)
Change the dispatch branch to always intercept session_search and return a clear error if the DB is unavailable, instead of falling through:
elif function_name == "session_search":
if not self._session_db:
function_result = json.dumps({"success": False, "error": "Session database not available."})
else:
from tools.session_search_tool import session_search as _session_search
function_result = _session_search(
query=function_args.get("query", ""),
role_filter=function_args.get("role_filter"),
limit=function_args.get("limit", 3),
db=self._session_db,
)
Affected Files