Files
hermes-agent/website/docs/developer-guide/gateway-internals.md
Teknium dd7921d514 fix(honcho): isolate session routing for multi-user gateway (#1500)
Salvaged from PR #1470 by adavyas.

Core fix: Honcho tool calls in a multi-session gateway could route to
the wrong session because honcho_tools.py relied on process-global
state. Now threads session context through the call chain:
  AIAgent._invoke_tool() → handle_function_call() → registry.dispatch()
  → handler **kw → _resolve_session_context()

Changes:
- Add _resolve_session_context() to prefer per-call context over globals
- Plumb honcho_manager + honcho_session_key through handle_function_call
- Add sync_honcho=False to run_conversation() for synthetic flush turns
- Pass honcho_session_key through gateway memory flush lifecycle
- Harden gateway PID detection when /proc cmdline is unreadable
- Make interrupt test scripts import-safe for pytest-xdist
- Wrap BibTeX examples in Jekyll raw blocks for docs build
- Fix thread-order-dependent assertion in client lifecycle test
- Expand Honcho docs: session isolation, lifecycle, routing internals

Dropped from original PR:
- Indentation change in _create_request_openai_client that would move
  client creation inside the lock (causes unnecessary contention)

Co-authored-by: adavyas <adavyas@users.noreply.github.com>
2026-03-16 00:23:47 -07:00

3.8 KiB

sidebar_position, title, description
sidebar_position title description
7 Gateway Internals How the messaging gateway boots, authorizes users, routes sessions, and delivers messages

Gateway Internals

The messaging gateway is the long-running process that connects Hermes to external platforms.

Key files:

  • gateway/run.py
  • gateway/config.py
  • gateway/session.py
  • gateway/delivery.py
  • gateway/pairing.py
  • gateway/channel_directory.py
  • gateway/hooks.py
  • gateway/mirror.py
  • gateway/platforms/*

Core responsibilities

The gateway process is responsible for:

  • loading configuration from .env, config.yaml, and gateway.json
  • starting platform adapters
  • authorizing users
  • routing incoming events to sessions
  • maintaining per-chat session continuity
  • dispatching messages to AIAgent
  • running cron ticks and background maintenance tasks
  • mirroring/proactively delivering output to configured channels

Config sources

The gateway has a multi-source config model:

  • environment variables
  • ~/.hermes/gateway.json
  • selected bridged values from ~/.hermes/config.yaml

Session routing

gateway/session.py and GatewayRunner cooperate to map incoming messages to active session IDs.

Session keying can depend on:

  • platform
  • user/chat identity
  • thread/topic identity
  • special platform-specific routing behavior

Authorization layers

The gateway can authorize through:

  • platform allowlists
  • gateway-wide allowlists
  • DM pairing flows
  • explicit allow-all settings

Pairing support is implemented in gateway/pairing.py.

Delivery path

Outgoing deliveries are handled by gateway/delivery.py, which knows how to:

  • deliver to a home channel
  • resolve explicit targets
  • mirror some remote deliveries back into local history/session tracking

Hooks

Gateway events emit hook callbacks through gateway/hooks.py. Hooks are local trusted Python code and can observe or extend gateway lifecycle events.

Background maintenance

The gateway also runs maintenance tasks such as:

  • cron ticking
  • cache refreshes
  • session expiry checks
  • proactive memory flush before reset/expiry

Honcho interaction

When Honcho is enabled, the gateway keeps persistent Honcho managers aligned with session lifetimes and platform-specific session keys.

Session routing

Honcho tools (honcho_profile, honcho_search, honcho_context, honcho_conclude) need to execute against the correct user's Honcho session. In a multi-user gateway, the process-global module state in tools/honcho_tools.py is insufficient — multiple sessions may be active concurrently.

The solution threads session context through the call chain:

AIAgent._invoke_tool()
  → handle_function_call(honcho_manager=..., honcho_session_key=...)
    → registry.dispatch(**kwargs)
      → _handle_honcho_*(args, **kw)
        → _resolve_session_context(**kw)   # prefers explicit kwargs over module globals

_resolve_session_context() in honcho_tools.py checks for honcho_manager and honcho_session_key in the kwargs first, falling back to the module-global _session_manager / _session_key for CLI mode where there's only one session.

Memory flush lifecycle

When a session is reset, resumed, or expires, the gateway flushes memories before discarding context. The flush creates a temporary AIAgent with:

  • session_id set to the old session's ID (so transcripts load correctly)
  • honcho_session_key set to the gateway session key (so Honcho writes go to the right place)
  • sync_honcho=False passed to run_conversation() (so the synthetic flush turn doesn't write back to Honcho's conversation history)

After the flush completes, any queued Honcho writes are drained and the gateway-level Honcho manager is shut down for that session key.