Skip to content

Bug: Setting skills=[] does not opt agent out of default skills #586

@Qasimk555

Description

@Qasimk555

Bug Description

Setting skills=[] on an agent decorator does not prevent the agent from receiving default skills. The agent still gets execute (bash) and read_skill tools attached.

Root Cause

There are two fallback mechanisms in the SDK that apply default skills:

1. fastagent.py (line 947-949)

if config_obj.skills is None:
    if not resolved:
        resolved = list(default_skills)

✅ Setting skills=[] bypasses this (since [] is not None)

2. mcp_agent.py (line 116-121)

manifests: list[SkillManifest] = list(getattr(self.config, "skill_manifests", []) or [])
if not manifests and context and context.skill_registry:
    try:
        manifests = list(context.skill_registry.load_manifests())

❌ Setting skills=[] does NOT bypass this because an empty list is falsy (not [] is True)

Impact

  • When skills=[] is set, skill_manifests becomes []
  • not [] evaluates to True
  • The fallback loads skills from context.skill_registry
  • This enables shell runtime (execute tool) and skill reader (read_skill tool)

For agents using @fast.agent() without a custom class, there is no way to opt out of skills.

Expected Behavior

Setting skills=[] should explicitly disable skills for an agent, preventing:

  • Shell runtime activation
  • execute tool attachment
  • read_skill tool attachment

Proposed Fix

In mcp_agent.py, check if skills was explicitly configured before applying the fallback:

manifests: list[SkillManifest] = list(getattr(self.config, "skill_manifests", []) or [])
# Only fall back to global registry if skills was NOT explicitly configured
skills_explicitly_configured = self.config.skills is not None
if not manifests and not skills_explicitly_configured and context and context.skill_registry:
    try:
        manifests = list(context.skill_registry.load_manifests())
    except Exception:
        manifests = []

Reproduction

from fast_agent.core.fastagent import FastAgent

fast = FastAgent("test")

@fast.agent(
    name="minimal_agent",
    instruction="You are a minimal agent.",
    skills=[],  # Explicitly opt out of skills
)
async def minimal():
    pass

# When running, minimal_agent still has execute and read_skill tools attached

Environment

  • fast-agent-mcp version: 0.4.16
  • Python version: 3.13+

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions