Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ mcpServers:
# Extensions and tools
--extension, -e Load additional extension file(s) (repeatable)
--no-extensions Disable all extensions
--no-core-tools Disable all built-in core tools (bash, read, write, edit, grep, find, ls, subagent)
--no-core-tools Disable built-in core tools except subagent: (bash, read, write, edit, grep, find, ls)
--prompt-template Load a specific prompt template by name
--no-prompt-templates Disable prompt template loading

Expand Down Expand Up @@ -602,7 +602,8 @@ host, err := kit.New(ctx, &kit.Options{
// Tool options
Tools: []kit.Tool{...}, // Replace default tool set entirely
ExtraTools: []kit.Tool{...}, // Add tools alongside defaults
DisableCoreTools: true, // Disable all built-in core tools; also controllable via
DisableCoreTools: true, // Disable all built-in core tools except for the
// subagent tool; also controllable via
// --no-core-tools flag, KIT_NO_CORE_TOOLS env var,
// or no-core-tools: true in .kit.yml
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Expand Down
12 changes: 7 additions & 5 deletions internal/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ type AgentConfig struct {
// CodingTools or tools with a custom WorkDir).
CoreTools []fantasy.AgentTool

// DisableCoreTools, when true, prevents loading any core tools.
// DisableCoreTools, when true, prevents loading any core tools except for
// the subagent tool.
// If both DisableCoreTools is true and CoreTools is empty, the agent
// will have no tools (useful for simple chat completions).
// will only have the subagent tool (useful for simple chat completions).
DisableCoreTools bool

// ToolWrapper is an optional function that wraps the combined tool list
Expand Down Expand Up @@ -288,11 +289,12 @@ func NewAgent(ctx context.Context, agentConfig *AgentConfig) (*Agent, error) {

// Register core tools (direct AgentTool implementations, no MCP overhead).
// Use caller-provided tools if set, otherwise default to all core tools.
// DisableCoreTools allows explicitly having zero tools (for chat-only mode).
// DisableCoreTools allows explicitly having zero tools except for the
// subagent tool (for chat-only mode).
var coreTools []fantasy.AgentTool
if agentConfig.DisableCoreTools && len(agentConfig.CoreTools) == 0 {
// Explicitly zero tools - chat-only mode
coreTools = nil
// Explicitly subagent tool only - chat-only mode
coreTools = core.SubagentTool()
Comment thread
coderabbitai[bot] marked this conversation as resolved.
} else if len(agentConfig.CoreTools) > 0 {
// Custom tools provided - use them
coreTools = agentConfig.CoreTools
Expand Down
5 changes: 3 additions & 2 deletions internal/agent/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ type AgentCreationOptions struct {
// CoreTools overrides the default core tool set. If empty, core.AllTools()
// is used.
CoreTools []fantasy.AgentTool
// DisableCoreTools, when true, prevents loading any core tools.
// DisableCoreTools, when true, prevents loading any core tools except for
// the subagent tool.
// If both DisableCoreTools is true and CoreTools is empty, the agent
// will have no tools (useful for simple chat completions).
// will only have the subagent tool (useful for simple chat completions).
DisableCoreTools bool
// ToolWrapper wraps the combined tool list before agent creation.
ToolWrapper func([]fantasy.AgentTool) []fantasy.AgentTool
Expand Down
6 changes: 6 additions & 0 deletions internal/core/tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ func SubagentTools(opts ...ToolOption) []fantasy.AgentTool {
}
}

func SubagentTool(opts ...ToolOption) []fantasy.AgentTool {
return []fantasy.AgentTool{
NewSubagentTool(opts...),
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// AllTools returns all available core tools.
func AllTools(opts ...ToolOption) []fantasy.AgentTool {
return append(SubagentTools(opts...), NewSubagentTool(opts...))
Expand Down
5 changes: 3 additions & 2 deletions internal/kitsetup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ type AgentSetupOptions struct {
// CoreTools overrides the default core tool set. If empty, core.AllTools()
// is used. Allows SDK users to pass custom tools (e.g. with WithWorkDir).
CoreTools []fantasy.AgentTool
// DisableCoreTools, when true, prevents loading any core tools.
// DisableCoreTools, when true, prevents loading any core tools except for
// the subagent tool.
// If both DisableCoreTools is true and CoreTools is empty, the agent
// will have no tools (useful for simple chat completions).
// will only have the subagent tool (useful for simple chat completions).
DisableCoreTools bool
// ExtraTools are additional tools added alongside core, MCP, and extension
// tools. They do not replace the defaults — they extend them.
Expand Down
4 changes: 2 additions & 2 deletions pkg/kit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ host, err := kit.New(ctx, &kit.Options{
// Tool options
Tools: []kit.Tool{kit.NewBashTool()}, // Replace default tool set
ExtraTools: []kit.Tool{myTool}, // Add alongside defaults
DisableCoreTools: true, // Use no core tools (0 tools)
DisableCoreTools: true, // Use no core tools except for the subagent tool

// Configuration
SkipConfig: true, // Skip .kit.yml files (viper defaults + env vars still apply)
Expand Down Expand Up @@ -398,7 +398,7 @@ Key `Options` fields for SDK usage:
| `SkipConfig` | Skip `.kit.yml` loading (defaults + env vars still apply) |
| `Tools` | Replace core tools with custom set |
| `ExtraTools` | Add tools alongside defaults |
| `DisableCoreTools` | Use no core tools (0 tools, for chat-only) |
| `DisableCoreTools` | Use no core tools (except subagent tool - for chat-only) |
| `NoSession` | Ephemeral mode (no session persistence) |
| `SessionPath` | Open specific session file |
| `Continue` | Resume most recent session |
Expand Down
32 changes: 32 additions & 0 deletions pkg/kit/kit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ func TestNewWithSkillsOptions(t *testing.T) {
ctx := context.Background()

t.Run("NoSkills disables skill loading", func(t *testing.T) {
defer resetViper()
host, err := kit.New(ctx, &kit.Options{
Model: "anthropic/claude-sonnet-4-5-20250929",
Quiet: true,
Expand All @@ -392,6 +393,7 @@ func TestNewWithSkillsOptions(t *testing.T) {
})

t.Run("SkillsDir propagates", func(t *testing.T) {
defer resetViper()
// Use a non-existent dir — no skills will load but the option must be
// accepted without error and result in zero skills.
dir := t.TempDir()
Expand All @@ -411,6 +413,7 @@ func TestNewWithSkillsOptions(t *testing.T) {
})

t.Run("explicit Skills paths load correctly", func(t *testing.T) {
defer resetViper()
// Write a minimal skill file to a temp dir.
dir := t.TempDir()
skillFile := dir + "/my-skill.md"
Expand Down Expand Up @@ -472,3 +475,32 @@ func TestNewSystemPromptInline(t *testing.T) {
t.Errorf("composed system-prompt missing inline content; got %q", composed)
}
}

// TestDisableCoreTools verifies that setting Options.DisableCoreTools to true
// limits the available tools to only the 'subagent' tool.
func TestDisableCoreTools(t *testing.T) {
if os.Getenv("ANTHROPIC_API_KEY") == "" {
t.Skip("Skipping test: ANTHROPIC_API_KEY not set")
}
defer resetViper()

ctx := context.Background()
host, err := kit.New(ctx, &kit.Options{
Model: "anthropic/claude-sonnet-4-5-20250929",
Quiet: true,
NoSession: true,
NoExtensions: true,
DisableCoreTools: true,
})
if err != nil {
t.Fatalf("Failed to create Kit with DisableCoreTools: %v", err)
}
defer func() { _ = host.Close() }()

tools := host.GetToolNames()
if len(tools) != 1 {
t.Errorf("Expected 1 tool when DisableCoreTools is true, got %d: %v", len(tools), tools)
} else if len(tools) > 0 && tools[0] != "subagent" {
t.Errorf("Expected only 'subagent' tool, got %q", tools[0])
}
}
2 changes: 1 addition & 1 deletion skills/kit-sdk/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ host, err := kit.New(ctx, &kit.Options{
// Tools
Tools: []kit.Tool{kit.NewBashTool()}, // REPLACES entire default tool set
ExtraTools: []kit.Tool{myTool}, // ADDS alongside core/MCP/extension tools
DisableCoreTools: true, // Use no core tools (0 tools, for chat-only)
DisableCoreTools: true, // Use no core tools except for the subagent tool (for chat-only)

// Configuration
SkipConfig: true, // Skip .kit.yml files (viper defaults + env vars still apply)
Expand Down
4 changes: 2 additions & 2 deletions www/pages/sdk/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ host, err := kit.New(ctx, &kit.Options{
// Tools
Tools: []kit.Tool{...}, // Replace default tool set entirely
ExtraTools: []kit.Tool{...}, // Add tools alongside defaults
DisableCoreTools: true, // Use no core tools (0 tools, for chat-only)
DisableCoreTools: true, // Use no core tools except for the subagent tool (for chat-only)

// Configuration
SkipConfig: true, // Skip .kit.yml files (viper defaults + env vars still apply)
Expand Down Expand Up @@ -158,7 +158,7 @@ when embedding Kit as a library.
|-------|------|---------|-------------|
| `Tools` | `[]Tool` | — | Replace the entire default tool set |
| `ExtraTools` | `[]Tool` | — | Additional tools alongside core/MCP/extension tools |
| `DisableCoreTools` | `bool` | `false` | Use no core tools (0 tools, for chat-only) |
| `DisableCoreTools` | `bool` | `false` | Use no core tools except for the subagent tool (for chat-only) |
| `NoExtensions` | `bool` | `false` | Disable Yaegi extension loading |
| `NoContextFiles` | `bool` | `false` | Disable automatic AGENTS.md loading |

Expand Down
Loading