一个助理,一段不分段的对话
统一会话的 7×24 协同助理:善用记忆与数据、代你行动、委派长程、回答可追溯
Tanka 的 Assistant 模式不是「一问一答的机器人」,而是一个 7×24 在线的 Tanka AI 助理——Tanka 的核心是企业协同。它在同一个会话里长期工作:没有「新建会话」的概念,同一个 room_id 就是它全部的记忆锚点。它以用户的第一人称视角代为产出与对外沟通(替你写文章、起草发言、发消息,而不是用旁观者口吻),但本质是助理:凡代表你做的关键动作都要先经你授权。它向内拥有持久的检查点与工作区,向外伸出五条能力触手:长期记忆、第一方数据、第一方 Action API、第三方 Link 数据、第三方 Link API;面对漫长或复杂的工作,它会委派(handoff)给专属的 flow session 并从这个座位上掌舵,结果以 session_report 自动回传;而它给出的每个结论都可追溯到真实来源(引用)。
设计公理
在看模块图之前,先认同五条立场——它们决定了后面每一个机制为什么是这样设计的。来源:assistant/prompts/assistant.jinja 的 agent_identity 与 handoff 心智块。
用户视角,本质是助理
这是一个 7×24 在线的 Tanka AI 助理(Tanka 核心是企业协同)。它以用户的第一人称视角替你产出与对外沟通——写文章、起草发言、发消息时用「我」而非旁观者口吻;但它本质是助理、不是你本人:凡代表你做的关键动作(对外可见的创建 / 变更 / 删除)都要先经你授权。
可用是职责,委派是选择
默认不是「好的」,而是「我来办」。保持可用是职责——不把自己埋进长任务;大活委派给专属 flow session 并从这个座位掌舵。委派是为了保持可用,不是能力上限:它本可以亲自做。
先取证,不靠记忆
对人和对象动作前,现查 ID、现读状态,绝不凭对话里记得的旧值。给出结论时还要标明来源(引用)。这是正确性与可信的地基。
行动前先言明
代表用户行动前先announce、先gather context、先draft plan 再confirm。读操作可以主动,写操作必须经人审(HITL)。
一段连续的关系
不分 session 意味着上下文、授权、待办、工作区都沉淀在同一条时间线上。压缩与 Turn Summary 让这条线可以无限延长而不丢事实。
顶层架构
用户与一个统一会话内核对话;内核向「读/感知」「写/行动」「委派/长程」三个方向伸出能力。读路径自由,写路径过 HITL,长程路径委派给子会话、结果经 session_messaging 收件箱自动回传。仅 templateCode=ASSISTANT 的房间开放委派(create/send)。
这张图回答一个问题:同一个助理,如何既"懂我"又"能替我办事"还能"盯着长期的事"? 答案是把能力按数据流向分成三束。读/感知束让它先理解——从长期记忆、第一方业务数据、第三方文件中取证,并给结论标注来源(引用);写/行动束让它落地——但每个对外可见的动作都被一张确认卡拦在用户面前;委派/长程束让它跨越单次回合的边界——把漫长或复杂的工作委派给专属 flow session(create/send),自己留在座位上保持可用,结果以 session_report 经 session_messaging 收件箱自动回到这条会话时间线。
统一会话内核
"不分 session"不是省略,而是一种刻意的设计:单一会话、近乎无限的上下文——用一个稳定的 room_id 作为全部状态的锚,让记忆、授权与工作产物在一条时间线上累积;近期原样在场,远期压缩成摘要,要原文时再按检索回捞。
三个让对话"长得了"的机制
能力版图:读 · 写 · 委派 · 可追溯
五条数据/Action 触手覆盖"读什么、写什么、内外之分";再加两项贯穿能力——把长程交给子会话的委派,以及给每个结论标注真实来源的引用。读自由、写过审、委派回传、引用可溯。
长期记忆
被 AI 深度处理、跨会话沉淀的记忆——不是原始消息,而是从中提炼出的结构化记忆。(原始第一方数据见 ②、第三方文件见 ④,此处不重复。)经 search_tools 检索召回。
- 情景记忆 Episodic Memory
- Worklog(Tanka Work Memory)
- 用户画像 Profile · 偏好 Preference
- 语义记忆 Semantic · 实体/关系/行为
- RunMode:WORK / COMPANION
第一方数据
Tanka 平台原生业务对象的精确读取,结构化、可过滤。
- 消息 / 群 / 联系人(人与群)
- 日历 / 会议(Zoom 摘要)
- 邮件 / 备忘 / 投票
- Followup 待办 · 可用时段查询
第一方 Action API
约 22 个写操作,经 ConfirmationSpec 渲染确认卡,提交到 TankaServerAPI 后端。
- 发消息 · 建群 · 增/删成员
- 建/改/取消日历 · 建会议
- 发邮件 · 建/操作投票
- 导入/起草备忘 · Followup 派发
第三方 Link 数据
已绑定第三方应用的只读访问;部分文件型数据(Dropbox/GDrive/Notion)直接进入长期记忆索引。
- 工具名前缀判定只读(list_/get_/search_…)
- Jira/Linear/GitHub/Confluence 读
- 云盘/文档/表格读
- italent 等纯读应用
第三方 Link API
第三方应用的写操作,统一经 POST /thirdparty/{app},同样过确认卡,未绑定则引导绑定。
- oh-link 网关(多数应用)
- direct OAuth(huggingFace/apify)
- PipeDream(clickup/line/…)
- 26 个 enabled app
委派与提醒
跨越单次回合:大活委派给可复用的 flow session;需要盯的事设成 reminder(异步跟进),由事件/时间触发自动回来;两者都经 session_messaging 收件箱回传或唤醒。底层由 wait_task 引擎驱动。
- 委派 handoff:create / send / list / get / semantic_search
- reminder 异步跟进:事件 CHAT/EMAIL/ARENA/VOTE · 时间 POINT/CRON
- 回传:session_report / reminder 触发经 NOTIFY
- INV-1:ROOT 可派生,DERIVED 不可再生
引用 Citation
读到的每条数据都能成为可点击的来源:结论里嵌 ref_N 标记,落地为 source:// 深链,答案成为一条可回溯的信息链。
- 可引用:聊天/备忘/邮件/日历/联系人/文件
- ref_N 标记 → source:// 深链
- referenceSources SSE 事件给前端
- 只引真实来源,绝不杜撰
跨源检索:把记忆与数据"想起来"
检索不是外部服务,而是助理自己的 agentic 行为:它自行决定打法、发起检索、判断够不够、不够就再来一轮。打法有两种,由 query_rewrite_and_route 按任务意图自行路由:
两种打法的召回结果都先经 rerank 重排去重 + 预处理,助理再据此判断是否够用——下图是助理这套自驱的检索回路。
委派与回传:Handoff + session_messaging
委派的判据不是任务看起来多大,而是「回完这句话,事情是否就结束了」:一次性问答留在主会话;有下一轮的工作(草稿要评审、交付物要修订、一条线要持续跟进)交给一个能承载这条弧线的 flow session。flow session 是耐用的——可复用、可数月承接一条线;房间格局属于用户,先 list 看已有房间、把活路由到已经在做这条线的房间,别为一句话能办完的事新开房间。委派后 send 持续追加指令(fire-and-forget),完成时结果自动回传。
所有「回传/唤醒」都走统一的 session_messaging 收件箱:子会话完成 → COMPLETION(即 session_report,带摘要 + 产物);子会话撞到确认卡 → NEEDS_CONFIRMATION 回报父助理;reminder 触发 → NOTIFY。投递采用 TankaServerAPI pull-wakeup:push 只是「有事了」的信号(best-effort),真正的真相源是 pull /work/watcher/events 的 drain——按 immediate / deferred / passive 的 activation 分桶,稳定 message_id 保证不丢不重。
可追溯回答:引用与来源
助理读到的数据不止用于作答,还能成为可点击的来源。整条链路由 CitationMiddleware(仅 ASSISTANT 房间挂载)驱动:读类 tanka_api 结果带回 source_items,中间件在 awrap_tool_call 时登记来源、发号 ref_N 并把 ref 注入工具结果 XML(原始 artifact 阅后即焚,不进 checkpoint);助理在文本里用 #ref_N 标注;stream rewriter 边出边把标记改写成 source:// 深链,并在结尾发一个 referenceSources SSE 事件给前端;回合结束再把 ref 标记从历史里剥干净。铁律:只引真实发过号的 ref、绝不杜撰,同源去重、按出现顺序排列。可引用的对象覆盖聊天消息、备忘、邮件、日历、联系人、链接与文件。
用户 ↔ 助理 用例
把上面的设计放进真实对话。每个用例标注「在起作用的能力」,看同一套机制如何应对不同场景。
跨源晨间回顾
"我昨天错过了什么重要的事?"
助理先用跨源检索召回近期第一方数据(聊天/邮件/备忘/投票),并结合你的长期记忆(画像 / Worklog)判断什么值得关注,再用第一方数据精确拉取细节,按主题归纳成简报——每条结论都带可点击来源(引用)。不是把信息倒给你,而是替你判断什么重要、且每句都可回溯。
代我办事
"建个 Q3 复盘群把张三李四拉进来,约周四下午的会。"
助理先现查联系人 ID(不靠记忆)并 Precheck(群成员数、时段空闲),再把"建群 + 日历邀请"渲染成确认卡。用户可逐项 approve / edit / reject,也可对"建群"选 always-allow——此后同类操作本会话内免确认。
跨第三方编排
"把本周 Jira 上 Done 的 issue 整理成周报,发到 Slack 的 #team。"
助理用第三方 Link 数据读 Jira,在 workspace 里成稿,再用第三方 Link API写 Slack。若 Slack 未绑定,会抛 McpNotLinkedException,助理转而弹出绑定引导卡,等用户授权后再续。
长程提醒与唤醒
"等财务回复'预算'那封邮件,就提醒我,并帮我起草下一步。"
这超出了单次回合——助理设一个 EVENT_EMAIL reminder(异步跟进),本回合即结束,会话保持但不阻塞。数小时后财务回信,单实例 Kafka 消费者判级 COMPLETE,以 NOTIFY 投进 session_messaging 收件箱(deferred activation、稳定 message_id);TankaServerAPI 在合适时机 pull /work/watcher/events、drain 渲染成提醒注入新回合,助理"想起来"该接着办了。push 只是信号,pull 才是真相——不丢不重。
复杂任务扇出
"调研这三个竞品,每个各出一页要点,最后给我横向对比。"
一个回合扛不动三份深度调研。助理把每个竞品委派给一个专属 flow session(create,fire-and-forget),自己留在座位上继续别的事、保持可用。每个子会话独立工作,完成时以 session_report(COMPLETION)经 session_messaging 自动回传摘要 + 产物;助理读各自 .flow/<id>/artifacts(父可读路径)汇成横向对比。要追加要求时用 send——子会话耐用、可复用。
定时主动跟进
"每周五 17:00 帮我催一下未完成的 followup。"
助理设一个 TIME_CRON reminder(经 RedBeat)。每周五到点,以 NOTIFY 经 session_messaging pull-wakeup 唤醒,它读第一方 followup 清单,对未完成项的负责人发消息催办——主动性来自时间触发,而行动仍走第一方 Action(并按需过确认)。
一次长程旅程
把六个用例串成一条跨越数天的真实时间线——同一个会话、同一个助理,记忆 + 委派 + reminder 经 session_messaging 协同。
"帮我推进 Q3 复盘"
助理调取你的长期记忆(Worklog / 画像)并跨源检索近期第一方数据(聊天/邮件/备忘),理解项目当前状态,提出行动计划并请你确认方向。
建群、约会、起草议程
确认卡逐项授权;建"Q3 复盘"群、发出周四会议邀请、把议程草稿写进备忘。用户对"建群/发邀请"选 always-allow。
盯着两件还没发生的事
设两个 reminder:一个 EVENT_EMAIL 等财务批预算,一个 EVENT_CHAT 等产品在群里确认排期。本回合结束,会话保持。
财务回信了
Kafka 消费者判级 COMPLETE,以 NOTIFY 进 session_messaging;TankaServerAPI pull-wakeup 注入下一回合,助理"想起"该接着办,起草批复回信待确认。
"顺便调研三个竞品"
委派(create)三个 flow session 并行调研,fire-and-forget。父会话继续处理别的事,保持可用。
三份调研回来了
三个子会话以 session_report 自动回传(经 session_messaging),助理读各自 .flow/<id>/artifacts,汇成横向对比、附来源引用,连同复盘进展一并交付。整段过程,用户只经历了"一次对话"。
设计原则与边界
能力越大,边界越要清楚。这些约束既是安全护栏,也是这套架构能长期可信运行的前提。
@[姓名] 格式。action_log 记录每次行动,TurnSummary 双轨备份每个回合;授权 grant 按 target/app/tool 粒度记录在会话状态里。message_id,不丢不重);push 到 TankaServerAPI 仅是 best-effort 信号,真正的真相源是 pull /work/watcher/events 的 drain,按 immediate / deferred / passive 分桶消费。旧的 event_outbox + OutboxMiddleware 注入已被取代。parent_room_id(无 dispatch-CAS / M2);INV-1:ROOT 可派生 DERIVED、DERIVED 不可再生子(防深层嵌套)。子会话耐用、可复用、不进终态;Kafka 消费者仍须单实例(内存防抖不可分布)。ref_N,绝不编造;同源去重、按出现顺序排列;原始 source artifact 阅后即焚不进 checkpoint;非 ASSISTANT 场景不挂引用链,零开销。