Skip to content

feat: progressive disclosure with inputSchema stripping for idle context reduction (phase 1) - #616

Closed
kingpanther13 wants to merge 14 commits into
homeassistant-ai:masterfrom
kingpanther13:feat/tool-guides-progressive-disclosure
Closed

feat: progressive disclosure with inputSchema stripping for idle context reduction (phase 1)#616
kingpanther13 wants to merge 14 commits into
homeassistant-ai:masterfrom
kingpanther13:feat/tool-guides-progressive-disclosure

Conversation

@kingpanther13

@kingpanther13 kingpanther13 commented Feb 13, 2026

Copy link
Copy Markdown
Member

What does this PR do?

Implements progressive disclosure to reduce idle context token usage. Tool descriptions and inputSchema parameter descriptions are stripped to minimal skeletons, with full documentation served on-demand via ha_get_tool_guide(). A required guide_response parameter enforces that LLMs read the full docs before using any thinned tool.

This maintains MCP compliance — all tools remain in tools/list with typed parameters and native annotations. No tools are hidden, no string dispatch, no protocol-level changes.

The Problem

ha-mcp registers 94+ tools. Their combined definitions (descriptions + inputSchemas) consume ~35,500 tokens — 17.8% of Claude's context, 27.8% of GPT-4o's, and well over ChatGPT's hard 16K tool token limit (#614). This wastes significant context on every turn regardless of which tools are used.

The Solution: Thin Registration + Progressive Disclosure

For each thinned tool:

  1. Tool description → 1-2 sentence summary (was: multi-paragraph with examples, warnings, field lists)
  2. inputSchema parameter descriptions → stripped entirely (was: inline docs, examples, enums). Parameter names + types remain.
  3. guide_response required parameter → enforces that the LLM calls ha_get_tool_guide(topic) first and pastes the output
  4. ha_get_tool_guide(topic) → returns the full documentation on demand (restructured into JSON, same content)

All tools stay registered with MCP. Typed invocation preserved. Native annotations preserved.

Note: This is a breaking change for any existing client code that calls these 9 tools directly without guide_response. LLM-based clients will self-adapt (the error message tells them what to do), but any hardcoded integrations calling these tools will need to be updated to call ha_get_tool_guide() first and pass the result.

Context Flow

Before (master):
  Every LLM turn → ALL 94 tool definitions sent (~35K tokens idle)

After (fully migrated):
  Every LLM turn → 95 thin tool definitions sent (~8.5K tokens idle)

  LLM needs a tool → calls ha_get_tool_guide("topic") → gets full docs (1 turn)
  LLM uses the tool → passes guide_response + typed params (direct call)

Per-tool idle cost: ~375 tokens → ~70 tokens (81% reduction)

Why This Approach

Concern How it's addressed
Tools in tools/list Yes — all tools registered normally
Typed invocation Yes — direct calls with typed parameters
MCP annotations visible Yes — destructiveHint, readOnlyHint, etc. preserved
ChatGPT 16K tool limit (#614) ~8.5K tokens fully migrated — fits
LLM skips reading docs Required guide_response param prevents blind calls
Full docs preserved Yes — restructured into JSON, served via ha_get_tool_guide()
Existing client code Breaking — must add guide_response to calls for these 9 tools

Prior Art & References

Migration Roadmap

Phase 1 (this PR):  9 tools thinned   → ~30K tokens idle (from ~35K)
Phase 2:            +20 tools         → ~22K tokens idle
Phase 3:            +30 tools         → ~14K tokens idle
Phase 4:            remaining tools   →  ~8.5K tokens idle (final state)

Each phase: thin descriptions + strip inputSchema param descriptions + add guide_response + add guide content to _TOOL_GUIDES. No tool implementation code is modified at any phase. Tools with already-compact descriptions (like ha_get_overview) are excluded — progressive disclosure is only applied where it yields meaningful savings.

Phase 1 Tools (This PR)

Tool Guide Topic Type
ha_config_set_automation automation Create/Update
ha_config_set_dashboard dashboard Create/Update
ha_config_set_script script Create/Update
ha_set_entity entity Update
ha_get_history history Read
ha_get_statistics history Read
ha_search_entities search Read
ha_deep_search search Read
ha_eval_template template Read

Excluded from thinning: ha_get_overview — already compact (554 chars total incl. parameter descriptions), negligible savings vs. added friction for a quick discovery tool.

Content Preservation Guarantee

All stripped content is fully preserved and served on-demand. Nothing is deleted — only relocated.

  • Tool descriptions → moved to _TOOL_GUIDES dict, returned by ha_get_tool_guide(topic)
  • Parameter descriptions → moved to _TOOL_GUIDES dict under each topic's parameter/field documentation
  • Python transform security docs → preserved in _TOOL_GUIDES["dashboard"]["python_transform_security"]
  • Entity empty-string clearing behavior → preserved in _TOOL_GUIDES["entity"]["clearing_values"]
  • Examples, warnings, troubleshooting → preserved in guide examples, critical_guidance, troubleshooting sections

An LLM calling ha_get_tool_guide("automation") receives the exact same information that was previously in the tool description and parameter Field descriptions — structured as JSON for better parsing.

What Changed in Phase 1

Description thinning (already in initial PR):

  • 9 tool descriptions: 25,514 chars → 4,444 chars (83% reduction)
  • Full content relocated to _TOOL_GUIDES dict, restructured as JSON and served via ha_get_tool_guide()

inputSchema stripping (new):

  • Parameter Field(description=...) removed from all thinned tool parameters
  • Parameter names + types preserved (typed invocation maintained)
  • guide_response description shortened to ~8 words per tool

Enforcement:

  • guide_response required parameter on all 9 thinned tools
  • validate_guide_response() validates before execution (checks non-null, valid JSON dict, success: true, topic matches expected tool topic)
  • All thinned tool docstrings use consistent imperative pattern: REQUIRED: You MUST call ha_get_tool_guide("topic") before using this tool.
  • ha_get_tool_guide description explicitly lists all 9 tools it covers for AI discoverability
  • E2E tests auto-inject valid guide_response via _GuideInjectingClient

Changes

  • src/ha_mcp/tools/tools_utility.pyha_get_tool_guide() + _TOOL_GUIDES with full docs for 7 topics
  • src/ha_mcp/tools/util_helpers.pyvalidate_guide_response() shared helper
  • src/ha_mcp/tools/tools_config_automations.py — Thinned description + stripped inputSchema + guide_response
  • src/ha_mcp/tools/tools_config_dashboards.py — Thinned description + stripped inputSchema + guide_response
  • src/ha_mcp/tools/tools_config_scripts.py — Thinned description + stripped inputSchema + guide_response
  • src/ha_mcp/tools/tools_entities.py — Thinned description + stripped inputSchema + guide_response
  • src/ha_mcp/tools/tools_history.py — Thinned descriptions + stripped inputSchema + guide_response (2 tools)
  • src/ha_mcp/tools/tools_search.py — Thinned descriptions + stripped inputSchema + guide_response (2 tools); ha_get_overview excluded (kept at master)
  • README.md — Added ha_get_tool_guide to utility tools table
  • tests/src/e2e/conftest.py_GuideInjectingClient auto-injects guide_response for E2E tests
  • tests/src/unit/ — Updated unit tests with guide_response parameter (correct topic matching)

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Maintenance/refactor
  • Breaking change

Testing

  • I have tested these changes with a LLM agent
  • All automated tests pass (uv run pytest)
  • Code follows style guidelines (uv run ruff check)

Checklist

  • I have updated documentation if needed

References

…ntation

Move verbose tool descriptions (examples, field schemas, usage patterns) into
an on-demand ha_get_tool_guide(topic) meta-tool. Tool descriptions are trimmed
to essential summaries pointing to ha_get_tool_guide() for detailed guidance.

7 topics: automation, script, dashboard, template, entity, history, search.
Total description reduction: ~20,000+ chars across 10 tools.

Extracted from homeassistant-ai#579 for independent review.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @kingpanther13, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the efficiency of the Home Assistant toolset for LLMs by streamlining tool descriptions. It extracts detailed usage information into a new, dedicated ha_get_tool_guide meta-tool, which can be queried on demand. This change aims to reduce the initial context load for the LLM while ensuring comprehensive documentation remains accessible when needed, without altering any functional aspects of the tools.

Highlights

  • Tool Documentation Trimming: Verbose descriptions for 10 Home Assistant tools have been significantly shortened, reducing the idle context size by approximately 27,000 characters.
  • New ha_get_tool_guide Meta-Tool: A new meta-tool, ha_get_tool_guide(topic), has been introduced to provide on-demand, detailed documentation for specific tool topics, enabling progressive disclosure of information.
  • No Behavior Changes: This pull request focuses solely on documentation and context optimization, with no modifications to runtime behavior, response formats, or default settings of the existing tools.
Changelog
  • src/ha_mcp/tools/tools_config_automations.py
    • Shortened the docstring for ha_config_set_automation to refer to ha_get_tool_guide('automation').
  • src/ha_mcp/tools/tools_config_dashboards.py
    • Shortened the docstring for ha_config_set_dashboard to refer to ha_get_tool_guide('dashboard').
  • src/ha_mcp/tools/tools_config_scripts.py
    • Shortened the docstring for ha_config_set_script to refer to ha_get_tool_guide('script').
  • src/ha_mcp/tools/tools_entities.py
    • Shortened the docstring for ha_set_entity to refer to ha_get_tool_guide('entity').
  • src/ha_mcp/tools/tools_history.py
    • Shortened the docstring for ha_get_history to refer to ha_get_tool_guide('history').
    • Shortened the docstring for ha_get_statistics to refer to ha_get_tool_guide('history').
  • src/ha_mcp/tools/tools_search.py
    • Shortened the docstring for ha_search_entities to refer to ha_get_tool_guide('search').
    • Shortened the docstring for ha_get_overview.
    • Shortened the docstring for ha_deep_search to refer to ha_get_tool_guide('search').
  • src/ha_mcp/tools/tools_utility.py
    • Added Annotated and Field imports for type hinting.
    • Shortened the docstring for ha_eval_template to refer to ha_get_tool_guide('template').
    • Implemented a new meta-tool ha_get_tool_guide for on-demand access to detailed tool documentation.
    • Defined _TOOL_GUIDES dictionary containing comprehensive usage guides for various tool topics.
Activity
  • No specific pull request activity (comments, reviews, or progress updates) was provided in the context.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request is an excellent application of the progressive disclosure principle outlined in the repository style guide (lines 131-135). By trimming verbose tool descriptions and introducing a new ha_get_tool_guide meta-tool, this change should significantly reduce the idle context size for the language model. The implementation is clean and effective. I have one high-severity suggestion for the new tool's error handling to ensure full compliance with the repository's structured error response guidelines.

Comment thread src/ha_mcp/tools/tools_utility.py Outdated
@kingpanther13 kingpanther13 changed the title feat: add ha_get_tool_guide for progressive disclosure of tool docs feat: reduce tool idle context usage/description length, add ha_get_tool_guide for progressive disclosure of tool docs Feb 13, 2026
claude and others added 7 commits February 13, 2026 08:11
…tructured errors

- Add ALL missing content from original tool descriptions to _TOOL_GUIDES
  (update examples, use cases, parameter details, string/conditional ops, etc.)
- Strengthen tool descriptions: "REQUIRED: You MUST call ha_get_tool_guide()"
  to maximize LLM compliance with progressive disclosure pattern
- Fix error handling in ha_get_tool_guide() to use create_error_response with
  ErrorCode.RESOURCE_NOT_FOUND per Gemini code review and repo style guide
- Add import for ErrorCode and create_error_response from errors module
- Ensure zero information loss: every detail from original descriptions exists
  in either the trimmed description or the corresponding tool guide

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add required guide_response parameter to all 10 tools that reference
ha_get_tool_guide(). This uses homeassistant-ai#363-level structural enforcement via
parameter schema — LLMs treat required params as API contracts they
cannot bypass, even when instructed to skip them.

Tools updated: ha_config_set_automation, ha_config_set_dashboard,
ha_config_set_script, ha_set_entity, ha_get_history, ha_get_statistics,
ha_search_entities, ha_get_overview, ha_deep_search, ha_eval_template.

Shared validate_guide_response() helper in util_helpers.py validates
that the response is a successful JSON output from ha_get_tool_guide().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add _GuideInjectingClient wrapper to conftest that auto-injects
a valid guide_response for tools that require it. This avoids
modifying 35+ test files while ensuring all E2E tests pass with
the new required parameter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update unit tests to include required guide_response parameter
for all direct tool function calls (ha_config_set_script,
ha_set_entity, ha_config_set_automation).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kingpanther13
kingpanther13 marked this pull request as ready for review February 13, 2026 14:22
@kingpanther13
kingpanther13 enabled auto-merge (squash) February 13, 2026 17:36
@sergeykad

Copy link
Copy Markdown
Collaborator

@kingpanther13 ,you have to test that it works correctly with LLMs after all the changes

@kingpanther13

Copy link
Copy Markdown
Member Author

@sergeykad yeah I need to get a test environment together again to experiment...I won't be able to do that till tomorrow. However I will say that I use this method on my Hubitat MCP and it seems to work fine w/Claude.ai and Claude code.

Resolve conflict in tools_search.py: combine imports from both branches
(coerce_int_param from master + validate_guide_response from PR branch).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
kingpanther13 added a commit to kingpanther13/ha-mcp-fork that referenced this pull request Feb 14, 2026
Summary of research into approaches for reducing the ~35K token idle
cost of 96 tool definitions. Key finding: proxy/meta-tool patterns
(Tool Search, Semantic Search) add round trips but save ~93% tokens
overall because the dominant cost is idle tool definitions on every
turn, not the occasional schema lookup.

Covers: PR homeassistant-ai#616, tool search proxy, semantic search, hybrid core+proxy,
dynamic registration, defer_loading, ENABLED_TOOL_MODULES.

Related: homeassistant-ai#614, homeassistant-ai#567, homeassistant-ai#605, PR homeassistant-ai#616

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kingpanther13

Copy link
Copy Markdown
Member Author

Closing in favor of a more comprehensive approach

After further research, I've determined that even fully expanding this PR to all 96 tools wouldn't sufficiently solve the core problem. The tool descriptions account for ~48% of idle token cost, but parameter schemas account for another ~41% (~18K tokens). Even with zero description text, 96 tool registrations still exceed ChatGPT's 16K tool token limit (issue #614).

What we're doing instead: Implementing the Tool Search Proxy pattern — the same server-side pattern recommended by Anthropic and independently validated by Speakeasy (100x token reduction on 400-tool servers). Three meta-tools (ha_find_tools, ha_get_tool_details, ha_execute_tool) replace the 96 direct registrations. Tool descriptions remain completely intact server-side — they're returned on-demand by ha_get_tool_details.

Key advantages over this PR:

  • ~95% token reduction (3 tools idle vs 96) — vs ~24% from this PR
  • Solves ChatGPT 16K limit — this PR cannot, even fully expanded
  • All tools protected — structural enforcement via required tool_schema param on execute (same principle as guide_response but universal)
  • Works with all LLMs — standard MCP tool calls, no special features needed
  • No tool descriptions modified — they live verbatim in server-side registry

Will be implemented incrementally — first PR moves 10 niche tools to proxy, subsequent PRs migrate the rest in batches.

References:

auto-merge was automatically disabled February 14, 2026 20:02

Pull request was closed

@kingpanther13 kingpanther13 reopened this Feb 15, 2026
@kingpanther13
kingpanther13 requested a review from a team February 15, 2026 04:16
@kingpanther13
kingpanther13 marked this pull request as draft February 15, 2026 04:16
@kingpanther13 kingpanther13 changed the title feat: reduce tool idle context usage/description length, add ha_get_tool_guide for progressive disclosure of tool docs feat: progressive disclosure with inputSchema stripping for idle context reduction (phase 1) Feb 15, 2026
Remove Field(description=...) from all parameters of the 10 Phase 1
thinned tools. Parameter names and types are preserved for typed
invocation. Full parameter documentation is already available via
ha_get_tool_guide() and the guide_response enforcement ensures LLMs
read it before calling.

Shortened guide_response descriptions from ~30 words to ~8 words.
Removed get_security_documentation() concatenation from dashboard
python_transform parameter.

This reduces per-tool idle schema cost from ~375 tokens to ~70 tokens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kingpanther13

Copy link
Copy Markdown
Member Author

Why This PR Was Reopened

This PR was originally closed while I explored a more aggressive approach — a server-side Tool Search Proxy (#627) that removed tools from tools/list entirely and routed them through 3 meta-tools (ha_find_tools, ha_get_tool_details, ha_execute_tool).

After thorough review and discussion, the proxy approach raised legitimate MCP compliance concerns:

  1. Proxied tools vanish from tools/list — breaks standard MCP discovery
  2. Typed invocation replaced by opaque string dispatch via ha_execute_tool
  3. Tool annotations hidden from MCP clients at the protocol level

This PR's approach avoids all three issues. Tools stay in tools/list with typed parameters and native annotations. No string dispatch, no custom discovery protocol.

What's New Since Closing

The original PR only thinned tool descriptions (Phase 1 of the progressive disclosure pattern). After analysis, I identified that inputSchema parameter descriptions are a major additional source of token bloat — especially on tools like ha_config_set_dashboard where python_transform and jq_transform had massive inline examples and documentation.

New in this reopening:

  • inputSchema parameter descriptions stripped from all 10 Phase 1 tools — Field(description=...) removed, parameter names + types preserved
  • guide_response descriptions shortened from ~30 words to ~8 words each
  • Topic validation added to validate_guide_response() — now verifies the guide topic matches the expected tool (previously any guide passed validation on any tool)
  • PR description rewritten with phased migration roadmap (Phase 1→4, targeting ~8.5K tokens at full migration)
  • Honest breaking change disclosureguide_response is a required parameter, which breaks existing direct callers

Token impact (Phase 1):

  • Description thinning: 25,826 → 4,602 chars (82% reduction on those tools)
  • inputSchema stripping: additional ~6,400 tokens saved across the 10 tools
  • Combined idle context: ~35K → ~30K tokens (Phase 1), targeting ~8.5K at full migration

The phased approach validates the pattern on 10 tools before expanding. Each subsequent phase is straightforward — thin descriptions, strip schemas, add guide content, add guide_response.

Resolved import conflicts in 5 tool files — adopted master's multi-line
import formatting while keeping validate_guide_response imports needed
by the progressive disclosure pattern.

Also fixes validate_guide_response() to check topic matches expected_topic,
and updates ha_get_tool_guide to set the canonical topic key in responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
kingpanther13 and others added 3 commits February 14, 2026 23:55
- Add python_transform_security to dashboard guide (ALLOWED/FORBIDDEN
  operations that were previously appended via get_security_documentation())
- Add clearing_values to entity guide (empty string '' behavior for
  area_id, name, icon that was in stripped Field descriptions)

Ensures all content stripped from inputSchema is fully preserved
and served on-demand via ha_get_tool_guide().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
guide_response=_GR was placed outside function call parentheses
during conflict resolution, causing syntax/runtime errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix 4 unit tests: add correct guide_response with matching topic
  (test_deep_search_error_handling, test_tools_entities,
  test_tools_config_scripts, test_wait_parameter)
- Standardize 3 config tool docstrings to use imperative
  "REQUIRED: You MUST call ha_get_tool_guide()" pattern matching the
  other 7 thinned tools (automation, dashboard, script)
- Exclude ha_get_overview from progressive disclosure: its description
  is already compact (554ch total) so thinning yields negligible savings
  while adding guide_response friction to a quick discovery tool
- Enrich ha_get_tool_guide description with explicit tool names and
  topic keywords for better AI discoverability across all models

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kingpanther13

Copy link
Copy Markdown
Member Author

BAT (Bot Acceptance Testing) Results — 3-Way Comparison

Tested with Claude Sonnet 4.5 against a live Home Assistant instance (192.168.1.150:8123). Prompt: "Search for light entities in my HA, which are on right now?"

Comparison Table

Metric Master (baseline) PR #616 Blind PR #616 Guided
Turns 3 6 4
API time (ms) 20,715 33,016 (+59%) 26,780
Cost (USD) $0.1326 $0.2691 (+103%) $0.2870
Input tokens 33,819 107,614 88,414
Output tokens 2,310 4,498 3,734
Cache read tokens 36,017 54,009 52,012
Total tokens 73,098 186,178 (+155%) 161,247
MCP tool calls 1 2 2
Total tool calls 2 6 4

Blind = no hint about the guide workflow; Guided = prompt includes "use ha_get_tool_guide first"

Key Finding: Claude Discovers the Guide Workflow Naturally

In the blind test, Claude did NOT try-and-fail. It:

  1. ToolSearch("home assistant search entities") → found ha_search_entities
  2. Read the thinned description, saw REQUIRED: You MUST call ha_get_tool_guide("search")
  3. ToolSearch("select:mcp__home-assistant__ha_get_tool_guide") → loaded guide tool
  4. ha_get_tool_guide(topic="search") → got full search docs
  5. ha_search_entities(... guide_response=...) → executed search

The guide requirement text in the tool description is sufficient for Claude to discover and follow the workflow without any external prompting.

Idle Context Savings (the real win)

The per-task token comparison above doesn't show the main benefit. The real savings are in idle context per turn:

Metric Master PR #616 Savings
9 thinned tool descriptions + params 25,514 chars (~6,379 tk) 4,444 chars (~1,111 tk) ~5,268 tokens/turn (83%)
ha_get_tool_guide (new tool) 0 ~99 tk -99 tk
Net per-turn ~5,169 tokens saved

Over a 10-turn conversation, that's ~50K tokens of idle context eliminated. This is Phase 1 — fully migrated savings will be much larger.

Tool-by-Tool Breakdown

Tool Master (chars) PR #616 (chars) Reduction
ha_config_set_automation 4,606 497 89%
ha_config_set_dashboard 4,885 570 88%
ha_eval_template 4,115 500 88%
ha_config_set_script 3,699 412 89%
ha_get_statistics 2,347 461 80%
ha_get_history 1,830 400 78%
ha_set_entity 1,742 483 72%
ha_deep_search 1,197 419 65%
ha_search_entities 1,093 390 64%

ha_get_overview excluded — already compact (554 chars total), negligible savings vs. added friction.

Topic Validation

validate_guide_response() now enforces topic matching — a guide for "search" will NOT pass validation on the "automation" tool. Each thinned tool validates that the guide topic matches its expected topic. This prevents lazy reuse of cached guide responses across different tool categories.

Additional Changes in Latest Commit

  • Consistent docstring pattern: All 9 thinned tools now use the same imperative REQUIRED: You MUST call ha_get_tool_guide("topic") pattern (3 config tools previously used softer wording)
  • Enriched ha_get_tool_guide description: Explicitly lists all 9 covered tools + topic keywords for better AI discoverability across all model providers
  • Fixed 4 unit tests: Added correct guide_response with matching topic to test fixtures

@sergeykad

Copy link
Copy Markdown
Collaborator

Honestly, I'm not sure if it's worth it. You pay fewer tokens upfront, but a simple check for lights ate 70k more tokens. IIRC, the whole idle cost is about 35k, so no reduction of the idle context can offset the increased call costs.

@julienld

Copy link
Copy Markdown
Member

Interesting. Not sure what to think. Caching might not be taken into account here. I removed caching from the BAT skill because it was adding noise to the results, but we might need it here.

@julienld

Copy link
Copy Markdown
Member

There might also be a tradeoff between speed and cost. We should add back time elapsed and token cache metrics to the skill.

@kingpanther13

Copy link
Copy Markdown
Member Author

Time elapsed is definitely slightly more, but overall token cost/context usage over time is less because we're reducing the idle context even with extra trips. It'll be more apparent when more tools are transitioned over.

@julienld

Copy link
Copy Markdown
Member

Maybe do that with tools used less often? We save context with the least used tools and keep the most used tools in context.

We need telemetry.

@kingpanther13

Copy link
Copy Markdown
Member Author

It'll show better savings when we have more tools copied over. I realized it'll be better to exclude many of the tools that already have a short description , and to exclude some of the more important ones, so yeah focusing on less used tools is likely what I'll do. This is still very much a WIP, I'll be doing a lot more fiddling around before I mark it as ready.

Also I realized some of my tests activated my other MCPs without warning me so the tokens above are likely not accurate. Will test more soon.

I am also toying with the idea of doing #627 much more scaled down, like doing a proxy thing for certain categories only, for example combining all zone tools into one and doing the proxy method so their original descriptions aren't messed up.

@kingpanther13

Copy link
Copy Markdown
Member Author

OK I did more testing using Gemini this time, This looks more promising. I will let you figure out how you feel about it. I will keep tinkering with it when I can, I'm not sure if I like this better or what I came up with in #637.

BAT Results: Progressive Disclosure (PR #616) vs Master

Tested with Gemini 3 Pro Preview against HA 2026.1.3 test container. All tests run without any hints about the
guide_response pattern — Gemini navigated it autonomously from thin tool descriptions alone.

Test 1: Idle Context (non-thinned tools only)

Uses only ha_get_state and ha_call_service — measures the cost of tool definitions sitting idle.

Metric Master PR #616 Delta
All passed Yes Yes --
API requests 5 5 0
Tool calls 4 4 0
Input tokens 35,052 51,184 +16,132 (+46%)
Prompt tokens 146,637 118,078 -28,559 (-19%)
Cached tokens 111,585 66,894 -44,691
Total tokens 147,244 118,687 -28,557 (-19%)
Thought tokens 380 452 +72
Latency 22,518ms 22,584ms ~same

Takeaway: When thinned tools aren't used, PR saves ~28K prompt tokens (-19%) per session from smaller tool
definitions alone.

Test 2: All 10 Thinned Tools Exercised

Exercises every thinned tool: ha_search_entities, ha_get_overview, ha_deep_search, ha_get_history,
ha_get_statistics, ha_eval_template, ha_set_entity, ha_config_set_automation, ha_config_set_script,
ha_config_set_dashboard — plus cleanup.

Metric Master PR #616 Delta
All passed Yes Yes --
API requests 9 8 -1
Tool calls 20 22 (+7 guide) +2
Tool success/fail 18/2 (90%) 22/0 (100%) PR more reliable
Input tokens 103,908 69,049 -34,859 (-34%)
Prompt tokens 263,032 216,026 -47,006 (-18%)
Cached tokens 159,124 146,977 -12,147
Total tokens 267,223 220,066 -47,157 (-18%)
Thought tokens 3,271 3,005 -266
Latency 64,906ms 59,181ms -5,725ms (-9%)

Takeaway: Even when all 10 thinned tools are used in a single session, PR still saves ~47K total tokens
(-18%)
. Guides are loaded once and cached across turns, while master sends verbose descriptions on every turn. PR
also achieved 100% tool call success vs master's 90%.

Summary

Scenario Prompt token savings Total token savings Reliability
Idle (no thinned tools used) -19% -19% Same
All 10 thinned tools active -18% -18% PR better (100% vs 90%)
  • Gemini 3 Pro navigates the guide_response pattern without any prompting or hints
  • No latency regression — slightly faster in the all-tools test
  • Phase 1 only thins 10 of 96 tools; full migration targets ~76% idle reduction

Key Takeaways

  1. Idle context: PR saves ~28K prompt tokens (-19%) when no thinned tools are used. The thinner tool definitions work
    as intended.
  2. All 10 tools active: PR saves ~47K total tokens (-18%) even when all thinned tools are exercised. The guide pattern
    is more efficient than the verbose inline descriptions, because guides are loaded once and cached, while master sends
    the full descriptions on every turn.
  3. Reliability improved: PR had 22/22 tool calls succeed (100%) vs master's 18/20 (90%). The guide gives Gemini better
    structured reference to follow for complex tools like ha_config_set_automation.
  4. No hint needed: Gemini 3 Pro navigates the guide_response pattern without any prompting about it.
  5. Latency: Roughly the same or slightly faster on the PR branch.

@kingpanther13

Copy link
Copy Markdown
Member Author

I'm going to close this one again in favor of #637, but will reopen if we need more context reduction in the future or if either of you want it. I think the extra calls and latency kinda kill it, but it's a good trick if we really need to reduce context usage further on any single tools.

kingpanther13 added a commit to kingpanther13/ha-mcp-fork that referenced this pull request Feb 21, 2026
Research and conversation transcript exploring idle context reduction
using FastMCP 3.0's Provider call_tool() with session state. Documents
prior approaches (homeassistant-ai#616, homeassistant-ai#637), FastMCP 3.0 features investigated
(Provider, Transforms, Visibility, SkillsProvider), and the first-call
docs concept that forces documentation delivery on first tool use per
session.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] error while connecting to openAI chat GPT

4 participants