feat(skills): remote-only tag hides skills from local endpoints (#6693)

Skills tagged remote-only in frontmatter are excluded from the injected
skill index when the active model's endpoint is local (loopback/private/
tailscale per is_local_endpoint). Big on-demand reference lookups
overwhelm small local contexts; local models never see the skill, while
remote models and API/UI listings are unaffected.

- SkillsManager.index_for gains optional keyword-only local_model flag
  (None = don't gate, same contract as active_toolsets=None)
- _build_system_prompt/_build_base_prompt thread endpoint_url from
  _build_route_request_state; unknown endpoint fails open
- tests: cover hidden-on-local, visible-on-remote/unknown, untagged
  skills never gated

Refs: discussed for the local-model overwhelm problem

Co-authored-by: Alexandre Teixeira <111787685+alteixeira20@users.noreply.github.com>
This commit is contained in:
zai184
2026-10-13 23:15:21 +01:00
committed by GitHub
co-authored by Alexandre Teixeira
parent f902be18f7
commit 86b886c611
3 changed files with 114 additions and 1 deletions
+6
View File
@@ -674,6 +674,7 @@ class SkillsManager:
*,
active_toolsets: Optional[List[str]] = None,
platform: Optional[str] = None,
local_model: Optional[bool] = None,
) -> List[Dict]:
"""Return the `[{name, description, category, status}]` list the
agent sees in its system prompt.
@@ -710,6 +711,11 @@ class SkillsManager:
# Platform gating
if platform and s.get("platforms") and platform not in s["platforms"]:
continue
# remote-only tag: hide from local/private-endpoint models. Big
# on-demand reference lookups overwhelm small local contexts.
# local_model=None (API listings, UI) never gates.
if local_model and "remote-only" in (s.get("tags") or []):
continue
# requires_toolsets: hide unless every required toolset is active.
# active_toolsets=None means the caller doesn't know the active
# set (API listings, chat preface) — don't gate in that case;