feat: add --orchestration startup flag to gate spawn tool
Orchestration (subagent spawning) is now opt-in rather than always-on. The spawn tool is only registered when orchestration is explicitly enabled, preventing the LLM from having a tool it has no guidance to use. Changes: - config: SubagentsConfig.Enabled bool (opt-in per agent via JSON config) - config: AgentDefaults.Orchestration bool (env PICOCLAW_AGENTS_DEFAULTS_ORCHESTRATION) - agent/instance: apply defaults.Orchestration to agent.Subagents at construction - agent/loop: gate spawn tool registration on agent.Subagents.Enabled - cmd/agent: --orchestration flag sets cfg.Agents.Defaults.Orchestration = true Usage: picoclaw agent --orchestration Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
55d3a08fcd
commit
bfabdea8b7
4 changed files with 29 additions and 9 deletions
|
|
@ -24,6 +24,7 @@ func agentCmd() {
|
||||||
message := ""
|
message := ""
|
||||||
sessionKey := "cli:default"
|
sessionKey := "cli:default"
|
||||||
modelOverride := ""
|
modelOverride := ""
|
||||||
|
orchestrationEnabled := false
|
||||||
|
|
||||||
args := os.Args[2:]
|
args := os.Args[2:]
|
||||||
for i := 0; i < len(args); i++ {
|
for i := 0; i < len(args); i++ {
|
||||||
|
|
@ -46,6 +47,8 @@ func agentCmd() {
|
||||||
modelOverride = args[i+1]
|
modelOverride = args[i+1]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
case "--orchestration":
|
||||||
|
orchestrationEnabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,6 +62,10 @@ func agentCmd() {
|
||||||
cfg.Agents.Defaults.Model = modelOverride
|
cfg.Agents.Defaults.Model = modelOverride
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if orchestrationEnabled {
|
||||||
|
cfg.Agents.Defaults.Orchestration = true
|
||||||
|
}
|
||||||
|
|
||||||
provider, modelID, err := providers.CreateProvider(cfg)
|
provider, modelID, err := providers.CreateProvider(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error creating provider: %v\n", err)
|
fmt.Printf("Error creating provider: %v\n", err)
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,15 @@ func NewAgentInstance(
|
||||||
skillsFilter = agentCfg.Skills
|
skillsFilter = agentCfg.Skills
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply defaults.Orchestration: if the flag is set, ensure orchestration is enabled.
|
||||||
|
if defaults.Orchestration {
|
||||||
|
if subagents == nil {
|
||||||
|
subagents = &config.SubagentsConfig{Enabled: true}
|
||||||
|
} else {
|
||||||
|
subagents.Enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
maxIter := defaults.MaxToolIterations
|
maxIter := defaults.MaxToolIterations
|
||||||
if maxIter == 0 {
|
if maxIter == 0 {
|
||||||
maxIter = 20
|
maxIter = 20
|
||||||
|
|
|
||||||
|
|
@ -216,15 +216,17 @@ func registerSharedTools(
|
||||||
agent.Tools.Register(tools.NewFindSkillsTool(registryMgr, searchCache))
|
agent.Tools.Register(tools.NewFindSkillsTool(registryMgr, searchCache))
|
||||||
agent.Tools.Register(tools.NewInstallSkillTool(registryMgr, agent.Workspace))
|
agent.Tools.Register(tools.NewInstallSkillTool(registryMgr, agent.Workspace))
|
||||||
|
|
||||||
// Spawn tool with allowlist checker
|
// Spawn tool — only registered when orchestration is explicitly enabled.
|
||||||
subagentManager := tools.NewSubagentManager(provider, agent.Model, agent.Workspace, msgBus)
|
if agent.Subagents != nil && agent.Subagents.Enabled {
|
||||||
subagentManager.SetLLMOptions(agent.MaxTokens, agent.Temperature)
|
subagentManager := tools.NewSubagentManager(provider, agent.Model, agent.Workspace, msgBus)
|
||||||
spawnTool := tools.NewSpawnTool(subagentManager)
|
subagentManager.SetLLMOptions(agent.MaxTokens, agent.Temperature)
|
||||||
currentAgentID := agentID
|
spawnTool := tools.NewSpawnTool(subagentManager)
|
||||||
spawnTool.SetAllowlistChecker(func(targetAgentID string) bool {
|
currentAgentID := agentID
|
||||||
return registry.CanSpawnSubagent(currentAgentID, targetAgentID)
|
spawnTool.SetAllowlistChecker(func(targetAgentID string) bool {
|
||||||
})
|
return registry.CanSpawnSubagent(currentAgentID, targetAgentID)
|
||||||
agent.Tools.Register(spawnTool)
|
})
|
||||||
|
agent.Tools.Register(spawnTool)
|
||||||
|
}
|
||||||
|
|
||||||
// Update context builder with the complete tools registry
|
// Update context builder with the complete tools registry
|
||||||
agent.ContextBuilder.SetToolsRegistry(agent.Tools)
|
agent.ContextBuilder.SetToolsRegistry(agent.Tools)
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@ type AgentConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SubagentsConfig struct {
|
type SubagentsConfig struct {
|
||||||
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
AllowAgents []string `json:"allow_agents,omitempty"`
|
AllowAgents []string `json:"allow_agents,omitempty"`
|
||||||
Model *AgentModelConfig `json:"model,omitempty"`
|
Model *AgentModelConfig `json:"model,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
@ -182,6 +183,7 @@ type AgentDefaults struct {
|
||||||
Temperature *float64 `json:"temperature,omitempty" env:"PICOCLAW_AGENTS_DEFAULTS_TEMPERATURE"`
|
Temperature *float64 `json:"temperature,omitempty" env:"PICOCLAW_AGENTS_DEFAULTS_TEMPERATURE"`
|
||||||
MaxToolIterations int `json:"max_tool_iterations" env:"PICOCLAW_AGENTS_DEFAULTS_MAX_TOOL_ITERATIONS"`
|
MaxToolIterations int `json:"max_tool_iterations" env:"PICOCLAW_AGENTS_DEFAULTS_MAX_TOOL_ITERATIONS"`
|
||||||
TaskReminderInterval int `json:"task_reminder_interval" env:"PICOCLAW_AGENTS_DEFAULTS_TASK_REMINDER_INTERVAL"`
|
TaskReminderInterval int `json:"task_reminder_interval" env:"PICOCLAW_AGENTS_DEFAULTS_TASK_REMINDER_INTERVAL"`
|
||||||
|
Orchestration bool `json:"orchestration,omitempty" env:"PICOCLAW_AGENTS_DEFAULTS_ORCHESTRATION"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelsConfig struct {
|
type ChannelsConfig struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue