对比 Aster 的 SubAgent 实现与 Claude Extended Thinking (Codex) 的 SubAgent 机制。
Claude 的 Extended Thinking 模式中,SubAgent 有以下关键特性:
- SubAgent 执行过程中自动保存状态
- 支持中断后恢复(Resume)
- 状态包括:执行进度、中间结果、工具调用历史
- 持久化到磁盘/数据库
- SubAgent 可以运行数小时甚至数天
- 主 Agent 不需要等待 SubAgent 完成
- 异步轮询机制检查 SubAgent 状态
- 支持后台执行
- CPU、内存、磁盘使用监控
- 超时控制
- 资源配额限制
- 自动清理机制
- Start: 启动 SubAgent
- Pause: 暂停执行
- Resume: 恢复执行
- Stop: 停止执行
- Query: 查询状态和输出
- Cleanup: 清理资源
- 每个 SubAgent 运行在独立进程中
- 完全的内存隔离
- 独立的文件系统视图(可选)
- 沙箱执行环境
| 特性 | 实现状态 | 说明 |
|---|---|---|
| 基本任务委派 | ✅ 完整 | 通过 task 工具调用 |
| 上下文隔离 | ✅ 完整 | 每个 SubAgent 独立上下文 |
| 并行执行 | ✅ 完整 | 支持同时启动多个 SubAgent |
| 专业化配置 | ✅ 完整 | SubAgentSpec 定义不同类型 |
| 工具集配置 | ✅ 完整 | 可继承或自定义工具 |
| 中间件继承 | ✅ 完整 | 灵活的中间件栈配置 |
| 结果返回 | ✅ 完整 | 返回摘要结果给主 Agent |
| 特性 | 实现状态 | 说明 |
|---|---|---|
| 状态持久化 | ⚠️ 部分 | FileSubagentManager 有基础实现,但未完全集成 |
| 生命周期管理 | ⚠️ 部分 | 有 Start/Stop,缺少 Pause/Resume |
| 资源监控 | ⚠️ 部分 | 有基础的 CPU/内存监控,但不完善 |
| 进程隔离 | ⚠️ 部分 | FileSubagentManager 支持进程级隔离,但未作为默认 |
| 特性 | 实现状态 | 影响 |
|---|---|---|
| Resume 机制 | ❌ 缺失 | 无法恢复中断的 SubAgent |
| 异步轮询 | ❌ 缺失 | 主 Agent 必须等待 SubAgent 完成 |
| 后台执行 | ❌ 缺失 | SubAgent 无法在后台长时间运行 |
| 状态查询 API | ❌ 缺失 | 无法查询正在运行的 SubAgent 状态 |
| 自动清理 | ❌ 缺失 | 需要手动清理 SubAgent 资源 |
| 超时控制 | ❌ 缺失 | 没有自动超时机制 |
Claude Codex:
# 启动 SubAgent
task_id = start_subagent(
type="researcher",
prompt="研究 AI 最新进展",
timeout=3600 # 1小时超时
)
# 主 Agent 继续其他工作
# ...
# 稍后查询状态
status = query_subagent(task_id)
if status.state == "running":
print(f"进度: {status.progress}%")
elif status.state == "completed":
result = get_subagent_output(task_id)
# 如果需要,可以暂停
pause_subagent(task_id)
# 稍后恢复
resume_subagent(task_id)
# 清理
cleanup_subagent(task_id)
Aster 当前实现:
// 启动 SubAgent(同步等待)
result, err := subagent.Execute(ctx, description, parentContext)
// 主 Agent 阻塞等待结果
// ❌ 无法查询状态
// ❌ 无法暂停/恢复
// ❌ 无法异步执行
Aster 的 FileSubagentManager(未完全集成):
// 有基础的生命周期管理,但未与 SubAgentMiddleware 集成
manager := builtin.NewFileSubagentManager()
// 启动
instance, _ := manager.StartSubagent(ctx, config)
// 查询状态
status, _ := manager.GetSubagent(instance.ID)
// 停止
manager.StopSubagent(instance.ID)
// ⚠️ 但这些功能未暴露给 task 工具
Claude Codex:
# 自动持久化
task_id = start_subagent(...)
# 即使主程序崩溃,SubAgent 状态也被保存
# 重启后可以恢复
task_ids = list_subagents()
for task_id in task_ids:
if get_status(task_id) == "running":
# 可以选择恢复或清理
resume_subagent(task_id)
Aster 当前实现:
// ❌ SubAgent 状态不持久化
// ❌ 主 Agent 关闭后,SubAgent 状态丢失
// ❌ 无法恢复中断的任务
// FileSubagentManager 有持久化,但未集成
Claude Codex:
# 启动多个长时间运行的 SubAgent
task1 = start_subagent("researcher", "深度研究主题A")
task2 = start_subagent("researcher", "深度研究主题B")
task3 = start_subagent("researcher", "深度研究主题C")
# 主 Agent 立即返回,继续处理其他任务
# SubAgent 在后台运行
# 稍后轮询检查
while True:
statuses = [query_subagent(t) for t in [task1, task2, task3]]
if all(s.state == "completed" for s in statuses):
break
time.sleep(10) # 每10秒检查一次
# 收集结果
results = [get_output(t) for t in [task1, task2, task3]]
Aster 当前实现:
// ✅ 支持并行启动
// ❌ 但主 Agent 必须等待所有 SubAgent 完成
// ❌ 无法异步轮询
// ❌ 无法在后台长时间运行
// 并行执行(但仍然是同步等待)
result1, _ := subagent1.Execute(ctx, desc1, nil) // 阻塞
result2, _ := subagent2.Execute(ctx, desc2, nil) // 阻塞
result3, _ := subagent3.Execute(ctx, desc3, nil) // 阻塞
Claude Codex:
status = query_subagent(task_id)
print(f"CPU: {status.cpu_percent}%")
print(f"Memory: {status.memory_mb} MB")
print(f"Runtime: {status.runtime_seconds}s")
print(f"Token usage: {status.tokens_used}")
# 自动超时
if status.runtime > timeout:
stop_subagent(task_id)
Aster 当前实现:
// FileSubagentManager 有基础监控
instance, _ := manager.GetSubagent(taskID)
if instance.ResourceUsage != nil {
fmt.Printf("Memory: %.2f MB\n", instance.ResourceUsage.MemoryMB)
fmt.Printf("CPU: %.2f%%\n", instance.ResourceUsage.CPUPercent)
}
// ⚠️ 但未集成到 SubAgentMiddleware
// ❌ 没有自动超时机制
// ❌ 没有资源配额限制
Claude Codex:
# 每个 SubAgent 运行在独立进程中
# 完全的内存隔离
# 崩溃不影响主 Agent
task_id = start_subagent(
type="code-executor",
prompt="执行用户代码",
sandbox=True, # 沙箱隔离
resource_limits={
"max_memory_mb": 512,
"max_cpu_percent": 50,
"max_runtime_seconds": 300
}
)
Aster 当前实现:
// ❌ SubAgent 运行在同一进程中(goroutine)
// ❌ 共享内存空间
// ⚠️ 崩溃可能影响主 Agent
// FileSubagentManager 支持进程隔离,但未作为默认
问题:FileSubagentManager 已经实现了很多高级特性,但未与 SubAgentMiddleware 集成。
建议:
// 1. 修改 SubAgentMiddleware 使用 FileSubagentManager
type SubAgentMiddleware struct {
*BaseMiddleware
manager SubagentManager // 使用 SubagentManager 接口
enableParallel bool
mu sync.RWMutex
}
// 2. 修改 task 工具支持异步执行
func (t *TaskTool) Execute(ctx context.Context, input map[string]interface{}, tc *tools.ToolContext) (interface{}, error) {
// 启动 SubAgent(异步)
instance, err := t.middleware.manager.StartSubagent(ctx, config)
// 返回 task_id,而不是等待结果
return map[string]interface{}{
"ok": true,
"task_id": instance.ID,
"status": "started",
}, nil
}
// 3. 添加新工具:query_subagent
type QuerySubagentTool struct {
middleware *SubAgentMiddleware
}
func (t *QuerySubagentTool) Execute(ctx context.Context, input map[string]interface{}, tc *tools.ToolContext) (interface{}, error) {
taskID := input["task_id"].(string)
instance, err := t.middleware.manager.GetSubagent(taskID)
return map[string]interface{}{
"task_id": taskID,
"status": instance.Status,
"output": instance.Output,
"progress": calculateProgress(instance),
}, nil
}
问题:无法恢复中断的 SubAgent。
建议:
// 1. 在 SubagentManager 中添加 Resume 方法(已有)
// 2. 添加 resume_subagent 工具
type ResumeSubagentTool struct {
middleware *SubAgentMiddleware
}
func (t *ResumeSubagentTool) Execute(ctx context.Context, input map[string]interface{}, tc *tools.ToolContext) (interface{}, error) {
taskID := input["task_id"].(string)
instance, err := t.middleware.manager.ResumeSubagent(taskID)
return map[string]interface{}{
"ok": true,
"task_id": instance.ID,
"status": instance.Status,
}, nil
}
// 3. 在主 Agent 启动时自动恢复未完成的 SubAgent
func (m *SubAgentMiddleware) OnAgentStart(ctx context.Context, agentID string) error {
// 列出所有 SubAgent
instances, _ := m.manager.ListSubagents()
// 恢复未完成的
for _, instance := range instances {
if instance.Status == "running" || instance.Status == "starting" {
log.Printf("Resuming subagent: %s", instance.ID)
_, _ = m.manager.ResumeSubagent(instance.ID)
}
}
return nil
}
问题:主 Agent 必须等待 SubAgent 完成。
建议:
// 1. 修改 task 工具支持 async 参数
func (t *TaskTool) InputSchema() map[string]interface{} {
return map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"description": map[string]interface{}{
"type": "string",
"description": "Task description",
},
"subagent_type": map[string]interface{}{
"type": "string",
"description": "SubAgent type",
},
"async": map[string]interface{}{
"type": "boolean",
"description": "Run asynchronously (default: false)",
"default": false,
},
},
"required": []string{"description", "subagent_type"},
}
}
// 2. 异步执行逻辑
func (t *TaskTool) Execute(ctx context.Context, input map[string]interface{}, tc *tools.ToolContext) (interface{}, error) {
async := input["async"].(bool)
if async {
// 异步启动
instance, _ := t.middleware.manager.StartSubagent(ctx, config)
return map[string]interface{}{
"ok": true,
"task_id": instance.ID,
"status": "started",
"message": "SubAgent started in background. Use query_subagent to check status.",
}, nil
} else {
// 同步等待(当前行为)
// ...
}
}
问题:没有自动超时和资源配额控制。
建议:
// 1. 在 SubagentConfig 中添加限制
type SubagentConfig struct {
// ... 现有字段
// 资源限制
Timeout time.Duration `json:"timeout,omitempty"`
MaxMemoryMB int `json:"max_memory_mb,omitempty"`
MaxCPUPercent float64 `json:"max_cpu_percent,omitempty"`
MaxTokens int `json:"max_tokens,omitempty"`
}
// 2. 在 monitorSubagent 中实现限制
func (sm *FileSubagentManager) monitorSubagent(ctx context.Context, instance *SubagentInstance, cmd *exec.Cmd, outFile *os.File) {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
timeout := instance.Config.Timeout
if timeout == 0 {
timeout = 1 * time.Hour // 默认1小时
}
timeoutTimer := time.NewTimer(timeout)
defer timeoutTimer.Stop()
for {
select {
case <-timeoutTimer.C:
// 超时,终止进程
log.Printf("SubAgent %s timeout, killing process", instance.ID)
_ = cmd.Process.Kill()
instance.Status = "timeout"
instance.Error = "execution timeout"
return
case <-ticker.C:
// 检查资源使用
sm.updateResourceUsage(instance)
if instance.ResourceUsage != nil {
// 检查内存限制
if instance.Config.MaxMemoryMB > 0 &&
instance.ResourceUsage.MemoryMB > float64(instance.Config.MaxMemoryMB) {
log.Printf("SubAgent %s exceeded memory limit", instance.ID)
_ = cmd.Process.Kill()
instance.Status = "resource_limit_exceeded"
instance.Error = "memory limit exceeded"
return
}
// 检查 CPU 限制
if instance.Config.MaxCPUPercent > 0 &&
instance.ResourceUsage.CPUPercent > instance.Config.MaxCPUPercent {
log.Printf("SubAgent %s exceeded CPU limit", instance.ID)
_ = cmd.Process.Kill()
instance.Status = "resource_limit_exceeded"
instance.Error = "CPU limit exceeded"
return
}
}
case <-ctx.Done():
return
}
}
}
问题:SubAgent 运行在同一进程中,缺乏隔离。
建议:
// 1. 添加配置选项
type SubAgentMiddlewareConfig struct {
// ... 现有字段
// 隔离模式
IsolationMode string // "goroutine" (默认) 或 "process"
}
// 2. 根据模式选择实现
func NewSubAgentMiddleware(config *SubAgentMiddlewareConfig) (*SubAgentMiddleware, error) {
var manager SubagentManager
if config.IsolationMode == "process" {
// 使用进程级隔离
manager = builtin.NewFileSubagentManager()
} else {
// 使用 goroutine(当前实现)
manager = NewInProcessSubagentManager()
}
// ...
}
| 功能类别 | Claude Codex | Aster 当前 | Aster 潜力 |
|---|---|---|---|
| 基础任务委派 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 上下文隔离 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 并行执行 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 状态持久化 | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| Resume 机制 | ⭐⭐⭐⭐⭐ | ⭐ | ⭐⭐⭐⭐⭐ |
| 异步执行 | ⭐⭐⭐⭐⭐ | ⭐ | ⭐⭐⭐⭐ |
| 资源监控 | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| 超时控制 | ⭐⭐⭐⭐⭐ | ⭐ | ⭐⭐⭐⭐⭐ |
| 进程隔离 | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| 生命周期管理 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
总体评分:
好消息:你们已经有了 FileSubagentManager,它实现了很多 Claude Codex 的特性!只需要将它与 SubAgentMiddleware 集成,就能大幅提升功能完整度。