Skip to content

feat(cli): add /tokens slash command for system prompt token breakdown - #48470

Closed
RemyFevry wants to merge 1 commit into
NousResearch:mainfrom
RemyFevry:feat/token-breakdown
Closed

feat(cli): add /tokens slash command for system prompt token breakdown#48470
RemyFevry wants to merge 1 commit into
NousResearch:mainfrom
RemyFevry:feat/token-breakdown

Conversation

@RemyFevry

Copy link
Copy Markdown
Contributor

feat: Add /tokens slash command for system prompt token breakdown

Summary

New /tokens command that shows exactly how many tokens each component of the system prompt consumes — identity, skills index, memory, user profile, tool schemas, environment hints, platform hints, and more.

This fills a visibility gap: /usage shows aggregate session tokens, but not where the tokens go in the system prompt itself. Users optimizing context budgets (e.g., trimming skills, managing memory size) had no way to measure the cost of each component.

What it does

Running /tokens produces a table like:

🔍 System Prompt Token Breakdown
──────────────────────────────────────────────────────────
Component                           Tokens       %
──────────────────────────────────────────────────────────
Skills Index                         3,680    72.7%
Tool Behavioral Guidance               499     9.9%
Task Completion Guidance               192     3.8%
Hermes Help Guidance                   140     2.8%
Steer Channel Note                     170     3.4%
Identity (default)                     128     2.5%
Platform Hint                          120     2.4%
Active Profile Hint                     77     1.5%
Timestamp / Session Info                24     0.5%
Environment Hints                       23     0.5%
──────────────────────────────────────────────────────────
System Prompt Total                  5,065
Tool Schemas                            49
──────────────────────────────────────────────────────────
Grand Total                          5,114
──────────────────────────────────────────────────────────
Context window:                    128,000
Used:                                 4.0%

Changes

agent/system_prompt.py (+242 lines)

  • build_system_prompt_breakdown(agent, system_message) — returns list[tuple[str, str]] of labeled components, mirroring the assembly logic of build_system_prompt_parts() but keeping each segment individually labeled
  • estimate_tokens(text) — uses tiktoken (cl100k_base) when installed, falls back to chars // 4

hermes_cli/commands.py (+1 line)

  • Registers CommandDef("tokens", ...) in the Info category

cli.py (+72 lines)

  • _show_token_breakdown() method — builds the breakdown, counts tokens per component, formats and prints the table
  • Wired in process_command() as elif canonical == "tokens"

Design decisions

  1. No new dependenciestiktoken is optional. Falls back to character-based estimate when not installed.
  2. Plain text output — works identically in CLI, TUI, and gateway/messaging platforms (WhatsApp, Telegram).
  3. Sorted by size — largest token consumers shown first, so users immediately see what to trim.
  4. Separate tool schema count — tool schemas aren't part of the system prompt string but consume context; shown separately for completeness.

Testing

Verified with a mock agent containing 6 tools, memory enabled, skills enabled:

Total components: 12
GRAND TOTAL: 5,114 tokens
SUCCESS - breakdown works!

Adds build_system_prompt_breakdown() in agent/system_prompt.py that returns
labeled (label, text) pairs for each component of the system prompt. Mirrors
the assembly logic of build_system_prompt_parts() but keeps segments
individually labeled instead of merging into coarse tiers.

Adds /tokens command in cli.py that displays a formatted table showing token
counts per component (identity, skills, memory, user profile, tool schemas,
environment hints, platform hints, etc.), sorted by size.

Uses tiktoken (cl100k_base) for accurate counting when available, falls back
to chars/4 estimate. No hard dependency added.

Works in CLI, TUI, and gateway/messaging platforms (plain text output).
@RemyFevry
RemyFevry force-pushed the feat/token-breakdown branch from a355fa4 to a23b4b7 Compare June 18, 2026 14:55
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard labels Jun 18, 2026

@teknium1 teknium1 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.

Thanks for the useful prompt-budget visibility proposal. Current main now has a shared context-breakdown engine, but this version needs rework before it can provide reliable component accounting.

Problems

  • agent/system_prompt.py:461 adds a second prompt assembler. Current assembly has since gained blocks and resolution paths, including PARALLEL_TOOL_CALL_GUIDANCE at agent/system_prompt.py:216 and platform-hint resolution at agent/system_prompt.py:432; the copied helper will therefore report totals that can differ from the actual provider prompt.
  • cli.py:8419 returns when self.agent is absent. The TUI slash worker has no live CLI agent (cli.py:9629-9637), so the claimed TUI support cannot produce a breakdown.
  • The diff adds no tests for the new accounting or either rendering path.

Suggested changes

  • Extend the shared agent/context_breakdown.py path, or derive labelled output directly from the real prompt builder, so every reported component comes from the same assembly source.
  • Route TUI through its live gateway-session breakdown path, and add tests for conditional prompt blocks plus CLI, gateway, and TUI dispatch.

This is an automated hermes-sweeper review.

Comment thread agent/system_prompt.py
return json.dumps(formatted_tools, ensure_ascii=False)


def build_system_prompt_breakdown(agent: Any, system_message: Optional[str] = None) -> list[tuple[str, str]]:

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.

This duplicates the prompt assembler, so it will drift as soon as a new prompt block or resolution path lands. Current main already has additions such as parallel-tool-call guidance and configured platform-hint resolution that this copied path would not count. Please derive labelled segments from the same source used to build the emitted prompt.

Comment thread cli.py
(identity, skills, memory, tools, etc.) so users can see exactly
where their context budget goes. Works in CLI, TUI, and gateway.
"""
if not self.agent:

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.

This prevents the stated TUI support: the TUI slash worker invokes CLI command handling without a live self.agent (documented by the existing /usage implementation), so /tokens will only print the no-active-agent message. Use the TUI gateway session's live-agent path or scope this command away from TUI.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 14, 2026
teknium1 added a commit that referenced this pull request Jul 26, 2026
Extends the cherry-picked /context command (PR #52184) and prompt-size
attribution helpers (PR #66656) into one visual context view across
surfaces, and absorbs the per-component budget-visibility goal of the
/tokens proposal (PR #48470):

- agent/context_breakdown.py: pure renderers over the existing payload —
  a 5x20 glyph block grid (1 cell ~= 1% of the model window), an
  'Estimated usage by category' table with free space, and expanded
  per-skill / per-toolset listings via compute_context_details(), which
  reuses the prompt-size attribution mechanism (skills index-line bytes +
  registry tool->toolset map) converted to the same chars/4 heuristic.
- cli.py: /context [all] renders grid + category table (+ expanded
  listings) from the live agent and in-memory conversation history.
- gateway/slash_commands.py: /context appends the plain-text category
  table (no grid — monospace not guaranteed on messaging platforms);
  /context all adds the expanded listings. Fail-open: breakdown errors
  never break the gauge.
- hermes_cli/commands.py: /context gains the 'all' subcommand; /version
  demoted to /hermes version on Slack to keep the 50-slash cap.
- tests: renderer unit tests against synthetic payloads, registry test,
  gateway /context + /context all + failure-degradation handler tests.
- docs: slash-commands reference + CLI guide entries.

Read-only and locally computed: no provider calls, no prompt-cache impact.

Co-authored-by: RemyFevry <29257684+RemyFevry@users.noreply.github.com>
Co-authored-by: joelbrilliant <joelbrilliant1@gmail.com>
Co-authored-by: CharlesMcquade <6466275+CharlesMcquade@users.noreply.github.com>
teknium1 added a commit that referenced this pull request Jul 27, 2026
Extends the cherry-picked /context command (PR #52184) and prompt-size
attribution helpers (PR #66656) into one visual context view across
surfaces, and absorbs the per-component budget-visibility goal of the
/tokens proposal (PR #48470):

- agent/context_breakdown.py: pure renderers over the existing payload —
  a 5x20 glyph block grid (1 cell ~= 1% of the model window), an
  'Estimated usage by category' table with free space, and expanded
  per-skill / per-toolset listings via compute_context_details(), which
  reuses the prompt-size attribution mechanism (skills index-line bytes +
  registry tool->toolset map) converted to the same chars/4 heuristic.
- cli.py: /context [all] renders grid + category table (+ expanded
  listings) from the live agent and in-memory conversation history.
- gateway/slash_commands.py: /context appends the plain-text category
  table (no grid — monospace not guaranteed on messaging platforms);
  /context all adds the expanded listings. Fail-open: breakdown errors
  never break the gauge.
- hermes_cli/commands.py: /context gains the 'all' subcommand; /version
  demoted to /hermes version on Slack to keep the 50-slash cap.
- tests: renderer unit tests against synthetic payloads, registry test,
  gateway /context + /context all + failure-degradation handler tests.
- docs: slash-commands reference + CLI guide entries.

Read-only and locally computed: no provider calls, no prompt-cache impact.

Co-authored-by: RemyFevry <29257684+RemyFevry@users.noreply.github.com>
Co-authored-by: joelbrilliant <joelbrilliant1@gmail.com>
Co-authored-by: CharlesMcquade <6466275+CharlesMcquade@users.noreply.github.com>
teknium1 added a commit that referenced this pull request Jul 27, 2026
Extends the cherry-picked /context command (PR #52184) and prompt-size
attribution helpers (PR #66656) into one visual context view across
surfaces, and absorbs the per-component budget-visibility goal of the
/tokens proposal (PR #48470):

- agent/context_breakdown.py: pure renderers over the existing payload —
  a 5x20 glyph block grid (1 cell ~= 1% of the model window), an
  'Estimated usage by category' table with free space, and expanded
  per-skill / per-toolset listings via compute_context_details(), which
  reuses the prompt-size attribution mechanism (skills index-line bytes +
  registry tool->toolset map) converted to the same chars/4 heuristic.
- cli.py: /context [all] renders grid + category table (+ expanded
  listings) from the live agent and in-memory conversation history.
- gateway/slash_commands.py: /context appends the plain-text category
  table (no grid — monospace not guaranteed on messaging platforms);
  /context all adds the expanded listings. Fail-open: breakdown errors
  never break the gauge.
- hermes_cli/commands.py: /context gains the 'all' subcommand; /version
  demoted to /hermes version on Slack to keep the 50-slash cap.
- tests: renderer unit tests against synthetic payloads, registry test,
  gateway /context + /context all + failure-degradation handler tests.
- docs: slash-commands reference + CLI guide entries.

Read-only and locally computed: no provider calls, no prompt-cache impact.

Co-authored-by: RemyFevry <29257684+RemyFevry@users.noreply.github.com>
Co-authored-by: joelbrilliant <joelbrilliant1@gmail.com>
Co-authored-by: CharlesMcquade <6466275+CharlesMcquade@users.noreply.github.com>
@teknium1

Copy link
Copy Markdown
Contributor

The /tokens system-prompt breakdown idea landed via #72242 (now merged), folded into the unified /context command with credit. Thanks!

@teknium1 teknium1 closed this Jul 27, 2026
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
Extends the cherry-picked /context command (PR NousResearch#52184) and prompt-size
attribution helpers (PR NousResearch#66656) into one visual context view across
surfaces, and absorbs the per-component budget-visibility goal of the
/tokens proposal (PR NousResearch#48470):

- agent/context_breakdown.py: pure renderers over the existing payload —
  a 5x20 glyph block grid (1 cell ~= 1% of the model window), an
  'Estimated usage by category' table with free space, and expanded
  per-skill / per-toolset listings via compute_context_details(), which
  reuses the prompt-size attribution mechanism (skills index-line bytes +
  registry tool->toolset map) converted to the same chars/4 heuristic.
- cli.py: /context [all] renders grid + category table (+ expanded
  listings) from the live agent and in-memory conversation history.
- gateway/slash_commands.py: /context appends the plain-text category
  table (no grid — monospace not guaranteed on messaging platforms);
  /context all adds the expanded listings. Fail-open: breakdown errors
  never break the gauge.
- hermes_cli/commands.py: /context gains the 'all' subcommand; /version
  demoted to /hermes version on Slack to keep the 50-slash cap.
- tests: renderer unit tests against synthetic payloads, registry test,
  gateway /context + /context all + failure-degradation handler tests.
- docs: slash-commands reference + CLI guide entries.

Read-only and locally computed: no provider calls, no prompt-cache impact.

Co-authored-by: RemyFevry <29257684+RemyFevry@users.noreply.github.com>
Co-authored-by: joelbrilliant <joelbrilliant1@gmail.com>
Co-authored-by: CharlesMcquade <6466275+CharlesMcquade@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants