Skip to content

feat(transports): add opt-in extra_body.hermes outbound metadata channel#27525

Open
konsisumer wants to merge 1 commit into
NousResearch:mainfrom
konsisumer:feat/hermes-outbound-metadata
Open

feat(transports): add opt-in extra_body.hermes outbound metadata channel#27525
konsisumer wants to merge 1 commit into
NousResearch:mainfrom
konsisumer:feat/hermes-outbound-metadata

Conversation

@konsisumer

Copy link
Copy Markdown
Contributor

What changed and why

Adds a documented extra_body.hermes object to every outgoing chat-completions request when extras.hermes_metadata.enabled: true is set in config.yaml (default: false).

This gives downstream OpenAI-compatible proxies and dispatchers (LiteLLM, Helicone, Langfuse, custom routers) machine-readable orchestration context — session, platform, chat, user, command origin — without parsing free text or spinning up one Hermes profile per channel.

Per the confirmed direction on #22714:

user_intent deferred to v2 (requires a classifier, not just plumbing).

Field names mirror SessionSource.chat_id / AIAgent.__init__ kwargs for naming consistency, and align with @gsskk's inbound-headers PR #24423 (X-Hermes-Chat-Idextra_body.hermes.chat_id).

Files changed

File Change
agent/transports/chat_completions.py _add_hermes_metadata() helper; called from both profile and legacy paths
agent/chat_completion_helpers.py Pass hermes_outbound_metadata + four context fields to build_kwargs()
agent/agent_init.py Add hermes_outbound_metadata: bool and command_origin: str params
run_agent.py Forward new params to init_agent()
gateway/run.py Read extras.hermes_metadata.enabled from config; pass to both agent creation sites (command_origin="user" for main flow, "scheduled" for background tasks)
docs/hermes-outbound-metadata.md Opt-in docs with wire example and strict-server caveat
tests/agent/transports/test_chat_completions.py 7 new tests: default-off (profile + legacy), all-fields (profile + legacy), None-fields omitted, empty block not emitted, coexists with other extra_body entries

How to test

# In your gateway profile config.yaml:
extras:
  hermes_metadata:
    enabled: true
  1. Start the Matrix (or Telegram/Discord) gateway with the config above.
  2. Send a message in a connected room.
  3. Inspect your downstream proxy/dispatcher logs — the outbound request should include:
{
  "extra_body": {
    "hermes": {
      "session_id": "<session-id>",
      "gateway_platform": "matrix",
      "chat_id": "!room:example.org",
      "user_id": "@alice:example.org",
      "command_origin": "user"
    }
  }
}
  1. With enabled: false (default), confirm no extra_body.hermes key appears.
  2. Against a strict-validating server (e.g. vLLM strict mode) with enabled: false — requests must succeed unchanged.

Unit test coverage: pytest tests/agent/transports/test_chat_completions.py::TestHermesOutboundMetadata -v

What platforms tested on

  • macOS (darwin 24.6.0, Python 3.11)
  • Unit tests: 395 transport + provider tests pass
  • 7 new TestHermesOutboundMetadata tests pass
  • Pre-existing failures in 5 unrelated tests (test_background_command, test_discord_component_auth, test_auxiliary_client, test_platform_commands, test_registry_manifest) confirmed pre-existing via git stash bisect

Fixes #22714

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/agent Core agent loop, run_agent.py, prompt builder comp/gateway Gateway runner, session dispatch, delivery labels May 17, 2026
@konsisumer

Copy link
Copy Markdown
Contributor Author

Rebased onto origin/main and resolved the in-scope conflict in agent/transports/chat_completions.py, preserving current Gemini extra_content sanitization while keeping this PR's opt-in extra_body.hermes metadata injection on both kwargs paths.

Verification:

  • ruff check on changed Python files passed (with an existing invalid # noqa warning on run_agent.py:93).
  • python scripts/check-windows-footguns.py --diff origin/main passed.
  • git diff --check passed.
  • pytest tests/agent/transports/test_chat_completions.py -q --timeout=60 passed: 79 tests.
  • Full bounded suite stopped during collection on tests/hermes_cli/test_dashboard_auth_401_reauth.py because local fastapi is not installed; that test is outside this PR's modified files.

@konsisumer konsisumer force-pushed the feat/hermes-outbound-metadata branch from ea255c0 to f424780 Compare June 4, 2026 15:14
@konsisumer

Copy link
Copy Markdown
Contributor Author

Rebased onto current origin/main and resolved the in-scope conflict in tests/agent/transports/test_chat_completions.py, retaining both upstream native-Gemini extra_body stripping coverage and this PR's extra_body.hermes metadata coverage.

Verification:

  • git diff --check passed.
  • ruff check on changed Python files passed, with the existing invalid # noqa warning on run_agent.py:93.
  • python scripts/check-windows-footguns.py --diff origin/main passed.
  • pytest tests/agent/transports/test_chat_completions.py -q --timeout=60 passed: 82 tests.
  • Full bounded suite stopped during collection on tests/hermes_cli/test_dashboard_auth_401_reauth.py because local fastapi is not installed; that file is outside this PR's modified files.

@konsisumer konsisumer force-pushed the feat/hermes-outbound-metadata branch from f424780 to 6a2f90e Compare June 5, 2026 12:33
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused implementation — I verified the requested extra_body.hermes channel is still missing on current main, and this PR is aligned with the #22714 discussion.

Problems

  • The PR claims metadata is added to every outgoing chat-completions request, but the iteration-limit summary path bypasses ChatCompletionsTransport.build_kwargs(). On current main it builds summary_extra_body directly in agent/chat_completion_helpers.py:1363, attaches it at agent/chat_completion_helpers.py:1457 / agent/chat_completion_helpers.py:1510, and sends via chat.completions.create() at agent/chat_completion_helpers.py:1470 / agent/chat_completion_helpers.py:1513. The PR diff only injects Hermes metadata in the transport/build-kwargs path, so those summary calls would not carry the opt-in block.

Suggested changes

  • Either add the same opt-in extra_body.hermes merge to the direct summary path, or narrow the docs/PR wording so it does not promise every chat-completions call.
  • Please add a real-path test for the extras.hermes_metadata.enabled config plumbing through gateway/run.py into AIAgent; AGENTS.md:84-87 specifically asks for E2E-style validation around config propagation.

This is an automated hermes-sweeper review.

@konsisumer konsisumer force-pushed the feat/hermes-outbound-metadata branch from 6a2f90e to 9dd96f8 Compare June 13, 2026 12:56
@konsisumer

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Addressed in this push:

  • Iteration-limit summary path: mirrored the opt-in extra_body.hermes merge in handle_max_iterations(), so the direct summary chat.completions.create() call now carries the same metadata block as the transport path.
  • Gateway config plumbing: added regression coverage that extras.hermes_metadata.enabled reaches AIAgent(...) through gateway/run.py for both the main user flow (command_origin="user") and background tasks ("scheduled").
  • Summary-path coverage: added a regression test proving the iteration-limit summary call emits extra_body.hermes when the flag is enabled.

Related: #22714.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Matrix gateway: no in-band channel to drive per-message LLM orchestration in a downstream dispatcher

3 participants