Skip to content

Interview Runtime

Interview Runtime

1. 目标 & 范围

目标

提供受访者端完整的 AI 访谈运行时能力:从受访者点击公开链接到 session 结束,全程由 LangGraph harness 驱动,经 AG-UI 协议将事件推送至前端 assistant-ui,使受访者以自然对话方式完成研究目标覆盖,并在整个过程中生成可审计、可重放的结构化 transcript。

范围(本模块)

  • Session 生命周期管理(created → active → completed/abandoned
  • 消息往返与 AG-UI streaming
  • Harness 决策循环(ask_question / probe / render_interaction / extract_fields / conclude
  • Consent 采集与 screening 判断
  • 追问策略执行与结束条件评估
  • Pending interaction 阻塞(LangGraph interrupt()
  • Summary 确认流程

非范围(见其他模块)


2. 用户故事

作为受访者,我希望通过公开链接无需注册即可进入访谈,以便降低参与门槛,让我专注于表达意见而非理解系统。

作为受访者,我希望 AI 以自然对话方式提问,而不是展示一份表格问卷,以便感受到被倾听、愿意深入分享。

作为受访者,我希望交互组件(选择、评分等)自然出现在对话流中,以便在需要时快速表达结构化偏好,而不打断叙述节奏。

作为受访者,我希望在访谈开始前看到数据使用说明并确认 consent,以便了解自己的数据如何被使用。

作为受访者,我希望随时可以结束访谈,以便在任何时刻退出而不感到被强制。

作为研究人员,我希望每个 session 完整记录 transcript、tool call、决策日志与 event log,以便事后审计 agent 行为,重放与排查问题。

作为研究人员,我希望 harness 自动追问直到覆盖 must objectives 或达到上限,以便不依赖人工主持也能获得足够深度的访谈数据。


3. 功能需求

3.1 Session 创建与初始化

FR-04-1(P0)受访者通过公开 slug 创建 session

  • 调用 POST /api/public/studies/{public_slug}/sessions,返回 session_id 与初始状态 created
  • 验收要点:无需认证、study 必须处于 published 状态、返回 session_idstatus: "created"

FR-04-2(P0)Session 记录配置版本快照

  • 创建时锁定并记录 study_config_version_idagent_config_version_idoutput_schema_version_idmodel_config_version_id
  • 验收要点:快照字段非空;后续对 study 配置的修改不影响已进行中的 session

FR-04-3(P0)Session 状态机完整支持

  • 状态流转:created → active → waiting_for_user / waiting_for_tool → active → completed / abandoned
  • 验收要点:每次状态变更写入 event log;completedabandoned 为终态,不可回退

FR-04-4(P0)Consent 采集

  • Harness 在 CONSENT_OR_SCREENING 阶段通过 render_interaction 渲染 ConsentPanel,受访者必须提交 status: "submitted" 才可继续
  • 验收要点:受访者拒绝 consent 则 session 状态置为 abandoned,后续 harness 不再推进;consent 结果记入 transcript

FR-04-5(P0)Screening 判断

  • Harness 可在 consent 后向受访者提问 screening 问题;基于回答由 LLM 判断是否符合研究目标
  • 验收要点:不符合 screening 条件时 session 以 abandoned 结束并给出友好告知;符合条件时进入 OPENING 阶段

3.3 消息往返与 AG-UI Streaming

FR-04-6(P0)受访者发送消息

  • 调用 POST /api/sessions/{session_id}/messages,后端存入 transcript turn,唤醒 harness 决策循环
  • 验收要点:消息写入后 session 状态由 waiting_for_user 切换为 active;turn 有唯一 turn_id

FR-04-7(P0)AG-UI 事件流

  • 后端 LangGraph harness 经 AG-UI 协议(HTTP/SSE)向前端推送业务语义事件,前端 assistant-ui 通过 @assistant-ui/react-ag-ui adapter 消费
  • 支持的 StreamEvent 类型(见 api_contracts):
    • message.delta:assistant 消息增量
    • message.completed:消息结束,携带 turn_id
    • tool.call:harness 工具调用通知(render_interaction / extract_fields / conclude
    • interaction.render:前端渲染交互组件
    • extraction.completed:轻量抽取结果
    • session.completed:session 结束,携带摘要
    • error:运行时错误
  • 验收要点:前端流式渲染 message.deltatool.call 后前端展示 pending 状态;error 时前端给出非技术性提示

FR-04-8(P0)前端禁用 chatbot 式编辑

  • 受访者 Interview 端 ChatTimeline 禁用 edit / regenerate / branch 操作
  • 验收要点:已发出的消息无法修改;无”重新生成”按钮;操作历史严格线性

3.4 Harness 决策循环

FR-04-9(P0)Harness 状态机节点

  • Harness 经以下节点顺序执行(对应 02_agent_harness.md 状态机): LOAD_CONTEXT → CONSENT_OR_SCREENING → OPENING → ASK_OR_PROBE → OPTIONAL_INTERACTION → EXTRACT → EVALUATE_COVERAGE → NEXT_TOPIC_OR_PROBE → SUMMARY_CONFIRMATION → CONCLUDE → POST_SESSION_EXTRACTION → END
  • 验收要点:每次节点切换写入 AgentDecisionLog;LangGraph checkpointer 持久化每个节点后的 graph state

FR-04-10(P0)Agent 动作执行

  • Harness 在每个决策节点输出且仅输出以下动作之一,并记录 rationale
    • ask_question:提出新问题,关联 objective_id
    • probe:对当前回答追问,携带 based_on_turn_id
    • render_interaction:触发交互组件渲染
    • extract_fields:触发字段抽取
    • conclude:结束 session,携带 reason
  • 验收要点:每次决策有且仅有一个动作;rationale 字段非空;决策日志含 modelprompt_version_idlatency_mstoken_usage

FR-04-11(P0)AgentDecisionLog 持久化

  • 每次 harness 决策写入 AgentDecisionLog(含 session_idturn_idphaseinput_summaryselected_actionrationalemodellatency_ms
  • 验收要点:decision log 可通过 GET /api/sessions/{session_id} 关联查询;不得丢失任何决策记录

3.5 追问策略

FR-04-12(P0)先开放后结构化追问

  • Harness 对每个 objective 先发出开放式问题,待受访者给出泛泛回答后再 proberender_interaction
  • 验收要点:同一 objective 下第一个动作为 ask_question,不直接以 render_interaction 开场

FR-04-13(P0)最大追问次数限制

  • 每个 StudyObjective 配置 max_probe_count(默认值:3);harness 对单个 objective 的 probe 动作不超过该上限
  • 验收要点:probe 计数存入 SessionState.covered_objectives[obj_id];达到上限后 harness 转向下一个 objective 或触发 extract_fields

FR-04-14(P0)追问触发条件

  • Harness 应在以下条件触发 probe:回答过于泛泛(无具体例子)、回答含强情绪(追问影响与原因)、回答存在内在矛盾(追问澄清)、关键字段缺失(targeted probe)
  • 验收要点:probe rationale 须指明触发原因(可人工审查)

FR-04-15(P1)用户疲劳识别

  • Harness 检测到受访者回答明显变短或频繁发出结束意愿信号时,优先触发 conclude 而非继续追问
  • 验收要点:测试场景中,连续 3 次单字回答后 harness 不再继续 probe

3.6 交互组件(Pending Interaction)

FR-04-16(P0)render_interaction 触发流程

  • Harness 动作 render_interaction → 后端生成 InteractionToolCall(含 interaction_idtypeschema_versionresearch_intent)→ 经 interaction.render AG-UI 事件推送 → 前端 InteractionRenderer 按 type 路由至对应组件 → 受访者提交后调用 POST /api/sessions/{session_id}/interactions/{interaction_id}/submit → 结果写入 transcript → harness 继续
  • 验收要点:全流程无断点;interaction_id 全局唯一;tool call 与 tool result 均写入 event log

FR-04-17(P0)LangGraph interrupt 阻塞

  • render_interaction 触发后,LangGraph graph 通过 interrupt() 暂停,session 状态切换为 waiting_for_tool;收到 submit 请求后恢复执行
  • 验收要点:waiting_for_tool 期间受访者发送新消息不触发 harness 前进;submit 恢复后 session 状态回到 active

FR-04-18(P0)交互结果记录

  • 每次 interaction 提交写入 tool_callsinteraction_eventstranscript_turnssession_state;skipped 结果同样记录(status: "skipped"
  • 验收要点:GET /api/sessions/{session_id} 返回的 tool_calls 包含对应记录;研究人员在结果页可查看每次组件的提交值

FR-04-19(P0)每屏单一主交互原则

  • 同一时刻 ChatTimeline 中最多一个交互组件处于待提交状态;前一个组件未提交或跳过前,harness 不推送新的 render_interaction
  • 验收要点:并发提交测试中不出现两个并行 pending interaction

3.7 结束条件

FR-04-20(P0)Must objectives 全覆盖结束

  • 所有 priority: "must" 的 objective 状态达到 covered 时,harness 可触发 conclude
  • 验收要点:concludereason 字段值为 "all_must_objectives_covered"

FR-04-21(P0)关键字段 confidence threshold 结束

  • 当 output schema 中所有 required: true 字段的 confidence 均达到配置的 confidence_threshold 时,harness 可触发 conclude
  • 验收要点:conclude 前最后一次 extract_fields 的结果可验证 threshold 已满足

FR-04-22(P0)最大轮次 / 时长结束

  • 达到 study 配置的 max_turn_countmax_duration_minutes 时,harness 强制触发 concludereason"max_turns_reached""max_duration_reached"
  • 验收要点:配置 max_turn=5 的 study,第 5 轮结束后 harness 不再问新问题

FR-04-23(P0)受访者主动结束

  • 受访者发送明确结束意愿信号(如”结束”、“我说完了”)时,harness 识别并触发 concludereason"participant_requested_end"
  • 验收要点:测试场景中受访者发送”结束”后 session 进入 summary 确认流程,不再继续追问

FR-04-24(P0)Screening 失败 / safety 触发结束

  • Screening 判断不符合或 safety/privacy policy 触发时,harness 触发 concludereason"screening_failed""safety_triggered",session 状态置为 abandoned
  • 验收要点:abandoned session 不出现在研究人员结果页的有效 session 列表中

3.8 Summary 确认

FR-04-25(P0)session 结束前 summary 确认

  • Harness 在 conclude 前执行 summarize_and_confirm 动作,向受访者展示本次访谈摘要,受访者可补充或确认
  • 验收要点:StreamEvent 类型 session.completed 携带 summary 字段;前端展示 CompletionScreen 组件

FR-04-26(P1)后处理抽取

  • Session 进入 completed 后,异步触发 POST_SESSION_EXTRACTION,对全量 transcript 执行最终 extract_fields
  • 验收要点:最终抽取结果写入 DB;结果页可查看(见 06_extraction_evidence

3.9 受访者体验约束

FR-04-27(P0)受访者无需理解 Agent / 工具概念

  • 前端不向受访者暴露”工具调用”、“Agent 决策”、“LangGraph”等内部概念;所有 streaming 动作对受访者表现为自然的消息或组件
  • 验收要点:ChatTimeline 中无 tool call 原始 JSON;loading 状态显示”正在思考…”而非技术性信息

FR-04-28(P0)访谈中断恢复

  • 受访者关闭页面后,凭同一 session_id 重新打开可继续未完成的 session(session 未达到终态)
  • 验收要点:waiting_for_user 状态的 session 重新加载后,ChatTimeline 恢复已有 transcript;受访者可继续作答

4. 关键流程

4.1 完整 Session 流程

1. 受访者访问公开 URL /interview/{public_slug}
2. 前端调用 POST /api/public/studies/{public_slug}/sessions → session_id
3. 建立 SSE 连接,接收 AG-UI 事件流
4. Harness: LOAD_CONTEXT(加载 study config、锁定版本)
5. Harness: CONSENT_OR_SCREENING
5a. render_interaction(consent) → 受访者确认 → transcript
5b. screening 问答 → 不符合 → abandoned;符合 → 继续
6. Harness: OPENING → ask_question(开场问题)
→ AG-UI message.delta / message.completed → ChatTimeline 渲染
7. 受访者回复 → POST /api/sessions/{session_id}/messages
8. Harness: ASK_OR_PROBE(评估 coverage)
→ probe / ask_question / render_interaction
9.(若 render_interaction)→ LangGraph interrupt()
→ interaction.render 事件 → InteractionRenderer 展示组件
→ 受访者提交 POST .../interactions/{id}/submit
→ harness 恢复
10. EXTRACT(checkpoint extraction)→ extraction.completed 事件
11. EVALUATE_COVERAGE → 未覆盖 → 回到步骤 8;已覆盖 → 继续
12. Harness: SUMMARY_CONFIRMATION → summarize_and_confirm
→ 受访者确认 / 补充 → 再次 extract
13. Harness: CONCLUDE → session.completed 事件
→ 前端展示 CompletionScreen
14. POST_SESSION_EXTRACTION(异步)

4.2 Runtime Event Flow(引用 01_system_architecture)

受访者发送消息
→ Session API 接收 → 存入 transcript turn
→ Harness 加载 state → 检查 coverage 与 next objective
→ 可选 RAG 检索
→ LLM 决策下一动作(ask / probe / render_interaction / extract / conclude)
→ 后端推送 AG-UI 事件流
→ 前端渲染消息或交互组件
→ 受访者提交交互结果
→ 存入 transcript → harness 继续

4.3 Pending Interaction 流程(LangGraph interrupt)

Harness 决策 render_interaction
→ 生成 InteractionToolCall(interaction_id、type、schema)
→ tool.call 事件 → interaction.render 事件
→ LangGraph interrupt() → session.status = waiting_for_tool
→ 前端 InteractionRenderer 展示组件
→ 受访者操作并提交 → POST .../interactions/{id}/submit
→ Backend 验证 → 写入 interaction_events / transcript
→ LangGraph resume → session.status = active
→ 继续决策循环

5. 数据

主要实体(引用 03_data_model.md

实体关键字段
Sessionsession_id, study_id, status, current_phase, turn_count, started_at, last_activity_at, config_versions
SessionStatecovered_objectives: Record<objective_id, CoverageState>, extracted_fields, pending_interaction_id
TranscriptTurnturn_id, session_id, role (user/assistant), content, created_at
ToolCalltool_call_id, session_id, tool_name, tool_input, tool_result, created_at
InteractionEventinteraction_id, session_id, type, status, value, submitted_at, client_context
AgentDecisionLogid, session_id, turn_id, phase, input_summary, selected_action, rationale, model, prompt_version_id, latency_ms, token_usage, created_at
EventLogappend-only,见下方事件类型

Event Log 事件类型(引用 01_system_architecture)

session.created
participant.message.created
agent.message.started
agent.message.delta
agent.message.completed
tool.call.created
tool.call.completed
interaction.rendered
interaction.submitted
extraction.started
extraction.completed
session.completed
session.abandoned

6. 接口

REST 端点(引用 api_contracts

方法路径说明
POST/api/public/studies/{public_slug}/sessions创建 session(公开,无需认证)
POST/api/sessions/{session_id}/messages受访者发送消息,触发 harness
POST/api/sessions/{session_id}/interactions/{interaction_id}/submit提交交互组件结果,恢复 interrupt
GET/api/sessions/{session_id}查询 session 详情(transcript、tool_calls、extracted_fields)

AG-UI 事件(Wire 层)

后端 LangGraph 经 AG-UI 协议(HTTP/SSE)推送事件,前端通过 @assistant-ui/react-ag-ui adapter 消费。业务语义 StreamEvent 类型如下(详见 api_contracts):

type StreamEvent =
| { type: "message.delta"; content: string }
| { type: "message.completed"; turn_id: string }
| { type: "tool.call"; tool_call_id: string; tool_name: string; tool_input: unknown }
| { type: "interaction.render"; interaction: InteractionToolCall }
| { type: "extraction.completed"; fields: ExtractedField[] }
| { type: "session.completed"; summary: string }
| { type: "error"; message: string }

7. 验收标准

AC-04-1:受访者访问公开 URL,无需登录,POST /api/public/studies/{slug}/sessions 返回 session_idstatus: "created",耗时 < 500ms。

AC-04-2:Session 记录 study_config_version_id 等 4 个版本字段;发布新版 study config 后,已有进行中 session 的 harness 行为不变。

AC-04-3:Consent 面板渲染后,受访者提交拒绝,session status 置为 abandoned,后续消息接口返回 403/410,不继续推进 harness。

AC-04-4:受访者发送消息,前端在 200ms 内开始接收 message.delta 事件,字符逐步呈现;message.completed 事件后 turn_id 可查询。

AC-04-5:Harness 触发 render_interactioninteraction.render 事件到达前端,InteractionRenderer 正确渲染对应组件(single_choice → RadioCardGroup,likert → LikertScale 等);渲染期间 session statuswaiting_for_tool

AC-04-6:受访者提交交互组件,POST .../interactions/{id}/submit 返回 ok: true;session status 恢复 active;harness 继续决策;transcript 中可查到对应 tool call 与 tool result。

AC-04-7:同一时刻 ChatTimeline 最多一个交互组件处于 pending 状态;并发压测中不出现两个并行 pending interaction。

AC-04-8:同一 objective 下 probe 动作不超过 max_probe_count(默认 3);超过上限后 harness 切换 objective 或触发 extract,不继续 probe 同一 objective。

AC-04-9:所有 must objectives 覆盖后,harness 触发 summarize_and_confirm,受访者确认后 session.completed 事件推送,status 置为 completed

AC-04-10:配置 max_turn_count: 10 的 study,第 10 轮回复后 harness 强制 conclude,reason"max_turns_reached",session 进入 completed

AC-04-11:受访者发送”结束”,harness 在下一决策循环触发 concludereason"participant_requested_end",不再继续发送新问题。

AC-04-12:ChatTimeline 中不出现 tool call 原始 JSON、“LangGraph”、“Agent”等内部术语;assistant loading 状态显示”正在思考…”。

AC-04-13:所有 harness 决策均写入 AgentDecisionLog,字段 rationale 非空;GET /api/sessions/{session_id} 可关联查询。

AC-04-14:Event log 包含完整事件序列(session.created → 消息事件 → tool 事件 → session.completed);给定 session_id 可完整重放 session 行为。

AC-04-15waiting_for_user 状态的 session,受访者重新打开页面后,ChatTimeline 恢复已有 transcript,可继续作答。


8. 边界 & 非目标

边界 / 非目标说明
受访者无需理解 Agent 概念所有 Agent/工具内部状态对受访者不可见
不支持 chatbot 式 edit/regenerateChatTimeline 为严格线性历史,不支持消息编辑或分支
不支持多轮并发 session(单人)同一受访者同一时刻只有一个 active session
不做实时多人协作访谈MVP 不做焦点小组或多人同时访谈
不做视频 / 音频输入MVP 只支持文本消息与结构化交互组件
Interaction 组件实现不在本模块组件 UI 与题型详见 05_interaction_components
字段抽取逻辑不在本模块抽取与 evidence 链详见 06_extraction_evidence
LangGraph 内部调度不暴露给前端wire 层统一走 AG-UI;前端不直接访问 LangGraph API

9. 依赖 & 风险

依赖

依赖类型说明
03_study_builder上游study config、objectives、output schema、agent config 必须已发布
05_interaction_components协作render_interaction 工具调用的组件渲染实现
06_extraction_evidence下游extract_fields 动作的抽取逻辑与 evidence 链
AG-UI 协议外部@assistant-ui/react-ag-ui adapter 与 LangGraph AG-UI 输出集成
LangGraph checkpointer(PostgresSaver)基础设施session 可重放、interrupt/resume、time-travel 依赖 checkpointer 正确配置
LiteLLM Model Gateway基础设施Harness LLM 调用经 LiteLLM 路由,provider 故障影响全部 session

风险

风险影响缓解措施
AG-UI adapter 与 LangGraph 集成不稳定前端无法消费事件流,访谈中断早期搭建 spike PoC,固定 adapter 版本;fallback 到 raw SSE
Streaming 事件乱序或丢失前端 ChatTimeline 显示异常每条事件携带 turn_id 和顺序号;前端做幂等渲染
LangGraph interrupt 恢复超时受访者提交后长时间等待设置 interrupt 超时(建议 30s);超时后推送 error 事件并允许重试
Harness 追问过度受访者疲劳流失max_probe_count 强制限制;P1 引入疲劳检测(FR-04-15)
LLM 决策输出不符合 AgentAction schemaHarness 无法执行动作,session 阻塞structured output 解析失败时触发 fallback(ask_question 默认动作)并写入 error log
session 并发量增加时 DB checkpointer 成为瓶颈响应延迟上升MVP 单机 PostgresSaver;P1 评估 Redis 或分库