Files
goclaw/internal/tools/subagent_config.go
T
viettranx 52c56978c5 fix(tools): improve workspace path guidance to reduce LLM path guessing
Agents were guessing absolute paths for file/exec tools, causing failed
tool calls and wasteful retries. Strengthen LLM guidance at three levels:

- System prompt: instruct to use relative paths, not guess absolute paths
- Tool param descriptions: mention workspace-relative resolution
- Subagent prompt: add missing workspace section with path guidance
2026-03-13 13:51:37 +07:00

101 lines
3.4 KiB
Go

package tools
import "fmt"
// DefaultSubagentConfig returns sensible defaults matching OpenClaw TS spec.
// TS sources: agent-limits.ts, sessions-spawn-tool.ts, subagent-registry.ts.
func DefaultSubagentConfig() SubagentConfig {
return SubagentConfig{
MaxConcurrent: 8, // TS: DEFAULT_SUBAGENT_MAX_CONCURRENT = 8
MaxSpawnDepth: 1, // TS: maxSpawnDepth ?? 1
MaxChildrenPerAgent: 5, // TS: maxChildrenPerAgent ?? 5
ArchiveAfterMinutes: 60, // TS: archiveAfterMinutes ?? 60
}
}
// applyDenyList removes denied tools from the registry based on depth.
func (sm *SubagentManager) applyDenyList(reg *Registry, depth int, cfg SubagentConfig) {
// Always deny
for _, name := range SubagentDenyAlways {
reg.Unregister(name)
}
// Leaf deny (at max depth)
if depth >= cfg.MaxSpawnDepth {
for _, name := range SubagentDenyLeaf {
reg.Unregister(name)
}
}
}
// buildSubagentSystemPrompt constructs the system prompt for a subagent,
// matching the TS buildSubagentSystemPrompt pattern from subagent-announce.ts.
func (sm *SubagentManager) buildSubagentSystemPrompt(task *SubagentTask, cfg SubagentConfig, workspace string) string {
parentLabel := "main agent"
if task.Depth >= 2 {
parentLabel = "parent orchestrator"
}
canSpawn := task.Depth < cfg.MaxSpawnDepth
prompt := fmt.Sprintf(`# Subagent Context
You are a **subagent** spawned by the %s for a specific task.
## Your Role
- You were created to handle: %s
- Complete this task. That is your entire purpose.
- You are NOT the %s. Do not try to be.
## Rules
1. **Stay focused** — Do your assigned task, nothing else.
2. **Complete the task** — Your final message will be automatically reported to the %s.
3. **Never ask for clarification** — Work with what you have. If asked to create content, generate it yourself.
4. **Be ephemeral** — You may be terminated after task completion. That is fine.
## Output Format
Your final response IS the deliverable — it will be forwarded to the user.
- If asked to create content (posts, articles, messages, etc.), output the FULL content directly. Do NOT describe what you wrote — just write it.
- Do NOT say "I wrote a post about..." or "Here is what I created...". Output the content itself as your response.
- If the task is research or analysis, provide the complete findings.
- The %s will receive your exact final response, so make it user-ready.
## What You Do NOT Do
- NO user conversations (that is the %s's job)
- NO external messages unless explicitly tasked
- NO cron jobs or persistent state
- NO pretending to be the %s`,
parentLabel, task.Task,
parentLabel, parentLabel, parentLabel, parentLabel, parentLabel)
if canSpawn {
prompt += `
## Sub-Agent Spawning
You CAN spawn your own sub-agents for parallel or complex work using the spawn tool.
Your sub-agents will announce their results back to you automatically (not to the main agent).
Coordinate their work and synthesize results before reporting back.`
} else if task.Depth >= 2 {
prompt += `
## Sub-Agent Spawning
You are a leaf worker and CANNOT spawn further sub-agents. Focus on your assigned task.`
}
prompt += fmt.Sprintf(`
## Session Context
- Label: %s
- Depth: %d / %d`, task.Label, task.Depth, cfg.MaxSpawnDepth)
if workspace != "" {
prompt += fmt.Sprintf(`
## Workspace
Your working directory is: %s
Use relative paths for file operations — do not guess absolute paths.`, workspace)
}
return prompt
}