feat: configurable skills prompt filter to reduce context bloat - #11223
Open
SupplyantSimon wants to merge 7 commits into
Open
feat: configurable skills prompt filter to reduce context bloat#11223SupplyantSimon wants to merge 7 commits into
SupplyantSimon wants to merge 7 commits into
Conversation
added 2 commits
April 18, 2026 07:27
- Adds skills.system_prompt_skills config option - Only listed skills appear in the auto-injected system prompt index - Cuts ~1500 tokens per turn when curated - Bumps config version to 18
…lter # Conflicts: # agent/prompt_builder.py
SupplyantSimon
force-pushed
the
feat/skills-prompt-filter
branch
from
April 19, 2026 19:27
572198b to
7ada837
Compare
- Add send_voice() to WhatsApp adapter for voice bubble delivery - Fix voice reply dedupe to allow replies on platforms without VC auto-TTS - Update ffmpeg Opus params for WhatsApp voice note compatibility
Add a circuit breaker mechanism in _invoke_tool() and the sequential execution path to detect and break infinite tool-call loops. When the same tool with identical arguments is called 3 consecutive times, the circuit breaker triggers and returns an error, forcing the LLM to try a different strategy. The breaker uses MD5 hashing of (tool_name, json_args) to create a stable signature, then checks if the last N calls all have the same signature. After triggering, the counter resets so future calls can succeed. - Added _consecutive_tool_calls and _circuit_breaker_threshold to AIAgent.__init__ - Added circuit breaker logic to _invoke_tool() (concurrent path) - Added circuit breaker logic to _execute_tool_calls_sequential() (sequential path) - All 22 existing tests pass
When a tool schema declares `type: array` or `type: object` and the model emits the value as a JSON string (common with complex oneOf discriminated unions), the MCP server rejects it with -32602 "expected array, received string". Extend `_coerce_value` to attempt `json.loads` for these types and replace the string with the parsed value before dispatch. Root cause confirmed via live testing: `add_reminders.reminders` uses a oneOf discriminated union (relative/absolute/location) that triggers model output drift. Sending a real array passes validation; sending a string reproduces the exact error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Collaborator
teknium1
reviewed
Jul 12, 2026
teknium1
left a comment
Contributor
There was a problem hiding this comment.
Thanks for tackling a real prompt-budget issue: current main still renders full descriptions for primary-session skills at agent/prompt_builder.py:1660-1667.
Problems
- The new filter removes non-curated skill names (
agent/prompt_builder.py:783in this diff). Current main explicitly requires names to remain visible because models do not reliably rediscover omitted skills viaskills_list(agent/prompt_builder.py:1622-1630), and the regression test codifies that contract (tests/agent/test_prompt_builder.py:429-455). - The branch also includes unrelated auxiliary-client, WhatsApp, MCP, circuit-breaker, and TTS changes. Those should not accompany a skills-index design change.
Suggested changes
- Preserve all names and reduce token cost through names-only demotion, using the existing compaction direction rather than pruning entries.
- Split unrelated commits and add tests for configuration, cache partitioning, and name visibility.
- Please consolidate with the approaches linked in the existing discussion (#12015 and #10172).
Automated hermes-sweeper review.
| _allowed = set(_sp_skills) | ||
| filtered: dict[str, list[tuple[str, str]]] = {} | ||
| for cat, items in skills_by_category.items(): | ||
| kept = [(n, d) for n, d in items if n in _allowed] |
Contributor
There was a problem hiding this comment.
This prunes every non-curated skill from the index. Current main intentionally preserves all names because models do not reliably rediscover omitted agent-created skills via skills_list (agent/prompt_builder.py:1622-1630; tests/agent/test_prompt_builder.py:429-455). Please retain names and compact descriptions instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
skills.system_prompt_skillsconfig option that filters which skills appear in the auto-injected system prompt index.Changes
agent/prompt_builder.py: filters the skills index against the configured curated list; updates cache key so filtered/unfiltered builds do not collidehermes_cli/config.py: addssystem_prompt_skillsto default config and bumps version to 18Impact
Cuts ~1,500 tokens per turn when a curated list is configured (e.g., from 81 skills down to 3). Other skills remain discoverable via
skills_list()/skill_view()on demand.Backwards Compatibility
When
system_prompt_skillsis unset or empty, all skills are included in the prompt (existing behavior).