Agent Harness 设计
Agent Harness 设计
目标
Agent Harness 是 AgentSurvey 的核心。它负责把研究配置、会话状态、LLM、工具、知识库和输出 schema 组织成一个可控、可审计、可扩展的访谈运行时。
不要把 Harness 简化为一个 prompt。它应该是显式状态机。
Harness 核心职责
- 加载 study config。
- 管理 session state。
- 判断当前研究 coverage。
- 决定下一步动作。
- 调用 LLM 和工具。
- 控制追问深度。
- 触发结构化抽取。
- 处理交互式 UI 结果。
- 判断结束条件。
- 记录 agent decision log。
状态机
START -> LOAD_CONTEXT -> CONSENT_OR_SCREENING -> OPENING -> ASK_OR_PROBE -> OPTIONAL_INTERACTION -> EXTRACT -> EVALUATE_COVERAGE -> NEXT_TOPIC_OR_PROBE -> SUMMARY_CONFIRMATION -> CONCLUDE -> POST_SESSION_EXTRACTION -> ENDAgent Actions
export type AgentAction = | { type: "send_message"; content: string } | { type: "ask_question"; question: string; objective_id?: string } | { type: "probe"; question: string; based_on_turn_id: string } | { type: "render_interaction"; interaction: InteractionToolCall } | { type: "retrieve_knowledge"; query: string } | { type: "extract_fields"; fields?: string[] } | { type: "summarize_and_confirm"; summary: string } | { type: "conclude"; reason: string };Session State
export type SessionState = { session_id: string; study_id: string; participant_id?: string; status: "created" | "active" | "waiting_for_user" | "waiting_for_tool" | "completed" | "abandoned"; current_phase: HarnessPhase; current_objective_id?: string; covered_objectives: Record<string, CoverageState>; extracted_fields: Record<string, ExtractedFieldState>; pending_interaction_id?: string; turn_count: number; started_at: string; last_activity_at: string; config_versions: ConfigVersionRefs;};Coverage State
export type CoverageState = { objective_id: string; status: "not_started" | "in_progress" | "covered" | "skipped" | "blocked"; confidence: number; evidence_count: number; last_turn_id?: string; missing_info?: string[];};Study Objective
export type StudyObjective = { id: string; title: string; description: string; priority: "must" | "should" | "optional"; suggested_questions: string[]; success_criteria: string[]; related_output_fields: string[]; max_probe_count?: number; interaction_tools?: string[];};Harness Decision Prompt 结构
LLM 不直接接收所有数据,而是接收结构化上下文:
System role: You are an AI research interviewer...
Study brief: - Goal - Target participant - Research constraints
Current objective: - Objective title - Success criteria - Missing information
Session summary: - Participant background - Key known facts - Covered objectives - Extracted fields
Recent transcript: - Last N turns
Available tools: - render_interaction - retrieve_knowledge - extract_fields - conclude
Decision instruction: Choose exactly one next action.Next Action Decision
建议让模型输出严格结构:
{ "action_type": "probe", "rationale": "用户提到了配置复杂,但没有给出具体例子,需要追问场景。", "objective_id": "obj_pain_point", "content": { "question": "你能举一个最近一次觉得配置复杂的具体例子吗?当时你想完成什么任务?" }}追问策略
Agent 应遵循:
- 先开放,后结构化。
- 对泛泛回答追问具体例子。
- 对强情绪回答追问影响和原因。
- 对矛盾回答澄清。
- 对关键字段缺失进行 targeted probe。
- 每个 objective 限制最大 probe 次数。
- 不为了填满 schema 过度追问。
- 在用户疲劳时优先结束。
什么时候调用交互组件
适合调用:
- 需要选择、排序、评分、确认;
- 需要降低用户输入成本;
- 需要把开放回答转成结构化变量;
- 需要可比较数据;
- 需要展示概念/选项/任务。
不适合调用:
- 用户正在讲故事;
- 需要建立信任;
- 问题很敏感;
- 追问可以更自然地完成;
- 组件会打断思路。
Extraction 集成
Harness 可以在三类节点触发抽取:
After user message -> lightweight extractionAfter objective covered -> checkpoint extractionAfter session completed -> final extraction轻量抽取用于更新 state,最终抽取用于结果页。
结束条件
可以结束的条件:
- 所有 must objectives 已覆盖。
- 关键 output fields 达到 confidence threshold。
- 用户表示没有更多补充。
- 达到最大轮次或最大时长。
- 用户要求结束。
- screening 不符合条件。
- safety/privacy policy 触发。
Decision Log
每次 Agent 决策都要记录:
export type AgentDecisionLog = { id: string; session_id: string; turn_id?: string; phase: HarnessPhase; input_summary: string; selected_action: AgentAction; rationale?: string; model: string; prompt_version_id: string; tool_candidates?: string[]; latency_ms: number; token_usage?: TokenUsage; created_at: string;};Harness MVP 实现建议
实现底座 = LangGraph(见 05_tech_stack_decision.md)。本文的
SessionState映射到 LangGraph graph state;waiting_for_tool(等待受访者交互)由interrupt()实现;session 可重放 / audit / decision log 由 checkpointer(PostgresSaver)提供。下面的HarnessRuntime是 graph 节点编排的逻辑视图,而非另起炉灶的自研运行时。
第一版不必引入 multi-agent 或可视化 graph builder,用 LangGraph 实现固定状态机 + 配置驱动即可:
StudyConfig -> Objectives[] -> OutputSchema -> EnabledTools -> AgentPolicy
HarnessRuntime -> choose_next_objective() -> decide_next_action() -> execute_action() -> update_state() -> maybe_extract() -> maybe_conclude()后续再逐步引入(其中 custom state graph / human handoff / time-travel debugging 多由 LangGraph 原生提供):
- custom state graph;
- multi-agent;
- visual debugger(LangGraph Studio);
- human handoff;
- auto evaluation。