[arnav] disable Claude Code's bundled plugin skills in agent sessions

Pass `skills=[]` to ClaudeAgentOptions so the SDK's built-in plugin
skills (/init, /review, /security-review, /simplify, /loop, /schedule,
/update-config, /keybindings-help, /fewer-permission-prompts,
/claude-api) are hidden from the model and rejected by the Skill tool.
These skills are inappropriate in OpenSwarm: half mutate ~/.claude
config files (settings.json, keybindings.json) that OpenSwarm doesn't
read, and the rest expose slash commands the backend never intercepts —
causing the model to falsely claim capabilities it can't actually use.
OpenSwarm's own skills system injects skill content directly into the
user prompt via _resolve_attached_skills, bypassing the Skill tool
entirely, so user-attached skills are unaffected.
Also adds a regression test that pins the `skills=[]` assignment so it
can't be silently dropped in a future refactor.
This commit is contained in:
Arnav Naval
2026-05-09 10:36:15 -05:00
parent 8e8696b858
commit 84d5e1fa60
2 changed files with 34 additions and 0 deletions
+14
View File
@@ -1921,6 +1921,20 @@ class AgentManager:
"type": "preset",
"preset": "claude_code",
}
# Suppress Claude Code's bundled plugin skills (/init, /review,
# /security-review, /simplify, /loop, /schedule, /update-config,
# /keybindings-help, /fewer-permission-prompts, /claude-api).
# OpenSwarm has its own skills system that injects skill content
# into the user prompt via _resolve_attached_skills, bypassing the
# SDK's Skill tool entirely — so the bundled skills only cause
# confusion: half mutate ~/.claude state OpenSwarm doesn't use
# (settings.json, keybindings.json), and the rest tell the model
# it can invoke slash commands the backend doesn't intercept.
# Empty list is the SDK's documented "skills off" signal — see
# the `skills` field on ClaudeAgentOptions in claude_agent_sdk
# types.py. User-attached skills are unaffected because they
# don't go through the Skill tool.
options_kwargs["skills"] = []
# exclude_dynamic_sections=True tells the CLI to keep
# per-user/per-machine grounding (cwd, git status, recent
# commits, OS info) out of the cached system prompt prefix
+20
View File
@@ -416,6 +416,26 @@ def test_compose_system_prompt_all_none_returns_none():
assert AgentManager()._compose_system_prompt(None, None, None) is None
def test_run_agent_loop_disables_bundled_claude_code_skills():
"""Regression guard for `options_kwargs["skills"] = []` in _run_agent_loop.
The claude-agent-sdk ships a Skill tool that surfaces Claude Code's
bundled plugin skills (/init, /review, /security-review, /simplify,
/loop, /schedule, /update-config, /keybindings-help,
/fewer-permission-prompts, /claude-api). These are inappropriate in
OpenSwarm — half mutate ~/.claude config the backend doesn't read, and
the rest reference slash commands the backend never intercepts. The
SDK's documented "skills off" signal is `skills=[]` on
ClaudeAgentOptions; user-attached skills bypass the Skill tool and
are unaffected. If this assignment ever gets dropped during a rebase
or refactor the bundled skills come back, so we pin it here.
"""
import inspect
src = inspect.getsource(AgentManager._run_agent_loop)
assert 'options_kwargs["skills"] = []' in src
def test_resolve_context_paths_empty_returns_empty():
assert AgentManager()._resolve_context_paths(None) == ""
assert AgentManager()._resolve_context_paths([]) == ""