diff --git a/runtime/subagent/subagent.go b/runtime/subagent/subagent.go index 0cfe8b1..4319521 100644 --- a/runtime/subagent/subagent.go +++ b/runtime/subagent/subagent.go @@ -27,6 +27,13 @@ type Request struct { NonGoals string `json:"non_goals,omitempty"` DoneCriteria string `json:"done_criteria,omitempty"` Deliverables []string `json:"deliverables,omitempty"` + // OutputFormat 交付物的结构/格式要求(Q3 WP3:委派模板四要素之一, + // 任务书「输出格式」节;空 = 由子代理自行决定)。 + OutputFormat string `json:"output_format,omitempty"` + // Tools 允许子代理使用的工具面(Q3 WP3:任务书「工具面」节;空 = 沿用 + // 子代理画像默认。宿主可按此收窄,不得用于扩权——子代理权限恒不超过 + // 委派方)。 + Tools []string `json:"tools,omitempty"` // Deadline / MaxToolCalls 是宿主注入的预算余量(模型不可自行扩权)。 Deadline time.Time `json:"-"` MaxToolCalls int `json:"-"` @@ -67,7 +74,7 @@ func RegisterWithHooks(r *tools.Registry, factory Factory, bus *hooks.Bus) { func (t *delegateTool) Name() string { return "delegate_task" } func (t *delegateTool) Description() string { - return "Delegate a self-contained subtask to a fresh sub-agent. Fill every field: goal, inputs (with versions), write_scope (directory the sub-agent may write), non_goals, done_criteria, deliverables. The sub-agent cannot exceed your permissions; report back its conclusion and files." + return "Delegate a self-contained subtask to a fresh sub-agent. Fill every field: goal, inputs (with versions), write_scope (directory the sub-agent may write), non_goals, done_criteria, deliverables, output_format (structure/format the deliverables must follow), tools (tool names the sub-agent should use). The sub-agent cannot exceed your permissions; report back its conclusion and files." } func (t *delegateTool) Parameters() json.RawMessage { return json.RawMessage(`{"type":"object","required":["goal","done_criteria"],"properties":{ @@ -77,6 +84,8 @@ func (t *delegateTool) Parameters() json.RawMessage { "non_goals":{"type":"string"}, "done_criteria":{"type":"string"}, "deliverables":{"type":"array","items":{"type":"string"}}, + "output_format":{"type":"string"}, + "tools":{"type":"array","items":{"type":"string"}}, "background":{"type":"boolean"} }}`) } diff --git a/runtime/subagent/subagent_test.go b/runtime/subagent/subagent_test.go index aa93b90..875d450 100644 --- a/runtime/subagent/subagent_test.go +++ b/runtime/subagent/subagent_test.go @@ -36,7 +36,9 @@ func TestDelegateToolRoundTrip(t *testing.T) { "write_scope":"research/", "non_goals":"不做实现", "done_criteria":"产出三来源对照表", - "deliverables":["notes.md","data/table.csv"] + "deliverables":["notes.md","data/table.csv"], + "output_format":"Markdown:结论先行,附三来源对照表", + "tools":["web_search","read_file"] }`)) if res.IsError { t.Fatal(res.Content) @@ -44,6 +46,11 @@ func TestDelegateToolRoundTrip(t *testing.T) { if got.Goal != "调研主题 X" || got.WriteScope != "research/" || got.DoneCriteria != "产出三来源对照表" { t.Fatalf("delegation fields lost: %+v", got) } + // Q3 WP3:输出格式与工具面随委派请求透传(任务书两节的声明源)。 + if got.OutputFormat != "Markdown:结论先行,附三来源对照表" || + strings.Join(got.Tools, ",") != "web_search,read_file" { + t.Fatalf("output_format/tools lost: %+v", got) + } if !strings.Contains(res.Content, "[sub-agent succeeded]") || !strings.Contains(res.Content, "调研完成") || !strings.Contains(res.Content, "files: data/table.csv, notes.md") {