mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-12 12:13:51 +00:00
* feat(collaboration): isolate delegated artifacts and child runs Isolate delegated inputs and outputs behind secure artifact exchange lifecycles. Scope Agent Link tasks by tenant and root agent, and enforce delegation spawn-tree boundaries. Add process-wide child-run admission and preserve logical media paths across native, MCP, and sandbox execution. * fix(collaboration): harden delegated task isolation Enforce tenant and root-agent task scope across migrations and stores. Add exactly-once async completion delivery, delegated sandbox boundaries, and confined artifact and media recovery across runtime surfaces. * fix(collaboration): recover interrupted async tasks * fix(collaboration): normalize persisted child-run status --------- Co-authored-by: ntduc <ntduc@cpp.ai.vn>
104 lines
3.2 KiB
Go
104 lines
3.2 KiB
Go
package tools
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// DefaultSubagentConfig returns GoClaw's runtime defaults. Per-root admission is
|
|
// independent from the Standard/Lite process safety cap.
|
|
func DefaultSubagentConfig() SubagentConfig {
|
|
return SubagentConfig{
|
|
MaxConcurrent: 20,
|
|
MaxSpawnDepth: 1,
|
|
MaxChildrenPerAgent: 5,
|
|
ArchiveAfterMinutes: 60,
|
|
MaxRetries: 2,
|
|
}
|
|
}
|
|
|
|
// 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.
|
|
Asynchronous descendants report to the root orchestrator with their direct-parent lineage.
|
|
Synchronous descendants return their result directly to you.`
|
|
} 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
|
|
}
|