harness - 子代理定义与任务委派
主代理(main)在处理复杂任务时,可以把子任务委派给"专项子代理"执行。子代理拥有独立的上下文与工具权限,互不污染。
1、内置子代理
solon-ai-harness 内置了几个常用子代理(开箱即用),定义文件位于 META-INF/solon/ai/harness/ 目录下:
| 名称 | 说明 | 工具集 |
|---|---|---|
general | 通用全能专家。其它子代理不匹配时优先选它 | *(全部公有工具) |
explore | 全域信息探索专家(本地文件 + 全网检索,无写权限) | list, read, grep, glob, skill, webfetch, websearch, codesearch |
plan | 规划与计划专家(制定逻辑路径与执行步骤,无写权限) | list, read, grep, glob, skill, webfetch, websearch, codesearch |
bash | Bash 命令执行专家(git、命令行操作,无写权限) | list, read, bash |
git-summary | Git 提交摘要生成专家(隐藏代理,内部使用) | 无工具(hidden) |
2、子代理定义文件(Markdown)
子代理通过 Markdown 文件定义:YAML Front Matter 描述元数据,正文即系统提示词。文件放在 {harnessHome}/agents/ 或挂载的 AGENTS 目录下。
---
name: "code_reviewer"
description: "代码评审专家,定位风险并给出改进建议"
tools: ["read", "grep", "glob"]
model: "deepseek-v4-flash"
---
你是一位严谨的代码评审专家。
输出规范:
- 按"风险等级"分组列出问题。
- 每条问题须标注文件路径与行号。
元数据字段(Front Matter):
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
name | String | / | 代理唯一标识 |
description | String | / | 职能描述(供主代理识别调度) |
tools | List<String> | / | 允许的工具(见《配置参考》工具权限表) |
disallowedTools | List<String> | / | 禁用的工具 |
model | String | / | 指定模型(不指定则用会话选中或主模型) |
skills | List<String> | / | 绑定的技能标识 |
mcpServers | List<String> | / | 绑定的 MCP 服务 |
memory | String | / | 记忆作用域(user / project / local) |
permissionMode | String | / | 权限模式(如 plan) |
enabled | boolean | true | 是否启用 |
hidden | boolean | false | 是否隐藏(不出现在可用代理列表) |
primary | boolean | false | 是否为主代理 |
background | boolean | false | 是否为后台任务代理 |
isolation | String | / | 隔离配置(如 worktree) |
teamName | String | / | 所属团队名称(用于团队成员管理) |
hooks | Object | / | 钩子配置(保留字段,暂不解析) |
注:
tools工具名大小写均可解析,ls与list等价,task与subagent等价。
3、用代码动态定义子代理
无文件时,也可用代码构建子代理(详见 《harness - 进一步扩展定制参考》):
AgentDefinition definition = new AgentDefinition();
definition.setSystemPrompt("你是一位代码评审专家...");
definition.getMetadata().setName("code_reviewer");
definition.getMetadata().setDescription("代码评审专家");
definition.getMetadata().addTools(ToolPermission.TOOL_READ, ToolPermission.TOOL_GREP);
ReActAgent subagent = engine.createSubagent(definition).build();
subagent.prompt("评审 src 目录").session(session).call();
4、任务委派(task / multitask)
当主代理拥有 task 工具权限时,模型可自主把任务委派给子代理。马具内部由 TaskTalent 暴露两个能力:
task:委派单一任务给某个子代理(串行)。multitask:并行执行多个互不依赖的子任务(无资源竞争时优先用它以省时)。
每个子任务都是无状态的(上下文隔离),因此委派时必须在 prompt 中提供完成任务所需的全部背景。委派结果会以结构化片段(含 agent_name、result_status、result_content)回传给主代理。
注:
task工具在AgentFactory.toolAddDo中同时接受task和subagent两个名称。todoread和todowrite则是todo的别名。
5、动态生成子代理(generate)
当主代理拥有 generate 工具权限(且 subagentEnabled=true)时,模型可在运行中"即时创建"一个垂直领域的专家子代理。若 saveToFile=true,定义会持久化到 {workspace}/.soloncode/agents/{name}.md,后续可复用。
生成的子代理基于内置 general 代理定义复制修改,继承其全部公有工具权限。生成后的代理会注册到 AgentManager,可通过 getAgent(name) 获取。
6、AgentManager 管理接口
// 获取所有可用子代理(不含隐藏的)
Collection<AgentDefinition> agents = engine.getAgentManager().getAgents();
// 按名称获取子代理(不存在则抛出异常)
AgentDefinition def = engine.getAgentManager().getAgent("bash");
// 检查是否存在
boolean exists = engine.getAgentManager().hasAgent("explore");
// 动态添加(覆盖同名)
engine.getAgentManager().addAgent(customDefinition);
// 动态添加(仅不存在时)
engine.getAgentManager().addAgentIfAbsent(customDefinition);
// 清除所有自定义代理(保留内置)
engine.getAgentManager().clearCustomAgents();