Session 来源与类型
如何为你的 Session 选择分类与角色,以及它们决定什么
每个 Session 都有一个来源(origin),由两个字段组成:category 和 type。它们回答两个不同的问题,你需要分别决定。
category 是分类,只有 chat 和 work 两个值。它决定会话存在哪个物理分区,也决定这个会话能不能派发工作。type 是角色,说明这条会话具体是什么。分类回答「它在哪一层」,角色回答「它是什么」。
该用哪个分类
问自己一件事:这条会话是用来对话,还是用来干活。
| 你要做的事 | 分类 | 角色 |
|---|---|---|
| 和用户持续对话(你的产品主界面) | chat | agent |
| 接入外部聊天渠道(Telegram、飞书等) | chat | channel |
| 群聊里的成员会话 | chat | group |
| 浏览器扩展里的问答 | chat | chrome |
| 执行一件明确的工作 | work | work |
| 由任务调度触发的一次执行 | work | task |
不传 origin 时默认是 { category: "work", type: "work" },也就是一条普通工作会话。
分类决定的两件事
物理分区。 会话落在 sessions/<category>/<session_id>/。分类只有两个,所以一个 Agent 的会话目录最多两层。同一个 session_id 可以分别存在于 chat 和 work 下——它们互不冲突,因为身份由分类和 ID 共同组成。
能不能派发工作。 chat 类的会话可以开启、检查、答复、停止其他会话,也可以归档。work 类的会话专注做被派发的那件事,不再递归派发。归档只有 work 类能做。
角色不参与分区的形成,它只影响具体的行为分支,例如外部聊天要选平台 prompt、群聊成员要校验归属。
开一条对话会话
const session = await agent.sessions.create({
origin: { category: "chat", type: "agent" },
workspace,
});派一件事,让它干活
const work = await agent.sessions.create({
origin: { category: "work", type: "work" },
workspace,
});
const turn = await work.prompt({ query: "把这份报告整理成表格" });
await turn.finished;按分类与角色查会话
list 的第一个维度是分类;分类不足以区分角色时再加角色。
// 某个分类下的全部会话
const conversations = await agent.sessions.list({ category: "chat" });
// 只看 Agent 主会话
const main = await agent.sessions.list({
category: "chat",
origin_type: "agent",
});恢复一个已有会话时传的也是分类:
const session = await agent.sessions.get(session_id, "chat", { workspace });自定义角色
已知的六个角色覆盖了常见场景。如果你的产品有自己的会话语义,可以声明自定义角色,但必须同时给出分类,否则创建会直接失败:
const session = await agent.sessions.create({
origin: {
category: "work",
type: "automation/daily",
schedule_id: "daily-report",
},
});分类必须在 chat 和 work 之间选一个,因为它是唯一决定分区与派发能力的字段。角色名可以是任意非空字符串,两者之外的字段会随来源一起持久化,由你自己解释。
这个约束是有意的:新增一个角色是零成本的,新增一个分区需要显式表达,不会因为写错一个字符串就静默落到别的目录里。