Mio 查邮件 · 接口怎么写

SalesRoom #271 · 2026-07-30 · 不走 HTTP,共享函数层

你的理解对了一半:要有查询层,但不该是 HTTP 关键

走 HTTP 的三个问题
白绕一圈 QA run 是 worker 进程里的 asyncio.Task —— 和 DB 在同一个进程。为了调同进程的一个函数,去序列化 + 走网络栈 + 再反序列化
把安全口子重新打开 HTTP endpoint 必须从某处拿 user_id。前端那条是网关注入 header;MCP 走 HTTP 就只能自己伪造 header(丑且脆)或者加一个 user_id 参数 —— 后者正是我们一路在躲的东西
错误要翻两遍 HTTP 状态码 → 异常 → MCP 结果。每翻一次就丢一层原因,最后又变成「查询失败」

正确的分层:共享的是函数,不是 HTTP

前端 · 将来的邮件列表 UI

routers/mail.py
身份来自网关 header

Mio · MCP tool

身份来自 closure

lib/mail_query.py
纯函数 · 收 conn 和 user_id

mail_messages

磁盘正文

两条路各自解决身份,然后调同一个函数。这才是「不重复造轮子」的正确形态 —— 复用查询逻辑,不是复用传输层

而且 HTTP 那半边现在不用写 —— 前端还没有邮件列表页面。等真要做的时候再加 router,调的是同一个函数。

三个函数:收什么、回什么

函数参数返回
list_mine user_id(closure)
kind 可选 client/internal/unknown
since_days 可选
limit 默认 20
索引,不含正文
id · 标题 · 发件人 · 时间 · 类别 · 客户名 · 是否已判定
read_mine user_id(closure)
mail_id
上面那些 + 正文(截断到 ~8KB)
search_team q 关键词 / customer 客户名
limit
没有 user_id —— 本来就是全组织
list_mine + 是谁的邮箱

返回里刻意不给的两样:

不给为什么
file_path给了就等于把文件系统还给 agent。它拿 id,我们内部查路径
列表里的正文20 封正文直接撑爆上下文。大多数问题看标题+发件人就能答,要正文再单独取

⚠️ 一个卡点:search_team 现在写不了

它的闸门条件是「只查已判定为工作的」:

WHERE triage_status = 'done' AND <triage 的判定结果> IN ('client','internal')

那个「triage 的判定结果」字段还不存在。表里现在只有 rule_kind(规则层判的)和 triage_status(pending/done),没有地方放 triage 的结论

选项
triage 覆写 rule_kind省一列,但丢掉「规则层说 unknown、triage 说 client」这个信息 —— 而那恰恰是将来衡量规则层准不准的唯一依据
加一列 triage_kind两个判断分开存。倾向这个,但这属于 triage 的设计,不该在这一步拍

这反过来印证了顺序:search_team 不是「先做也行」,是物理上依赖 triage 先定字段

所以现在做什么

做什么依赖
1定时取数 —— 半天的活,做完邮件就开始攒无。现在就能做
2triage —— 判定 + 分类 + 定 triage_kind 字段要有邮件样本
3mail_query.py + MCP(list_mine / read_mine)只依赖已有字段,其实随时能写
4search_team必须等 ②

③ 技术上不卡,但现在写完 Mio 只会一直说「你没有邮件」 —— 你那 12 封全是通知,规则层全丢了,本地是空的。

Generated as a visual answer · open in browser