fix(discord): keep /skill command descriptions under Discord size limits#10214
Closed
njiangk wants to merge 1 commit into
Closed
fix(discord): keep /skill command descriptions under Discord size limits#10214njiangk wants to merge 1 commit into
njiangk wants to merge 1 commit into
Conversation
teknium1
added a commit
that referenced
this pull request
Apr 17, 2026
…trivially Closes #11321, closes #10259. ## Problem The nested /skill command group (category subcommand groups + skill subcommands) serialized to ~14KB with the default 75-skill catalog, exceeding Discord's ~8000-byte per-command registration payload. The entire tree.sync() rejected with error 50035 — ALL slash commands including the 27 base commands failed to register. ## Fix Replace the nested Group layout with a single flat Command: /skill name:<autocomplete> args:<optional string> Autocomplete options are fetched dynamically by Discord when the user types — they do NOT count against the per-command registration budget. So this single command registers at ~200 bytes regardless of how many skills exist. Scales to thousands of skills with no size calculations, no splitting, no hidden skills. UX improvements: - Discord live-filters by user's typed prefix against BOTH name and description, so '/skill pdf' finds 'ocr-and-documents' via its description. More discoverable than clicking through category menus. - Unknown skill name → ephemeral error pointing user at autocomplete. - Stable alphabetical ordering across restarts. ## Why not the other proposed approaches Three prior PRs tried to fit within the 8KB limit by modifying the nested layout: - #10214 (njiangk): truncated all descriptions to 'Run <name>' and category descriptions to 'Skills'. Works but destroys slash picker UX. - #11385 (LeonSGP43): 40-char description clamp + iterative trim-largest-category fallback. Works but HIDES skills the user can no longer invoke via slash — functional regression. - #10261 (zeapsu): adaptive split into /skill-<cat> top-level groups. Preserves all skills but pollutes the slash namespace with 20 top-level commands. All three work around the symptom. The flat autocomplete design dissolves the problem — there is no payload-size pressure to manage. ## Tests tests/gateway/test_discord_slash_commands.py — 5 new test cases replace the 3 old nested-structure tests: - flat-not-nested structure assertion - empty skills → no command registered - callback dispatches the right cmd_key by name - unknown name → ephemeral error, no dispatch - large-catalog regression guard (500 skills) — command payload stays under 500 bytes regardless E2E validated against real discord.py 2.7.1: - Command registers as discord.app_commands.Command (not Group). - Autocomplete filters by name AND description (verified across several queries including description-only matches like 'pdf' → OCR skill). - 500-skill catalog returns max 25 results per autocomplete query (Discord's hard cap), filtered correctly. - Choice labels formatted as 'name — description' clamped to 100 chars.
teknium1
added a commit
that referenced
this pull request
Apr 17, 2026
…trivially (#11580) Closes #11321, closes #10259. ## Problem The nested /skill command group (category subcommand groups + skill subcommands) serialized to ~14KB with the default 75-skill catalog, exceeding Discord's ~8000-byte per-command registration payload. The entire tree.sync() rejected with error 50035 — ALL slash commands including the 27 base commands failed to register. ## Fix Replace the nested Group layout with a single flat Command: /skill name:<autocomplete> args:<optional string> Autocomplete options are fetched dynamically by Discord when the user types — they do NOT count against the per-command registration budget. So this single command registers at ~200 bytes regardless of how many skills exist. Scales to thousands of skills with no size calculations, no splitting, no hidden skills. UX improvements: - Discord live-filters by user's typed prefix against BOTH name and description, so '/skill pdf' finds 'ocr-and-documents' via its description. More discoverable than clicking through category menus. - Unknown skill name → ephemeral error pointing user at autocomplete. - Stable alphabetical ordering across restarts. ## Why not the other proposed approaches Three prior PRs tried to fit within the 8KB limit by modifying the nested layout: - #10214 (njiangk): truncated all descriptions to 'Run <name>' and category descriptions to 'Skills'. Works but destroys slash picker UX. - #11385 (LeonSGP43): 40-char description clamp + iterative trim-largest-category fallback. Works but HIDES skills the user can no longer invoke via slash — functional regression. - #10261 (zeapsu): adaptive split into /skill-<cat> top-level groups. Preserves all skills but pollutes the slash namespace with 20 top-level commands. All three work around the symptom. The flat autocomplete design dissolves the problem — there is no payload-size pressure to manage. ## Tests tests/gateway/test_discord_slash_commands.py — 5 new test cases replace the 3 old nested-structure tests: - flat-not-nested structure assertion - empty skills → no command registered - callback dispatches the right cmd_key by name - unknown name → ephemeral error, no dispatch - large-catalog regression guard (500 skills) — command payload stays under 500 bytes regardless E2E validated against real discord.py 2.7.1: - Command registers as discord.app_commands.Command (not Group). - Autocomplete filters by name AND description (verified across several queries including description-only matches like 'pdf' → OCR skill). - 500-skill catalog returns max 25 results per autocomplete query (Discord's hard cap), filtered correctly. - Choice labels formatted as 'name — description' clamped to 100 chars.
Contributor
|
Closing in favor of a different approach — #11580 — #11580 Thank you for catching this bug and submitting a fix. Your analysis (Discord aggregate 8KB limit on /skill slash metadata) was correct, and your We went with a different layout: a flat Thanks for the fix — you're credited in the merge commit body. |
ulasbilgen
pushed a commit
to ulasbilgen/hermes-adhd-agent
that referenced
this pull request
May 1, 2026
…trivially (NousResearch#11580) Closes NousResearch#11321, closes NousResearch#10259. ## Problem The nested /skill command group (category subcommand groups + skill subcommands) serialized to ~14KB with the default 75-skill catalog, exceeding Discord's ~8000-byte per-command registration payload. The entire tree.sync() rejected with error 50035 — ALL slash commands including the 27 base commands failed to register. ## Fix Replace the nested Group layout with a single flat Command: /skill name:<autocomplete> args:<optional string> Autocomplete options are fetched dynamically by Discord when the user types — they do NOT count against the per-command registration budget. So this single command registers at ~200 bytes regardless of how many skills exist. Scales to thousands of skills with no size calculations, no splitting, no hidden skills. UX improvements: - Discord live-filters by user's typed prefix against BOTH name and description, so '/skill pdf' finds 'ocr-and-documents' via its description. More discoverable than clicking through category menus. - Unknown skill name → ephemeral error pointing user at autocomplete. - Stable alphabetical ordering across restarts. ## Why not the other proposed approaches Three prior PRs tried to fit within the 8KB limit by modifying the nested layout: - NousResearch#10214 (njiangk): truncated all descriptions to 'Run <name>' and category descriptions to 'Skills'. Works but destroys slash picker UX. - NousResearch#11385 (LeonSGP43): 40-char description clamp + iterative trim-largest-category fallback. Works but HIDES skills the user can no longer invoke via slash — functional regression. - NousResearch#10261 (zeapsu): adaptive split into /skill-<cat> top-level groups. Preserves all skills but pollutes the slash namespace with 20 top-level commands. All three work around the symptom. The flat autocomplete design dissolves the problem — there is no payload-size pressure to manage. ## Tests tests/gateway/test_discord_slash_commands.py — 5 new test cases replace the 3 old nested-structure tests: - flat-not-nested structure assertion - empty skills → no command registered - callback dispatches the right cmd_key by name - unknown name → ephemeral error, no dispatch - large-catalog regression guard (500 skills) — command payload stays under 500 bytes regardless E2E validated against real discord.py 2.7.1: - Command registers as discord.app_commands.Command (not Group). - Autocomplete filters by name AND description (verified across several queries including description-only matches like 'pdf' → OCR skill). - 500-skill catalog returns max 25 results per autocomplete query (Discord's hard cap), filtered correctly. - Choice labels formatted as 'name — description' clamped to 100 chars.
aj-nt
pushed a commit
to aj-nt/hermes-agent
that referenced
this pull request
May 1, 2026
…trivially (NousResearch#11580) Closes NousResearch#11321, closes NousResearch#10259. ## Problem The nested /skill command group (category subcommand groups + skill subcommands) serialized to ~14KB with the default 75-skill catalog, exceeding Discord's ~8000-byte per-command registration payload. The entire tree.sync() rejected with error 50035 — ALL slash commands including the 27 base commands failed to register. ## Fix Replace the nested Group layout with a single flat Command: /skill name:<autocomplete> args:<optional string> Autocomplete options are fetched dynamically by Discord when the user types — they do NOT count against the per-command registration budget. So this single command registers at ~200 bytes regardless of how many skills exist. Scales to thousands of skills with no size calculations, no splitting, no hidden skills. UX improvements: - Discord live-filters by user's typed prefix against BOTH name and description, so '/skill pdf' finds 'ocr-and-documents' via its description. More discoverable than clicking through category menus. - Unknown skill name → ephemeral error pointing user at autocomplete. - Stable alphabetical ordering across restarts. ## Why not the other proposed approaches Three prior PRs tried to fit within the 8KB limit by modifying the nested layout: - NousResearch#10214 (njiangk): truncated all descriptions to 'Run <name>' and category descriptions to 'Skills'. Works but destroys slash picker UX. - NousResearch#11385 (LeonSGP43): 40-char description clamp + iterative trim-largest-category fallback. Works but HIDES skills the user can no longer invoke via slash — functional regression. - NousResearch#10261 (zeapsu): adaptive split into /skill-<cat> top-level groups. Preserves all skills but pollutes the slash namespace with 20 top-level commands. All three work around the symptom. The flat autocomplete design dissolves the problem — there is no payload-size pressure to manage. ## Tests tests/gateway/test_discord_slash_commands.py — 5 new test cases replace the 3 old nested-structure tests: - flat-not-nested structure assertion - empty skills → no command registered - callback dispatches the right cmd_key by name - unknown name → ephemeral error, no dispatch - large-catalog regression guard (500 skills) — command payload stays under 500 bytes regardless E2E validated against real discord.py 2.7.1: - Command registers as discord.app_commands.Command (not Group). - Autocomplete filters by name AND description (verified across several queries including description-only matches like 'pdf' → OCR skill). - 500-skill catalog returns max 25 results per autocomplete query (Discord's hard cap), filtered correctly. - Choice labels formatted as 'name — description' clamped to 100 chars.
02356abc
pushed a commit
to 02356abc/hermes-agent
that referenced
this pull request
May 14, 2026
…trivially (NousResearch#11580) Closes NousResearch#11321, closes NousResearch#10259. ## Problem The nested /skill command group (category subcommand groups + skill subcommands) serialized to ~14KB with the default 75-skill catalog, exceeding Discord's ~8000-byte per-command registration payload. The entire tree.sync() rejected with error 50035 — ALL slash commands including the 27 base commands failed to register. ## Fix Replace the nested Group layout with a single flat Command: /skill name:<autocomplete> args:<optional string> Autocomplete options are fetched dynamically by Discord when the user types — they do NOT count against the per-command registration budget. So this single command registers at ~200 bytes regardless of how many skills exist. Scales to thousands of skills with no size calculations, no splitting, no hidden skills. UX improvements: - Discord live-filters by user's typed prefix against BOTH name and description, so '/skill pdf' finds 'ocr-and-documents' via its description. More discoverable than clicking through category menus. - Unknown skill name → ephemeral error pointing user at autocomplete. - Stable alphabetical ordering across restarts. ## Why not the other proposed approaches Three prior PRs tried to fit within the 8KB limit by modifying the nested layout: - NousResearch#10214 (njiangk): truncated all descriptions to 'Run <name>' and category descriptions to 'Skills'. Works but destroys slash picker UX. - NousResearch#11385 (LeonSGP43): 40-char description clamp + iterative trim-largest-category fallback. Works but HIDES skills the user can no longer invoke via slash — functional regression. - NousResearch#10261 (zeapsu): adaptive split into /skill-<cat> top-level groups. Preserves all skills but pollutes the slash namespace with 20 top-level commands. All three work around the symptom. The flat autocomplete design dissolves the problem — there is no payload-size pressure to manage. ## Tests tests/gateway/test_discord_slash_commands.py — 5 new test cases replace the 3 old nested-structure tests: - flat-not-nested structure assertion - empty skills → no command registered - callback dispatches the right cmd_key by name - unknown name → ephemeral error, no dispatch - large-catalog regression guard (500 skills) — command payload stays under 500 bytes regardless E2E validated against real discord.py 2.7.1: - Command registers as discord.app_commands.Command (not Group). - Autocomplete filters by name AND description (verified across several queries including description-only matches like 'pdf' → OCR skill). - 500-skill catalog returns max 25 results per autocomplete query (Discord's hard cap), filtered correctly. - Choice labels formatted as 'name — description' clamped to 100 chars.
gweeteve
pushed a commit
to gweeteve/hermes-agent
that referenced
this pull request
Jun 2, 2026
…trivially (NousResearch#11580) Closes NousResearch#11321, closes NousResearch#10259. ## Problem The nested /skill command group (category subcommand groups + skill subcommands) serialized to ~14KB with the default 75-skill catalog, exceeding Discord's ~8000-byte per-command registration payload. The entire tree.sync() rejected with error 50035 — ALL slash commands including the 27 base commands failed to register. ## Fix Replace the nested Group layout with a single flat Command: /skill name:<autocomplete> args:<optional string> Autocomplete options are fetched dynamically by Discord when the user types — they do NOT count against the per-command registration budget. So this single command registers at ~200 bytes regardless of how many skills exist. Scales to thousands of skills with no size calculations, no splitting, no hidden skills. UX improvements: - Discord live-filters by user's typed prefix against BOTH name and description, so '/skill pdf' finds 'ocr-and-documents' via its description. More discoverable than clicking through category menus. - Unknown skill name → ephemeral error pointing user at autocomplete. - Stable alphabetical ordering across restarts. ## Why not the other proposed approaches Three prior PRs tried to fit within the 8KB limit by modifying the nested layout: - NousResearch#10214 (njiangk): truncated all descriptions to 'Run <name>' and category descriptions to 'Skills'. Works but destroys slash picker UX. - NousResearch#11385 (LeonSGP43): 40-char description clamp + iterative trim-largest-category fallback. Works but HIDES skills the user can no longer invoke via slash — functional regression. - NousResearch#10261 (zeapsu): adaptive split into /skill-<cat> top-level groups. Preserves all skills but pollutes the slash namespace with 20 top-level commands. All three work around the symptom. The flat autocomplete design dissolves the problem — there is no payload-size pressure to manage. ## Tests tests/gateway/test_discord_slash_commands.py — 5 new test cases replace the 3 old nested-structure tests: - flat-not-nested structure assertion - empty skills → no command registered - callback dispatches the right cmd_key by name - unknown name → ephemeral error, no dispatch - large-catalog regression guard (500 skills) — command payload stays under 500 bytes regardless E2E validated against real discord.py 2.7.1: - Command registers as discord.app_commands.Command (not Group). - Autocomplete filters by name AND description (verified across several queries including description-only matches like 'pdf' → OCR skill). - 500-skill catalog returns max 25 results per autocomplete query (Discord's hard cap), filtered correctly. - Choice labels formatted as 'name — description' clamped to 100 chars.
Egavasyug
pushed a commit
to Egavasyug/hermes-agent
that referenced
this pull request
Jun 10, 2026
…trivially (NousResearch#11580) Closes NousResearch#11321, closes NousResearch#10259. ## Problem The nested /skill command group (category subcommand groups + skill subcommands) serialized to ~14KB with the default 75-skill catalog, exceeding Discord's ~8000-byte per-command registration payload. The entire tree.sync() rejected with error 50035 — ALL slash commands including the 27 base commands failed to register. ## Fix Replace the nested Group layout with a single flat Command: /skill name:<autocomplete> args:<optional string> Autocomplete options are fetched dynamically by Discord when the user types — they do NOT count against the per-command registration budget. So this single command registers at ~200 bytes regardless of how many skills exist. Scales to thousands of skills with no size calculations, no splitting, no hidden skills. UX improvements: - Discord live-filters by user's typed prefix against BOTH name and description, so '/skill pdf' finds 'ocr-and-documents' via its description. More discoverable than clicking through category menus. - Unknown skill name → ephemeral error pointing user at autocomplete. - Stable alphabetical ordering across restarts. ## Why not the other proposed approaches Three prior PRs tried to fit within the 8KB limit by modifying the nested layout: - NousResearch#10214 (njiangk): truncated all descriptions to 'Run <name>' and category descriptions to 'Skills'. Works but destroys slash picker UX. - NousResearch#11385 (LeonSGP43): 40-char description clamp + iterative trim-largest-category fallback. Works but HIDES skills the user can no longer invoke via slash — functional regression. - NousResearch#10261 (zeapsu): adaptive split into /skill-<cat> top-level groups. Preserves all skills but pollutes the slash namespace with 20 top-level commands. All three work around the symptom. The flat autocomplete design dissolves the problem — there is no payload-size pressure to manage. ## Tests tests/gateway/test_discord_slash_commands.py — 5 new test cases replace the 3 old nested-structure tests: - flat-not-nested structure assertion - empty skills → no command registered - callback dispatches the right cmd_key by name - unknown name → ephemeral error, no dispatch - large-catalog regression guard (500 skills) — command payload stays under 500 bytes regardless E2E validated against real discord.py 2.7.1: - Command registers as discord.app_commands.Command (not Group). - Autocomplete filters by name AND description (verified across several queries including description-only matches like 'pdf' → OCR skill). - 500-skill catalog returns max 25 results per autocomplete query (Discord's hard cap), filtered correctly. - Choice labels formatted as 'name — description' clamped to 100 chars.
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
/skillsubcommand descriptionsProblem
Discord slash command sync can fail with:
Command exceeds maximum size (8000)because skill descriptions pulled from
SKILL.mdare too verbose when registered under the/skillcommand group.Fix
Use minimal descriptions:
Run <skill>SkillsThis preserves usability while keeping the command tree within Discord's limits.
Validation
Observed local gateway failures before the patch:
Failed to upload commands to Discord (HTTP status 400, error code 50035)Command exceeds maximum size (8000)