AI Agent Harness — 项目设计
设计目标
构建一个面向智能视频剪辑场景的 AI Agent 运行时框架,重点解决三个核心问题:
- Agent 可靠性:如何让 Agent 稳定完成多步骤任务而不陷入死循环或偏离目标
- 工具编排能力:如何安全、高效地调度和执行多种异构工具
- 生产级工程质量:可观测、可审计、可限制、可降级
系统架构
┌────────────────────────────── Agent Harness ──────────────────────────────┐
│ │
│ ┌─────────────────────────── Control Layer ───────────────────────────┐ │
│ │ │ │
│ │ User Input ──▶ Input Guardrail ──▶ Router ──▶ Agent Loop │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌─────────┐ ┌────────┐ │ │
│ │ │ Planner │ │ ReAct │ │ │
│ │ │ Agent │ │ Agent │ │ │
│ │ └────┬────┘ └───┬────┘ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ Tool Executor │ │ │
│ │ │ (sandbox + timeout) │ │ │
│ │ └────────────┬────────────┘ │ │
│ │ │ │ │
│ │ ┌────────────┼────────────┐ │ │
│ │ ▼ ▼ ▼ │ │
│ │ ┌────────┐ ┌─────────┐ ┌────────┐ │ │
│ │ │ Video │ │ RAG │ │ Util │ │ │
│ │ │ Tools │ │ Tool │ │ Tools │ │ │
│ │ └────────┘ └─────────┘ └────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────── State Layer ─────────────────────────────┐ │
│ │ │ │
│ │ ┌──────────────┐ ┌───────────────┐ ┌──────────────────┐ │ │
│ │ │ Conversation │ │ Long-term │ │ Execution │ │ │
│ │ │ Memory │ │ Memory │ │ History │ │ │
│ │ │ (sliding) │ │ (vector DB) │ │ (audit log) │ │ │
│ │ └──────────────┘ └───────────────┘ └──────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────── Infra Layer ─────────────────────────────┐ │
│ │ │ │
│ │ ┌──────────┐ ┌────────────┐ ┌─────────┐ ┌────────────┐ │ │
│ │ │ Tracer │ │ Metrics │ │ Logger │ │ Config │ │ │
│ │ │ (OTEL) │ │(Prometheus)│ │ (slog) │ │ (YAML) │ │ │
│ │ └──────────┘ └────────────┘ └─────────┘ └────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────── 外部接入 ──────────────────────────────────────┐
│ │
│ HTTP API (gin/chi) ── SSE Stream ── CLI (`agent run/chat/plan`) │
│ │
└───────────────────────────────────────────────────────────────────────────┘核心接口定义
Agent — 顶层抽象
go
type AgentConfig struct {
Name string
Model string // LLM model ID
SystemPrompt string
Tools []Tool
MaxSteps int // ReAct 最大循环次数
MaxTokens int // Token 预算上限
Timeout time.Duration // 全流程超时
Guardrails []Guardrail
Memory MemoryStore
}
type Agent interface {
// 单轮执行 — 输入用户消息,返回最终回复
Run(ctx context.Context, input string) (*AgentResult, error)
// 流式执行 — 支持中间步骤回调
RunStream(ctx context.Context, input string, onStep func(Step)) (*AgentResult, error)
// 多轮对话
Chat(ctx context.Context, sessionID string, input string) (*AgentResult, error)
}
type AgentResult struct {
Output string // 最终回复文本
Steps []Step // 执行步骤记录
TokenUsage TokenUsage // Token 消耗统计
Duration time.Duration // 总耗时
ToolCalls int // 工具调用次数
}
type Step struct {
Type StepType // "thought" | "action" | "observation" | "plan"
Content string
ToolName string // action 步骤的工具名
ToolArgs json.RawMessage
ToolResult string
Timestamp time.Time
Duration time.Duration
TokensUsed int
}
type StepType string
const (
StepThought StepType = "thought"
StepAction StepType = "action"
StepObservation StepType = "observation"
StepPlan StepType = "plan"
StepFinalAnswer StepType = "final_answer"
)LLM — 大模型通信层
go
type Message struct {
Role string // "system" | "user" | "assistant" | "tool"
Content string
ToolCalls []ToolCall // assistant 的工具调用请求
ToolCallID string // tool 消息对应的调用 ID
}
type ToolCall struct {
ID string
Name string
Arguments json.RawMessage
}
type ChatResponse struct {
Content string
ToolCalls []ToolCall
Usage TokenUsage
FinishReason string // "stop" | "tool_calls" | "length"
}
type TokenUsage struct {
PromptTokens int
CompletionTokens int
TotalTokens int
}
type LLMClient interface {
Chat(ctx context.Context, messages []Message, opts ...ChatOption) (*ChatResponse, error)
ChatStream(ctx context.Context, messages []Message, onChunk func(string), opts ...ChatOption) (*ChatResponse, error)
}
type ChatOption func(*chatOptions)
func WithTools(tools []ToolSchema) ChatOption { /* ... */ }
func WithTemperature(t float64) ChatOption { /* ... */ }
func WithMaxTokens(n int) ChatOption { /* ... */ }
func WithModel(model string) ChatOption { /* ... */ }Tool — 工具系统
go
type Tool interface {
Name() string
Description() string
Schema() *ToolParamSchema // JSON Schema 参数描述
Execute(ctx context.Context, args json.RawMessage) (*ToolOutput, error)
}
type ToolParamSchema struct {
Type string `json:"type"` // "object"
Properties map[string]ParamProperty `json:"properties"`
Required []string `json:"required"`
}
type ParamProperty struct {
Type string `json:"type"`
Description string `json:"description"`
Enum []string `json:"enum,omitempty"`
}
type ToolOutput struct {
Content string // 工具执行结果(文本)
Data any // 结构化数据(可选)
Error string // 错误信息
Metadata map[string]string // 追踪元数据
}
// ToolSchema 是传给 LLM 的工具描述格式(OpenAI function calling 格式)
type ToolSchema struct {
Type string `json:"type"` // "function"
Function FunctionDef `json:"function"`
}
type FunctionDef struct {
Name string `json:"name"`
Description string `json:"description"`
Parameters json.RawMessage `json:"parameters"`
}Tool Registry — 工具注册中心
go
type Registry interface {
Register(tool Tool) error
Unregister(name string) error
Get(name string) (Tool, bool)
List() []Tool
Schemas() []ToolSchema // 供 LLM 使用的 Schema 列表
Execute(ctx context.Context, name string, args json.RawMessage) (*ToolOutput, error)
}Tool Executor — 安全执行层
go
type ExecutorConfig struct {
Timeout time.Duration // 单次调用超时
MaxRetries int // 最大重试次数
RetryBackoff time.Duration // 退避基数
MaxConcurrency int // 最大并行工具调用数
Sandbox bool // 是否沙箱隔离
}
type Executor interface {
// 执行单个工具调用
Execute(ctx context.Context, call ToolCall) (*ToolOutput, error)
// 并行执行多个工具调用
ExecuteBatch(ctx context.Context, calls []ToolCall) ([]*ToolOutput, error)
}Planner — 任务规划器
go
type Plan struct {
Goal string
Steps []PlanStep
Created time.Time
Status PlanStatus // "active" | "completed" | "failed" | "replanning"
}
type PlanStep struct {
ID string
Description string
Tool string // 预期使用的工具
Status PlanStepStatus // "pending" | "running" | "done" | "failed" | "skipped"
Result string
DependsOn []string // 依赖的前置步骤 ID
}
type PlanStatus string
const (
PlanActive PlanStatus = "active"
PlanCompleted PlanStatus = "completed"
PlanFailed PlanStatus = "failed"
PlanReplanning PlanStatus = "replanning"
)
type Planner interface {
// 生成计划
CreatePlan(ctx context.Context, goal string, availableTools []ToolSchema) (*Plan, error)
// 重新规划(当某步骤失败或结果需要调整时)
Replan(ctx context.Context, plan *Plan, observation string) (*Plan, error)
// 获取下一个可执行步骤
NextStep(plan *Plan) (*PlanStep, bool)
}Memory — 记忆系统
go
type MemoryStore interface {
// ---- 短期记忆(对话上下文)----
// 获取会话消息历史
GetMessages(ctx context.Context, sessionID string, limit int) ([]Message, error)
// 追加消息
AddMessage(ctx context.Context, sessionID string, msg Message) error
// 压缩/总结历史消息
Compact(ctx context.Context, sessionID string) error
// ---- 长期记忆(跨会话持久化)----
// 存储记忆条目
Store(ctx context.Context, entry MemoryEntry) error
// 语义检索相关记忆
Recall(ctx context.Context, query string, topK int) ([]MemoryEntry, error)
// 清除会话
Clear(ctx context.Context, sessionID string) error
}
type MemoryEntry struct {
ID string
Content string
Type MemoryType // "fact" | "preference" | "episode"
Metadata map[string]string
CreatedAt time.Time
Score float64 // 检索相关度(查询时填充)
}
type MemoryType string
const (
MemoryFact MemoryType = "fact" // 事实知识
MemoryPreference MemoryType = "preference" // 用户偏好
MemoryEpisode MemoryType = "episode" // 历史操作
)Guardrails — 安全护栏
go
type Guardrail interface {
Name() string
// 检查用户输入
ValidateInput(ctx context.Context, input string) *GuardrailResult
// 检查 LLM 输出
ValidateOutput(ctx context.Context, output *ChatResponse) *GuardrailResult
// 检查工具调用
ValidateToolCall(ctx context.Context, call ToolCall) *GuardrailResult
}
type GuardrailResult struct {
Passed bool
Reason string // 不通过时的原因
Action GuardrailAction
}
type GuardrailAction string
const (
ActionBlock GuardrailAction = "block" // 拦截,不继续执行
ActionWarn GuardrailAction = "warn" // 警告但继续
ActionRewrite GuardrailAction = "rewrite" // 改写后继续
)
// 预置 Guardrail 实现
type BudgetGuardrail struct {
MaxSteps int
MaxTokens int
MaxToolCalls int
}
type ContentGuardrail struct {
BlockedPatterns []string // 正则黑名单
AllowedTools []string // 工具白名单
}
type LoopDetector struct {
MaxRepeats int // 相同 tool call 最大重复次数
WindowSize int // 检测窗口大小
}Router — 意图路由
go
type Route struct {
Name string
Description string
Agent Agent // 路由到的 Agent
Condition func(input string) bool
}
type Router interface {
// 根据用户输入选择合适的 Agent
Route(ctx context.Context, input string) (Agent, error)
// 注册路由
AddRoute(route Route)
}关键算法设计
1. ReAct 控制循环
go
func (a *ReactAgent) Run(ctx context.Context, input string) (*AgentResult, error) {
ctx, cancel := context.WithTimeout(ctx, a.config.Timeout)
defer cancel()
// 初始化追踪
ctx, span := tracer.Start(ctx, "agent.run")
defer span.End()
messages := a.buildInitialMessages(input)
var steps []Step
budget := &tokenBudget{max: a.config.MaxTokens}
for step := 0; step < a.config.MaxSteps; step++ {
// ---- Guardrail: 预算检查 ----
if err := a.checkBudget(budget); err != nil {
return a.buildResult(steps, budget, err), nil
}
// ---- Reason: 调用 LLM ----
resp, err := a.llm.Chat(ctx, messages, WithTools(a.registry.Schemas()))
if err != nil {
return nil, fmt.Errorf("step %d llm chat: %w", step, err)
}
budget.add(resp.Usage)
// ---- 终止条件: 无 tool call = 最终回答 ----
if len(resp.ToolCalls) == 0 {
steps = append(steps, Step{
Type: StepFinalAnswer, Content: resp.Content,
})
return a.buildResult(steps, budget, nil), nil
}
// ---- Act: 执行工具调用 ----
messages = append(messages, assistantMsg(resp))
for _, call := range resp.ToolCalls {
// Guardrail: 工具调用检查
if err := a.validateToolCall(ctx, call); err != nil {
messages = append(messages, toolErrorMsg(call.ID, err))
continue
}
// 循环检测
if a.loopDetector.IsLoop(call) {
return a.buildResult(steps, budget, ErrLoopDetected), nil
}
// 执行
output, err := a.executor.Execute(ctx, call)
observation := formatObservation(output, err)
steps = append(steps, Step{
Type: StepAction, ToolName: call.Name,
ToolArgs: call.Arguments, ToolResult: observation,
})
messages = append(messages, toolMsg(call.ID, observation))
}
}
return a.buildResult(steps, budget, ErrMaxStepsExceeded), nil
}2. Plan-and-Execute 流程
go
func (a *PlanExecuteAgent) Run(ctx context.Context, input string) (*AgentResult, error) {
// Phase 1: 制定计划
plan, err := a.planner.CreatePlan(ctx, input, a.registry.Schemas())
if err != nil {
return nil, fmt.Errorf("create plan: %w", err)
}
var steps []Step
steps = append(steps, Step{Type: StepPlan, Content: formatPlan(plan)})
// Phase 2: 逐步执行
for {
planStep, hasNext := a.planner.NextStep(plan)
if !hasNext {
break
}
planStep.Status = "running"
// 用 ReAct Agent 执行单步
result, err := a.stepExecutor.Run(ctx, planStep.Description)
if err != nil {
planStep.Status = "failed"
planStep.Result = err.Error()
// Phase 3: 重新规划
plan, err = a.planner.Replan(ctx, plan,
fmt.Sprintf("Step '%s' failed: %s", planStep.Description, err))
if err != nil {
return nil, fmt.Errorf("replan: %w", err)
}
steps = append(steps, Step{Type: StepPlan, Content: formatPlan(plan)})
continue
}
planStep.Status = "done"
planStep.Result = result.Output
steps = append(steps, result.Steps...)
}
// Phase 4: 总结
summary, err := a.summarize(ctx, plan, steps)
if err != nil {
return nil, err
}
return &AgentResult{Output: summary, Steps: steps}, nil
}3. 并行 Tool 执行
go
func (e *toolExecutor) ExecuteBatch(ctx context.Context, calls []ToolCall) ([]*ToolOutput, error) {
results := make([]*ToolOutput, len(calls))
g, gctx := errgroup.WithContext(ctx)
g.SetLimit(e.config.MaxConcurrency) // 并发度限制
for i, call := range calls {
i, call := i, call
g.Go(func() error {
output, err := e.executeWithRetry(gctx, call)
if err != nil {
results[i] = &ToolOutput{Error: err.Error()}
return nil // 不中断其他 tool
}
results[i] = output
return nil
})
}
_ = g.Wait()
return results, nil
}
func (e *toolExecutor) executeWithRetry(ctx context.Context, call ToolCall) (*ToolOutput, error) {
var lastErr error
for attempt := 0; attempt <= e.config.MaxRetries; attempt++ {
if attempt > 0 {
time.Sleep(e.config.RetryBackoff * time.Duration(1<<(attempt-1)))
}
callCtx, cancel := context.WithTimeout(ctx, e.config.Timeout)
output, err := e.registry.Execute(callCtx, call.Name, call.Arguments)
cancel()
if err == nil {
return output, nil
}
lastErr = err
}
return nil, fmt.Errorf("after %d retries: %w", e.config.MaxRetries, lastErr)
}4. 循环检测算法
go
type LoopDetector struct {
window []callSignature
maxSize int
threshold int // 相同签名出现次数阈值
}
type callSignature struct {
Name string
Args string // args 的哈希
}
func (d *LoopDetector) IsLoop(call ToolCall) bool {
sig := callSignature{
Name: call.Name,
Args: hashArgs(call.Arguments),
}
d.window = append(d.window, sig)
if len(d.window) > d.maxSize {
d.window = d.window[1:]
}
count := 0
for _, s := range d.window {
if s == sig {
count++
}
}
return count >= d.threshold
}视频剪辑 Agent 场景设计
用户交互流程
用户: "帮我把这段5分钟的vlog剪成一个30秒的精华版,加上字幕和轻快的背景音乐"
│
▼ [意图路由]
路由到 PlanExecuteAgent(多步骤复杂任务)
│
▼ [Plan 阶段]
Plan:
1. 分析视频内容,识别精彩片段 (analyze_video)
2. 选择最佳片段组合,凑够30秒 (select_segments)
3. 拼接选中片段并添加转场 (concat_videos)
4. 生成字幕 (generate_subtitles)
5. 推荐并添加背景音乐 (recommend_bgm → add_audio)
6. 导出最终视频 (export_video)
│
▼ [Execute 阶段 — 逐步执行]
Step 1: analyze_video("vlog.mp4", type="highlight")
→ 识别到 8 个精彩片段,含情绪标注
Step 2: select_segments(segments=[...], target=30s, priority="energy")
→ 选择 4 个高能片段,总时长 31.2s
Step 3: concat_videos(segments=[...], transition="crossfade")
→ 拼接完成,生成 highlight_draft.mp4
Step 4: generate_subtitles("highlight_draft.mp4", lang="zh")
→ 生成字幕文件 highlight_draft.srt
Step 5: recommend_bgm(mood="upbeat", duration=31)
→ 推荐 3 首 BGM,自动选择最匹配的
Step 6: export_video(project=..., format="mp4", quality="1080p")
→ 导出完成: output/vlog_highlight_30s.mp4
│
▼ [回复用户]
"已完成!我把vlog剪成了30秒精华版:
- 选择了4个高能片段(骑行画面、日落、美食、笑脸)
- 添加了淡入淡出转场
- 自动生成了中文字幕
- 配了一首轻快的BGM
输出文件: output/vlog_highlight_30s.mp4"工具实现示例
go
type AnalyzeVideoTool struct{}
func (t *AnalyzeVideoTool) Name() string { return "analyze_video" }
func (t *AnalyzeVideoTool) Description() string {
return "分析视频内容,识别场景、人物、情绪和精彩片段"
}
func (t *AnalyzeVideoTool) Schema() *ToolParamSchema {
return &ToolParamSchema{
Type: "object",
Properties: map[string]ParamProperty{
"video_path": {Type: "string", Description: "视频文件路径"},
"analysis_type": {
Type: "string",
Description: "分析类型",
Enum: []string{"highlight", "scene", "face", "emotion"},
},
},
Required: []string{"video_path", "analysis_type"},
}
}
func (t *AnalyzeVideoTool) Execute(ctx context.Context, args json.RawMessage) (*ToolOutput, error) {
var params struct {
VideoPath string `json:"video_path"`
AnalysisType string `json:"analysis_type"`
}
if err := json.Unmarshal(args, ¶ms); err != nil {
return nil, fmt.Errorf("parse args: %w", err)
}
// 实际场景中这里调用视频分析服务/模型
// MVP 阶段使用模拟数据
result := analyzeVideoSimulated(params.VideoPath, params.AnalysisType)
return &ToolOutput{
Content: result.Summary,
Data: result,
}, nil
}可观测性设计
Trace 追踪
每次 Agent 执行产生一条完整 Trace,包含:
Trace: agent.run (总耗时 12.3s)
├── Span: agent.plan (1.2s)
│ └── Span: llm.chat (1.1s) [model=gpt-4, tokens=850]
├── Span: agent.execute_step.1 (3.5s)
│ ├── Span: llm.chat (1.0s) [tokens=420]
│ └── Span: tool.analyze_video (2.4s) [status=ok]
├── Span: agent.execute_step.2 (2.1s)
│ ├── Span: llm.chat (0.9s) [tokens=380]
│ └── Span: tool.select_segments (1.1s) [status=ok]
├── Span: agent.execute_step.3 (4.2s)
│ ├── Span: llm.chat (0.8s) [tokens=350]
│ └── Span: tool.concat_videos (3.3s) [status=ok]
└── Span: agent.summarize (1.3s)
└── Span: llm.chat (1.2s) [tokens=290]Metrics 指标
| 指标 | 类型 | 说明 |
|---|---|---|
agent_runs_total | Counter | Agent 执行次数(成功/失败) |
agent_steps_total | Counter | 总步骤数 |
agent_duration_seconds | Histogram | 执行耗时分布 |
agent_tokens_used | Counter | Token 消耗量 |
tool_calls_total | Counter | 工具调用次数(按 tool name) |
tool_duration_seconds | Histogram | 工具执行耗时 |
tool_errors_total | Counter | 工具调用错误次数 |
guardrail_blocks_total | Counter | 护栏拦截次数 |
loop_detections_total | Counter | 循环检测触发次数 |
HTTP API 设计
接口列表
POST /api/v1/agent/run — 同步执行(短任务)
POST /api/v1/agent/run/stream — SSE 流式执行(长任务)
POST /api/v1/agent/chat — 多轮对话
GET /api/v1/agent/sessions/:id — 获取会话历史
DELETE /api/v1/agent/sessions/:id — 清除会话
POST /api/v1/tools — 注册工具(动态)
GET /api/v1/tools — 列出已注册工具
DELETE /api/v1/tools/:name — 注销工具
GET /api/v1/health — 健康检查
GET /metrics — Prometheus 指标流式输出格式(SSE)
event: step
data: {"type":"plan","content":"制定计划:1. 分析视频 2. 选择片段 ..."}
event: step
data: {"type":"action","tool":"analyze_video","args":{"video_path":"...","analysis_type":"highlight"}}
event: step
data: {"type":"observation","content":"找到8个精彩片段..."}
event: step
data: {"type":"action","tool":"select_segments","args":{...}}
event: done
data: {"output":"已完成!...","token_usage":{"total":2100},"duration":"12.3s"}开发分期
Phase 1:Core Loop(第1-2周)
目标:跑通 ReAct 循环,能通过 CLI 与 Agent 对话并调用工具
- [x] 项目骨架搭建(Go module + Makefile)
- [ ] LLM Client 接口 + OpenAI 实现(支持 function calling)
- [ ] Tool 接口 + Registry + 3 个示例工具
- [ ] ReAct 控制循环核心逻辑
- [ ] 循环检测 + MaxSteps 限制
- [ ] CLI:
agent chat交互模式 - [ ] 基础单元测试
Phase 2:Planning & Memory(第3周)
目标:支持 Plan-and-Execute 模式 + 对话记忆
- [ ] Planner 接口 + LLM-based 实现
- [ ] Plan-and-Execute Agent
- [ ] 短期记忆(滑动窗口 + 消息压缩)
- [ ] 长期记忆(Qdrant 向量存储)
- [ ] 意图路由器(简单 → ReAct,复杂 → Plan-and-Execute)
- [ ] CLI:
agent plan "任务描述"查看计划
Phase 3:Video Tools + RAG 集成(第4周)
目标:完整的视频剪辑场景工具链 + RAG 知识库作为 Tool
- [ ] 视频分析 Tool(模拟实现 → 后续接真实服务)
- [ ] 场景分割 Tool
- [ ] 字幕生成 Tool
- [ ] BGM 推荐 Tool
- [ ] 视频拼接/裁剪 Tool
- [ ] RAG 知识查询 Tool(对接前一个项目)
- [ ] 端到端场景测试
Phase 4:Production Ready(第5周)
目标:可部署的 HTTP 服务 + 完整可观测性
- [ ] Guardrails 框架(Budget / Content / LoopDetect)
- [ ] OpenTelemetry 全链路追踪
- [ ] Prometheus 指标暴露
- [ ] HTTP API + SSE 流式输出
- [ ] Docker 部署方案
- [ ] 性能基准测试
- [ ] 评估框架:Agent 任务完成率量化
项目目录结构
agent-harness/
├── cmd/
│ └── agent/
│ └── main.go # CLI 入口
├── internal/
│ ├── agent/
│ │ ├── react.go # ReAct Agent 实现
│ │ ├── plan_execute.go # Plan-and-Execute Agent
│ │ └── router.go # 意图路由
│ ├── llm/
│ │ ├── client.go # LLM 接口定义
│ │ └── openai.go # OpenAI 实现
│ ├── tool/
│ │ ├── registry.go # Tool 注册中心
│ │ ├── executor.go # 安全执行器
│ │ └── builtin/ # 内置工具
│ │ ├── analyze_video.go
│ │ ├── split_scenes.go
│ │ ├── generate_subtitles.go
│ │ ├── recommend_bgm.go
│ │ ├── concat_videos.go
│ │ ├── export_video.go
│ │ └── rag_query.go
│ ├── memory/
│ │ ├── store.go # Memory 接口
│ │ ├── sliding_window.go # 滑动窗口实现
│ │ └── vector.go # 向量长期记忆
│ ├── planner/
│ │ └── llm_planner.go # LLM 规划器
│ ├── guardrail/
│ │ ├── guardrail.go # Guardrail 接口
│ │ ├── budget.go # Token 预算
│ │ ├── content.go # 内容安全
│ │ └── loop_detect.go # 循环检测
│ └── observe/
│ ├── tracer.go # OpenTelemetry
│ └── metrics.go # Prometheus
├── api/
│ └── server.go # HTTP 服务
├── configs/
│ └── default.yaml # 默认配置
├── eval/
│ ├── testcases/ # 评估测试集
│ └── runner.go # 评估运行器
├── Makefile
├── Dockerfile
└── go.mod评估方案
Agent 任务完成度评测
| 指标 | 含义 | 计算方式 |
|---|---|---|
| Task Completion Rate | 任务完成率 | 成功完成数 / 总任务数 |
| Step Efficiency | 步骤效率 | 最优步数 / 实际步数 |
| Tool Accuracy | 工具调用准确率 | 正确 tool call / 总 tool call |
| Plan Quality | 计划质量(Plan 模式) | LLM-as-Judge 评分 |
| Token Efficiency | Token 使用效率 | 任务质量 / Token 消耗 |
评估命令
bash
# 运行评估测试集
agent eval --testset=eval/testcases/video_editing.json
# 对比 ReAct vs Plan-and-Execute
agent eval --agent=react --agent=plan_execute --compare
# 压力测试
agent bench --concurrency=10 --duration=60s