Tool-driven 交互式 UI 协议
Tool-driven 交互式 UI 协议
落地说明:本协议的 wire 层走 AG-UI 事件,前端由 assistant-ui 的 generative UI 渲染(见
../03_architecture/05_tech_stack_decision.md);下文的InteractionToolCall/InteractionToolResult是与传输无关的业务 schema。
背景
AgentSurvey 的前端不应该只是聊天输入框。AI Agent 在访谈过程中应能根据研究目标自主决定是否调用交互组件,例如:
- 单选;
- 多选;
- Likert;
- NPS;
- 排序;
- 矩阵题;
- 概念卡片;
- 模态表单;
- consent;
- 文件上传;
- 图片/原型反馈。
这类能力可以抽象成:
Agent tool call -> Interaction schema -> Frontend component -> User result -> Agent continuation核心设计原则
- Agent 只声明“需要什么交互”,不关心 React 组件实现。
- 前端只根据 schema 渲染组件,不解析 prompt 意图。
- 用户交互结果必须以结构化 tool result 回传。
- 所有 tool call 和 result 都要进入 transcript/event log。
- 每次交互都要有 research_intent,方便后续解释。
- UI schema 需要版本化。
Interaction Tool Call
export type InteractionToolCall = { tool: "render_interaction"; interaction_id: string; schema_version: "2026-06-01"; type: InteractionType; title: string; description?: string; instruction?: string; required?: boolean; allow_skip?: boolean; research_intent: string; output_schema: JsonSchema; evidence_policy?: EvidencePolicy; display?: InteractionDisplay; validation?: InteractionValidation; metadata?: Record<string, unknown>;};Interaction Types
export type InteractionType = | "single_choice" | "multiple_choice" | "likert" | "nps" | "rating" | "ranking" | "matrix" | "text_input" | "modal_form" | "concept_card" | "comparison" | "consent" | "file_upload" | "image_annotation" | "task_confirmation";通用字段
export type ChoiceOption = { id: string; label: string; description?: string; value?: string | number | boolean; exclusive?: boolean; metadata?: Record<string, unknown>;};
export type InteractionDisplay = { mode?: "inline_card" | "modal" | "side_panel" | "full_screen"; compact?: boolean; show_progress?: boolean; confirm_before_submit?: boolean;};
export type EvidencePolicy = | "cite_selection" | "cite_free_text" | "cite_followup_turn" | "no_citation_needed";示例:单选
{ "tool": "render_interaction", "interaction_id": "int_primary_pain_001", "schema_version": "2026-06-01", "type": "single_choice", "title": "你当前最主要的痛点是什么?", "description": "请选择最接近的一项,后面我会继续追问具体例子。", "required": true, "allow_skip": true, "research_intent": "identify_primary_pain_point", "options": [ {"id": "setup_complexity", "label": "配置复杂"}, {"id": "low_response_quality", "label": "回答质量不稳定"}, {"id": "manual_analysis", "label": "人工整理成本高"}, {"id": "tool_fragmentation", "label": "工具链分散"}, {"id": "other", "label": "其他"} ], "output_schema": { "type": "object", "properties": { "selected_option_id": {"type": "string"}, "selected_label": {"type": "string"} }, "required": ["selected_option_id"] }, "evidence_policy": "cite_selection", "display": {"mode": "inline_card"}}示例:多选
{ "tool": "render_interaction", "interaction_id": "int_tool_needs_001", "schema_version": "2026-06-01", "type": "multiple_choice", "title": "这个平台你最需要哪些能力?", "description": "最多选择 3 项。", "research_intent": "prioritize_platform_capabilities", "options": [ {"id": "multi_project", "label": "多项目管理"}, {"id": "rag", "label": "知识库/RAG"}, {"id": "interactive_ui", "label": "交互式问卷组件"}, {"id": "evidence", "label": "证据链输出"}, {"id": "custom_tools", "label": "自定义工具"} ], "validation": {"min_items": 1, "max_items": 3}, "output_schema": { "type": "object", "properties": { "selected_option_ids": { "type": "array", "items": {"type": "string"} } }, "required": ["selected_option_ids"] }}示例:Likert
{ "tool": "render_interaction", "interaction_id": "int_value_rating_001", "schema_version": "2026-06-01", "type": "likert", "title": "如果这个平台能自动产出带证据链的结构化访谈结果,你觉得价值有多大?", "research_intent": "measure_perceived_value", "scale": { "min": 1, "max": 5, "min_label": "完全没价值", "max_label": "非常有价值" }, "output_schema": { "type": "object", "properties": { "score": {"type": "integer", "minimum": 1, "maximum": 5} }, "required": ["score"] }}示例:排序
{ "tool": "render_interaction", "interaction_id": "int_feature_ranking_001", "schema_version": "2026-06-01", "type": "ranking", "title": "请按重要性排序这些能力", "research_intent": "rank_feature_importance", "options": [ {"id": "agent_harness", "label": "Agent Harness"}, {"id": "ui_tools", "label": "交互式 UI 工具"}, {"id": "kb", "label": "知识库"}, {"id": "schema_extraction", "label": "结构化抽取"}, {"id": "exports", "label": "导出/集成"} ], "output_schema": { "type": "object", "properties": { "ranked_option_ids": { "type": "array", "items": {"type": "string"} } }, "required": ["ranked_option_ids"] }}Tool Result
export type InteractionToolResult = { interaction_id: string; type: InteractionType; status: "submitted" | "skipped" | "cancelled" | "expired"; value: unknown; submitted_at: string; client_context?: { duration_ms?: number; changed_count?: number; device?: "desktop" | "mobile" | "tablet"; };};示例:
{ "interaction_id": "int_primary_pain_001", "type": "single_choice", "status": "submitted", "value": { "selected_option_id": "manual_analysis", "selected_label": "人工整理成本高" }, "submitted_at": "2026-06-22T10:30:00Z", "client_context": { "duration_ms": 5400, "device": "desktop" }}前端渲染映射
| interaction type | 推荐组件 |
|---|---|
| single_choice | RadioCardGroup |
| multiple_choice | CheckboxCardGroup |
| likert | LikertScale |
| nps | NpsScale |
| rating | StarRating / NumericRating |
| ranking | DragSortableList |
| matrix | MatrixQuestionTable |
| text_input | TextAreaCard |
| modal_form | ModalForm |
| concept_card | StimulusCard |
| comparison | ComparisonCards |
| consent | ConsentPanel |
| file_upload | UploadDropzone |
| image_annotation | ImageFeedbackCanvas |
| task_confirmation | ConfirmationCard |
Agent 使用策略
Agent 不应滥用交互组件。建议规则:
- 当需要可比较、可统计的数据时调用组件。
- 当用户开放回答已经足够清楚时,不必再弹组件。
- 一个 screen 最多展示一个主交互。
- 组件之后通常要有自然语言 follow-up。
- 对敏感问题应允许跳过。
- 对研究关键字段,可先问开放题,再用组件确认。
数据记录
每次 interaction 都应写入:
tool_calls;interaction_events;transcript_turns;extraction_evidence;session_state。
这样才能后续重放、审计和分析。