Skip to content

fix(model_tools): log warning when enabled/disabled toolset is unknown - #24095

Closed
briandevans wants to merge 2 commits into
NousResearch:mainfrom
briandevans:fix/model-tools-warn-unknown-toolset-23997
Closed

briandevans wants to merge 2 commits into
NousResearch:mainfrom
briandevans:fix/model-tools-warn-unknown-toolset-23997

Conversation

@briandevans

@briandevans briandevans commented May 12, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Every production code path that calls get_tool_definitions passes quiet_mode=True (cron, gateway, oneshot, TUI, delegate, ACP, curator). The ⚠️ Unknown toolset line in _compute_tool_definitions is a bare print() gated on if not quiet_mode, so in real runtime an unrecognized entry in enabled_toolsets / disabled_toolsets is silently dropped with no record anywhere.

This PR promotes the conditional print to an unconditional logger.warning(...) plus the original print preserved for interactive sessions, applied symmetrically to both enabled_toolsets and disabled_toolsets. get_tool_definitions memoizes on (enabled, disabled, registry._generation, config-mtime), so a stable misconfig logs exactly one WARNING at startup — not one per turn. When MCP discovery later registers the alias, registry._generation bumps, the cache invalidates, and the next compute resolves cleanly. This is option (c) only from the reporter's three suggestions — no change to resolution rules.

Related Issue

Fixes #23997 (visibility piece)

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • model_tools.py — in _compute_tool_definitions, the else branch now emits logger.warning("Unknown toolset '%s' in {enabled,disabled}_toolsets — dropping. Check spelling against hermes tools list …", toolset_name) unconditionally, then falls through to the existing print for interactive sessions. Applied symmetrically to enabled and disabled.
  • tests/test_model_tools.pyTestUnknownToolsetWarnsInQuietMode (3 cases: unknown enabled, unknown disabled, known toolset doesn't warn) using caplog against the model_tools logger.

How to Test

  1. uv run --with pytest --with pytest-xdist --with pytest-asyncio python3 -m pytest tests/test_model_tools.py tests/test_toolsets.py tests/test_get_tool_definitions_cache_isolation.py tests/hermes_cli/test_tools_disable_enable.py tests/tools/test_delegate_composite_toolsets.py -v
  2. Expected: 79 passed.
  3. Regression guard: stash model_tools.py only — 2 of the 3 new tests fail with assert []. Restore — all 3 pass.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run focused tests for the touched code and all pass (79/79)
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15.x

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — logger.warning is platform-independent
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A

Related / Positioning

Sibling code paths that may need the same observability treatment: alias-resolution timing in tools/mcp_tool.py::_register_server_tools (option a) and the platform-toolset writer in hermes_cli/tools_config.py (option b). Intentionally left out of this PR's scope to keep the diff small — happy to widen if preferred.

Copilot AI review requested due to automatic review settings May 12, 2026 01:42
@briandevans

Copy link
Copy Markdown
Contributor Author

CI audit — all 3 failures (Tests / e2e, Tests / test, Lint / Windows footguns) are the same pre-existing baselines on clean origin/main documented one PR over in #24066 (run 25706932804 on e855925). Zero failures touch the changed code in model_tools.py / tests/test_model_tools.py.

The new TestUnknownToolsetWarnsInQuietMode cases all pass; full tests/test_model_tools.py + tests/test_toolsets.py + tests/test_get_tool_definitions_cache_isolation.py + adjacent print-asserting suites at tests/hermes_cli/test_tools_disable_enable.py + tests/tools/test_delegate_composite_toolsets.py = 79/79 pass locally.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves observability for toolset configuration by emitting logger.warning when unknown entries appear in enabled_toolsets / disabled_toolsets, ensuring misconfigurations are visible in production logs even when quiet_mode=True.

Changes:

  • Add logger.warning(...) on unknown toolset rejection paths in _compute_tool_definitions, while preserving the interactive print(...) output.
  • Add regression tests validating that unknown toolsets log warnings in quiet_mode=True, and that known toolsets do not.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
model_tools.py Logs warnings when toolsets are unknown so production (quiet) paths don’t silently drop misconfigured toolsets.
tests/test_model_tools.py Adds caplog-based regression tests for warning emission on unknown toolsets in quiet mode.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread model_tools.py Outdated
Comment on lines +359 to +361
# silently drop misnamed toolsets. The cache key includes
# registry._generation, so this only fires once per unique
# (config, registry-state) pair — not on every turn. (#23997)
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/tools Tool registry, model_tools, toolsets labels May 12, 2026
@briandevans
briandevans force-pushed the fix/model-tools-warn-unknown-toolset-23997 branch from 16fc166 to 01af6ca Compare May 13, 2026 22:13
@briandevans

Copy link
Copy Markdown
Contributor Author

@copilot Addressed in commit 3a4964f6bc: clarified the comment to distinguish the cached (quiet_mode=True) vs uncached (interactive) paths. In quiet_mode the cache in get_tool_definitions() dedupes to once per (config, registry-state); in interactive mode the cache is bypassed and the warning may repeat per call, which is acceptable there because the print() is also visible.

@briandevans
briandevans force-pushed the fix/model-tools-warn-unknown-toolset-23997 branch from 3a4964f to b3f6d48 Compare May 15, 2026 05:16
@briandevans
briandevans force-pushed the fix/model-tools-warn-unknown-toolset-23997 branch from b3f6d48 to 959201a Compare May 16, 2026 05:15
@briandevans
briandevans force-pushed the fix/model-tools-warn-unknown-toolset-23997 branch 2 times, most recently from 9a1097b to a5b3752 Compare May 22, 2026 23:10
@briandevans
briandevans force-pushed the fix/model-tools-warn-unknown-toolset-23997 branch from a5b3752 to 7bd331c Compare May 24, 2026 23:15
@briandevans
briandevans force-pushed the fix/model-tools-warn-unknown-toolset-23997 branch from 7bd331c to 5bb94cc Compare May 27, 2026 20:10
@briandevans
briandevans force-pushed the fix/model-tools-warn-unknown-toolset-23997 branch from 5bb94cc to 2943864 Compare May 29, 2026 18:12
briandevans and others added 2 commits May 30, 2026 09:16
Every production code path that calls `get_tool_definitions` —
cron, gateway, oneshot, TUI, delegate, ACP — passes `quiet_mode=True`,
which suppressed the user-facing `print("⚠️  Unknown toolset")` line in
`_compute_tool_definitions`. The result: misnamed toolsets in
`enabled_toolsets` / `disabled_toolsets` were silently dropped with no
log evidence anywhere. In NousResearch#23997 this hid an MCP server-name misconfig
across 283 cron sessions on a 13-profile fleet for ~90 min until the
reporter read the source.

Surface the rejection through `logger.warning` so it lands in
`gateway.log` / cron logs regardless of `quiet_mode`. The
existing `print()` for interactive sessions is unchanged. The warning
fires once per unique `(config, registry-generation)` pair via the
existing memoization in `get_tool_definitions`, so a stable misconfig
yields one log line at boot, not one per turn — and when MCP discovery
later bumps `registry._generation` and resolves the alias, the cache
invalidates and the next compute simply succeeds.

Tests assert both additive and subtractive paths emit a WARNING-level
record in `quiet_mode=True`, and that recognized toolsets do NOT
trigger the warning.

Fixes NousResearch#23997 (visibility piece — option (c) in the reporter's
suggested fixes; option (a)/(b) live deeper in the cron tool-resolution
path and are intentionally left out of this PR's scope).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…set warning

The original comment claimed the unknown-toolset logger.warning "only fires
once per unique (config, registry-state) pair" without noting that the
underlying cache only applies when quiet_mode=True. In interactive mode the
cache is bypassed and the warning may repeat. Comment now explicitly
distinguishes the two paths.

Per Copilot review on NousResearch#24095.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briandevans
briandevans force-pushed the fix/model-tools-warn-unknown-toolset-23997 branch from 2943864 to 592b890 Compare May 30, 2026 16:16
@briandevans

Copy link
Copy Markdown
Contributor Author

Housekeeping: closing to keep my open-PR set focused on actively-reviewed work. This has been open ~20d without maintainer review and the surrounding code has continued to move, so it's unlikely to land as-is. The underlying fix still stands — happy to reopen and rebase if it would be useful. Thanks!

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

Labels

comp/tools Tool registry, model_tools, toolsets P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] enabled_toolsets silently rejects MCP server names — MCP tools absent in cron sessions

3 participants