Proactive(主动沟通)
平台助手在用户没问的时候说一句有用的话,并给一个可点的动作。 用户向说明见主动沟通指南;能力谱系与产品判断见
docs/agent-architecture/proactive-playbook.md。
职责
| 负责 | 不负责 |
|---|---|
| 找出"此刻最值得说的一件事" | 平台公告 / 营销推送 |
| 把它写成一条带卡片的消息 | 替用户做审批 / 付款 / 验收 |
| 记住用户对某类内容的偏好 | 读别人的任务与对话 |
| 时间级触发(每 30 分钟扫描) | 事件级即时提醒(复用同一套结构,尚未接线) |
一次主动沟通的完整链路
ProactiveScheduler(@Cron 每 30 分钟)
→ 最近有任务的人(任务表倒序 + userId 去重,≤50)
→ ProactiveDialogueService.speakSummaryForUser
collect:待确认 / 待付款 / 失败 / 停滞 / 刚完成 / 推进中 / 最近聊过
composeProactiveCard:**只挑一件**,产出 { content, card }
appendAgentMessage → dialogue_messages(metadata.proactive)
→ ProactiveNewsService.speakNewsForUser
任务关键词 × 最近 3 天 digest × 兴趣权重 → 每天最多一条
→ 前端:气泡渲染成卡片(标题 + 一句补充 + 一个主按钮)两条路径共用"今天说过没有"的判断,重复扫描不会重复打扰。
卡片类型
| kind | 说什么 | 主按钮 | 补充信息来自 |
|---|---|---|---|
approval | 某任务在等你确认 | 去确认 | journal.phase.pendingApprovals(金额 / 类型 / 等待天数) |
payment | 某任务等你付款 | 去支付 | journal.phase.pendingPayments |
failed | 某任务执行失败 | 看失败原因 | journal.phase.error |
stalled | 某任务 N 天没动静 | 看看卡在哪 | 最后一条日志标题 |
completed | 某任务刚完成 | 看结果 | tasks.artifacts.length |
in_progress | 某任务还在推进 | 看进展 | 最后一条日志标题 |
conversation | 你和某 agent 聊过 | 整理结论 | 会话的最后消息时间与条数 |
金额一律是最小单位(分 / cent),前端换算后显示(¥44.00),不直接打印数字。
数据模型
proactive_interests(新增)
| 字段 | 说明 |
|---|---|
userId / topic | 唯一键;topic 目前是资讯源的 sourceId |
weight | 累积权重,[-10, 10];正向 +2、负向 -3 |
positive / negative | 表态次数 |
lastSignalAt | 最近一次表态时间 |
权重 ≤ -4 ⇒ 该主题不再推(两次"不感兴趣"即静音)。
dialogue_messages.metadata
json
{
"proactive": true,
"proactiveKey": "proactive:summary:2026-10-31",
"reason": "task_summary",
"proactiveCard": { "kind": "completed", "title": "…", "detail": "…", "actionLabel": "看结果", "action": "open_task", "taskId": "…" }
}接口
| 方法 | 路径 | 作用 |
|---|---|---|
| POST | /api/proactive/news-feedback | 对一条资讯表态(up / down),返回权重与是否已静音 |
| GET | /api/proactive/interests | 列出我各类内容的偏好权重 |
| DELETE | /api/proactive/interests/:topic | 忘掉某个主题(撤销"不感兴趣") |
| POST | /api/journal/proactive-summary | 手动触发一次"今天有没有该说的"(打开工作台时前端调用) |
边界与纪律
- 一条一个关注点:优先级 待确认 → 待付款 → 失败 → 停滞 → 刚完成 → 推进中 → 最近聊过;
- 每天最多一条:
proactive:summary:<date>幂等;资讯另有news:<date>:<newsId>; - 没有事实就不说,但"没有卡住的任务"不算没有事实 —— 完成、推进、聊过都算;
- 失败只降级:调度、取数、写入任何一环失败都不影响用户打开页面;
- 不编造:金额、失败原因、最后一步、交付物数量全部来自 journal 投影与 task 文档;
- 可关:
PROACTIVE_SCHEDULER=off停掉时间级触发(事件级不受影响)。
源码位置
| 位置 | 内容 |
|---|---|
libs/modules/src/task/proactive/proactive-scheduler.ts | 时间级触发点 |
libs/modules/src/task/services/proactive-dialogue.service.ts | 单关注点选择与卡片组装 |
libs/modules/src/task/proactive/services/proactive-news.service.ts | 资讯匹配与推送 |
libs/modules/src/task/proactive/services/proactive-interest.service.ts | 兴趣权重读写 |
libs/modules/src/task/proactive/proactive-feedback.controller.ts | 反馈与偏好接口 |
frontend/src/pages/workspace/components/ProactiveCard.tsx | 卡片组件 |
frontend/src/pages/workspace/index.tsx | 未读红点(本地已读游标) |