Session
AgentController 功能目前处于 beta 阶段。在正式脱离 beta 状态之前,次要版本中可能会包含破坏性变更。
Session 是面向单个资源和可选作用域的隔离运行时。它负责自己的事件总线、线程绑定、状态、模式和模型选择、运行控制、审批、暂停、后续消息以及显示状态。AgentController 提供共享的 Agent、配置、存储、Workspace 和服务。
请通过 controller.createSession() 创建 Session。直接构造和控制器接线方法并不是应用 API。
有关概念介绍,请参阅 AgentController 概述。
用法示例用法示例的直接链接
以下示例使用受支持的控制器到 Session 流程。
await controller.init()
const session = await controller.createSession({ resourceId: 'project-42' })
const unsubscribe = session.subscribe(event => {
if (event.type === 'display_state_changed') {
render(event.displayState)
}
})
await session.sendMessage({ content: 'Review the current project.' })
unsubscribe()
属性属性的直接链接
Session 按子对象组织,每个子对象负责一种对话级状态。
identity:
thread:
mode:
model:
om:
permissions:
subagents:
run:
stream:
suspensions:
followUps:
approval:
displayState:
state:
browser:
方法方法的直接链接
身份和事件身份和事件的直接链接
getTags()gettags的直接链接
返回创建 Session 时提供的标签副本。
const tags = session.getTags()
返回:Record<string, string>
subscribe(listener)subscribelistener的直接链接
订阅此 Session 的隔离事件总线。该方法返回一个取消订阅函数。
const unsubscribe = session.subscribe(event => {
console.log(event.type)
})
unsubscribe()
返回:() => void
消息和运行控制消息和运行控制的直接链接
sendMessage({ content, files?, requestContext? })sendmessage-content-files-requestcontext-的直接链接
发送用户消息。如果没有活动线程,Session 会先创建一个线程。
await session.sendMessage({
content: 'Summarize this file.',
files: [{ data: fileContents, mediaType: 'text/plain', filename: 'notes.txt' }],
})
steer({ content, requestContext? })steer-content-requestcontext-的直接链接
将引导内容排入活动运行。
await session.steer({ content: 'Focus on the failing tests.' })
followUp({ content, requestContext? })followup-content-requestcontext-的直接链接
运行处于活动状态时将后续消息排入队列,空闲时则立即发送。
await session.followUp({ content: 'Then propose a fix.' })
getCurrentRunId()getcurrentrunid的直接链接
返回活动流的运行标识符、受跟踪的运行标识符,空闲时返回 null。
const runId = session.getCurrentRunId()
返回:string | null
abort()abort的直接链接
中止活动运行并清除待处理的暂停显示状态。
session.abort()
WorkspaceWorkspace的直接链接
getWorkspace()getworkspace的直接链接
返回为此 Session 解析的 Workspace。此方法会保留 Session 级覆盖项和从 Session 作用域中选择的 Workspace。
const workspace = session.getWorkspace()
const skill = await workspace.skills?.get('code-review')
返回:Workspace
Session 授权Session 授权的直接链接
Session 作用域的授权会自动批准 Tool,无需提示。这些授权是临时的:Session 重启时会重置,且永远不会持久化。
grantCategory(category)grantcategorycategory的直接链接
为当前 Session 授予一个 Tool 类别。此类别中的 Tool 将被自动批准。
session.grantCategory('edit')
grantTool(toolName)granttooltoolname的直接链接
为当前 Session 授予特定 Tool。
session.grantTool('mastra_workspace_execute_command')
getGrants()getgrants的直接链接
返回当前已授权的类别和 Tool。
const grants = session.getGrants()
// { categories: string[], tools: string[] }
hasCategoryGrant(category)hascategorygrantcategory的直接链接
返回某个类别是否拥有内存中的 Session 授权。
const allowed = session.hasCategoryGrant('edit')
返回:boolean
hasToolGrant(toolName)hastoolgranttoolname的直接链接
返回某个 Tool 是否拥有内存中的 Session 授权。
const allowed = session.hasToolGrant('write_file')
返回:boolean
Tool 审批Tool 审批的直接链接
resolveToolApproval(toolName)resolvetoolapprovaltoolname的直接链接
应用显式 Tool 规则、Session 授权和类别规则后,返回最终策略。
const policy = session.resolveToolApproval('execute_command')
返回:PermissionPolicy
respondToToolApproval({ decision, toolCallId?, requestContext?, declineContext? })respondtotoolapproval-decision-toolcallid-requestcontext-declinecontext-的直接链接
响应由 tool_approval_required 事件触发的待处理 Tool 审批请求。传入 always_allow_category 还可在 Session 剩余生命周期内授权该 Tool 的整个类别。
session.respondToToolApproval({ decision: 'approve' })
session.respondToToolApproval({ decision: 'decline' })
session.respondToToolApproval({ decision: 'always_allow_category' })
respondToToolSuspension({ resumeData, toolCallId?, requestContext? })respondtotoolsuspension-resumedata-toolcallid-requestcontext-的直接链接
使用应用提供的数据恢复已暂停的 Tool。有多个 Tool 调用处于暂停状态时,请提供 toolCallId。
await session.respondToToolSuspension({
toolCallId: event.toolCallId,
resumeData: ['src'],
})
对于 submit_plan,请传入 { action: 'approved' } 或 { action: 'rejected', feedback }。在 Tool 恢复之前,审批可能会切换到 transitionsTo 配置的模式。
Token 用量Token 用量的直接链接
getTokenUsage()gettokenusage的直接链接
返回活动线程持续累计的 token 用量副本。
const usage = session.getTokenUsage()
// { promptTokens, completionTokens, totalTokens, ... }
身份身份的直接链接
session.identity 负责对话的稳定标识符:资源 ID、Session id 和 ownerId。id 和 ownerId 在 Session 的整个生命周期中保持稳定,切换资源 ID 时不会改变。它们对应存储中 SessionRecord 的 id 和 ownerId 字段。
session.identity.getId()sessionidentitygetid的直接链接
返回稳定的 Session 标识符。
const sessionId = session.identity.getId()
session.identity.getOwnerId()sessionidentitygetownerid的直接链接
返回 Session 稳定的所有者标识符。
const ownerId = session.identity.getOwnerId()
session.identity.getResourceId()sessionidentitygetresourceid的直接链接
返回当前资源 ID。
const resourceId = session.identity.getResourceId()
session.identity.getDefaultResourceId()sessionidentitygetdefaultresourceid的直接链接
返回创建 Session 时使用的资源 ID。
const defaultResourceId = session.identity.getDefaultResourceId()
要更改资源 ID,请使用 controller.setResourceId(),它还会清除活动线程。资源切换不会影响 Session 的 id 和 ownerId。
线程线程的直接链接
session.thread 负责活动线程绑定和资源作用域的线程操作。配置存储后,即使重新创建控制器,已存储的线程和消息也可保留;实时 Session 及其事件总线则不会保留。
session.thread.create({ title?, id? })sessionthreadcreate-title-id-的直接链接
创建一个线程,将 Session 绑定到该线程,并打开其事件流。
const thread = await session.thread.create({
id: 'thread-7',
title: 'Investigate login failure',
})
返回:Promise<AgentControllerThread>
session.thread.rename({ title })sessionthreadrename-title-的直接链接
重命名活动的已存储线程。
await session.thread.rename({ title: 'Fix login failure' })
session.thread.clone({ sourceThreadId?, title?, resourceId? })sessionthreadclone-sourcethreadid-title-resourceid-的直接链接
克隆一个自有线程及其消息,然后将 Session 绑定到克隆线程。
const clone = await session.thread.clone({
sourceThreadId: 'thread-7',
title: 'Alternative approach',
})
返回:Promise<AgentControllerThread>
session.thread.switch({ threadId, emitEvent? })sessionthreadswitch-threadid-emitevent-的直接链接
切换到一个自有的已存储线程,并填充其模式、模型和观测记忆设置。
await session.thread.switch({ threadId: 'thread-8' })
session.thread.delete({ threadId })sessionthreaddelete-threadid-的直接链接
删除一个自有线程。删除活动线程还会清除当前绑定。
await session.thread.delete({ threadId: 'thread-8' })
session.thread.getId()sessionthreadgetid的直接链接
返回活动线程 ID;没有绑定线程时返回 null。
const threadId = session.thread.getId()
session.thread.list(options?)sessionthreadlistoptions的直接链接
列出存储中的线程。默认仅返回当前资源的线程,并隐藏临时的分叉子 Agent 线程。
const threads = await session.thread.list()
const allThreads = await session.thread.list({ allResources: true })
const everything = await session.thread.list({ includeForkedSubagents: true })
session.thread.getById({ threadId })sessionthreadgetbyid-threadid-的直接链接
按 ID 返回单个线程;线程不存在时返回 null。
const thread = await session.thread.getById({ threadId: 'thread-abc123' })
session.thread.listActiveMessages(options?)sessionthreadlistactivemessagesoptions的直接链接
检索活动线程的消息。没有绑定线程时返回空数组。
const messages = await session.thread.listActiveMessages({ limit: 50 })
session.thread.listMessages({ threadId, limit? })sessionthreadlistmessages-threadid-limit-的直接链接
检索特定线程的消息。
const messages = await session.thread.listMessages({ threadId: 'thread-abc123' })
消息读取方法 listActiveMessages、listMessages 和 firstUserMessage 返回 MastraDBMessage 对象,firstUserMessages 则返回以线程 ID 为键的 Map<string, MastraDBMessage>。每条消息都有 role、id、createdAt,以及包含 content.format 和 content.parts 数组的 content 对象。请从 content.parts 读取文本、推理、Tool 调用和附件。系统提醒和通知等信号会作为 role: 'signal' 的独立消息返回。
session.thread.firstUserMessage({ threadId })sessionthreadfirstusermessage-threadid-的直接链接
检索线程的第一条用户消息;没有时返回 null。
const firstMsg = await session.thread.firstUserMessage({
threadId: 'thread-abc123',
})
session.thread.firstUserMessages({ threadIds })sessionthreadfirstusermessages-threadids-的直接链接
一次检索多个线程的第一条用户消息,并以 map 形式返回。
const firstByThread = await session.thread.firstUserMessages({
threadIds: ['thread-a', 'thread-b'],
})
session.thread.getSetting({ key })sessionthreadgetsetting-key-的直接链接
从活动线程元数据中读取设置。
const value = await session.thread.getSetting({ key: 'omThreshold' })
session.thread.setSetting({ key, value })sessionthreadsetsetting-key-value-的直接链接
向活动线程元数据写入设置。
await session.thread.setSetting({ key: 'omThreshold', value: 0.8 })
session.thread.deleteSetting({ key })sessionthreaddeletesetting-key-的直接链接
从活动线程元数据中移除设置。
await session.thread.deleteSetting({ key: 'omThreshold' })
模式模式的直接链接
session.mode 负责活动模式选择。
session.mode.get()sessionmodeget的直接链接
返回活动模式 ID。
const modeId = session.mode.get()
session.mode.resolve()sessionmoderesolve的直接链接
返回根据控制器已配置模式解析出的完整 AgentControllerMode 对象。
const mode = session.mode.resolve()
session.mode.switch({ modeId })sessionmodeswitch-modeid-的直接链接
切换到另一个模式。Session 会先保存传出模式的模型,再将新模式持久化到活动线程。随后恢复传入模式已选择的模型或默认模型。Session 会立即发出 mode_changed,并在模型解析后发出 model_changed。
await session.mode.switch({ modeId: 'build' })
模型模型的直接链接
session.model 负责活动模型选择,包括按模式保存的模型记忆。
session.model.get()sessionmodelget的直接链接
返回活动模型 ID。
const modelId = session.model.get()
session.model.displayName()sessionmodeldisplayname的直接链接
返回活动模型 ID 的最后一段作为简短显示名称。未选择模型时返回 'unknown'。
const name = session.model.displayName()
session.model.hasSelection()sessionmodelhasselection的直接链接
检查当前是否已选择模型。
if (session.model.hasSelection()) {
// Ready to send messages
}
session.model.switch({ modelId, scope?, modeId? })sessionmodelswitch-modelid-scope-modeid-的直接链接
切换活动模型。当 scope 为 'thread'(默认值)时,模型 ID 会作为该模式的模型持久化,以便切换回来时恢复。此方法会向控制器的 modelUseCountTracker 报告选择,并发出 model_changed 事件。
// Set for the current session only
await session.model.switch({
modelId: 'anthropic/claude-sonnet-4-6',
scope: 'global',
})
// Persist to the current thread (default)
await session.model.switch({ modelId: 'anthropic/claude-sonnet-4-6' })
观测记忆观测记忆的直接链接
观测记忆模型的选择按角色分组在 session.om.observer 和 session.om.reflector 下。两个角色公开相同的方法。读取时若 Session 状态中已设置值则返回该值,否则回退到控制器的 omConfig 默认值。
session.om.observer.modelId() / session.om.reflector.modelId()sessionomobservermodelid--sessionomreflectormodelid的直接链接
返回该角色的模型 ID;如果 Session 状态和 omConfig 都未提供,则返回 undefined。
const observer = session.om.observer.modelId()
const reflector = session.om.reflector.modelId()
session.om.observer.threshold() / session.om.reflector.threshold()sessionomobserverthreshold--sessionomreflectorthreshold的直接链接
返回该角色以 token 为单位的阈值(观察器为观察阈值,反思器为反思阈值);未设置时返回 undefined。
const observationThreshold = session.om.observer.threshold()
const reflectionThreshold = session.om.reflector.threshold()
session.om.observer.switchModel({ modelId }) / session.om.reflector.switchModel({ modelId })sessionomobserverswitchmodel-modelid---sessionomreflectorswitchmodel-modelid-的直接链接
切换该角色的模型。此方法会将设置持久化到线程元数据,并发出 om_model_changed 事件。
await session.om.observer.switchModel({
modelId: 'anthropic/claude-haiku-4-5',
})
await session.om.reflector.switchModel({
modelId: 'anthropic/claude-haiku-4-5',
})
session.om.observer.resolvedModel() / session.om.reflector.resolvedModel()sessionomobserverresolvedmodel--sessionomreflectorresolvedmodel的直接链接
通过已配置的模型网关将该角色的模型 ID 解析为模型实例;未设置模型 ID 或未配置解析器时返回 undefined。
const observerModel = session.om.observer.resolvedModel()
const reflectorModel = session.om.reflector.resolvedModel()
权限权限的直接链接
session.permissions 负责 session.state 中表示的 Tool 审批策略,即解析审批时查询的按类别和按 Tool 规则。这些规则不同于 Session 授权中记录的内存授权。授权会随实时 Session 重置。除非宿主恢复对应的 Session 状态,否则权限规则不会持久保存。
session.permissions.getRules()sessionpermissionsgetrules的直接链接
返回当前权限规则;未设置时返回空规则({ categories: {}, tools: {} })。
const rules = session.permissions.getRules()
// { categories: { execute: 'ask' }, tools: { dangerous_tool: 'deny' } }
session.permissions.setForCategory({ category, policy })sessionpermissionssetforcategory-category-policy-的直接链接
为 Tool 类别设置审批策略('allow' | 'ask' | 'deny')。更改持久化到 Session 状态后,Promise 才会 resolve。
await session.permissions.setForCategory({ category: 'execute', policy: 'ask' })
session.permissions.setForTool({ toolName, policy })sessionpermissionssetfortool-toolname-policy-的直接链接
为特定 Tool 设置审批策略。按 Tool 策略优先于类别策略。持久化后,Promise 才会 resolve。
await session.permissions.setForTool({ toolName: 'dangerous_tool', policy: 'deny' })
子 Agent子 Agent的直接链接
session.subagents 负责子 Agent 配置。目前,它通过 session.subagents.model 公开子 Agent 模型选择。
session.subagents.model.get({ agentType? })sessionsubagentsmodelget-agenttype-的直接链接
返回子 Agent 模型 ID。提供 agentType 时优先使用对应值,其次使用全局子 Agent 模型;两者均未设置时返回 null。
const modelId = session.subagents.model.get({ agentType: 'explore' })
session.subagents.model.set({ modelId, agentType? })sessionsubagentsmodelset-modelid-agenttype-的直接链接
设置子 Agent 模型 ID。传入 agentType 可设置按类型覆盖项,省略则设置全局默认值。此方法会持久化到线程设置,并发出 subagent_model_changed 事件。
// Set the global subagent model
await session.subagents.model.set({ modelId: 'anthropic/claude-sonnet-4-6' })
// Set a per-type override
await session.subagents.model.set({
modelId: 'anthropic/claude-haiku-4-5',
agentType: 'explore',
})
运行运行的直接链接
session.run 负责进行中运行的运行和 Trace 身份及中止状态。
session.run.getRunId() / getTraceId()sessionrungetrunid--gettraceid的直接链接
返回当前运行已存储的运行 ID 和 Trace ID;空闲时返回 null。
const runId = session.run.getRunId()
const traceId = session.run.getTraceId()
session.run.isRunning()sessionrunisrunning的直接链接
返回当前是否有运行正在进行。
if (session.run.isRunning()) {
// A run is active
}
流流的直接链接
session.stream 负责 Agent 线程流的实时订阅及其去重键。
session.stream.activeRunId()sessionstreamactiverunid的直接链接
返回实时流上的活动运行 ID;未打开流时返回 null。
const runId = session.stream.activeRunId()
session.stream.isActive()sessionstreamisactive的直接链接
返回流当前是否有活动运行。
if (session.stream.isActive()) {
// The current thread's stream is producing output
}
暂停暂停的直接链接
session.suspensions 负责等待恢复的已停放交互式 Tool 调用(例如 ask_user 和 request_access)。
session.suspensions.hasPending()sessionsuspensionshaspending的直接链接
返回当前是否有任何 Tool 处于暂停状态。
if (session.suspensions.hasPending()) {
// At least one interactive tool is waiting for a response
}
session.suspensions.has({ toolCallId })sessionsuspensionshas-toolcallid-的直接链接
返回特定 Tool 调用是否已暂停。
const waiting = session.suspensions.has({ toolCallId: event.toolCallId })
使用 session.respondToToolSuspension() 恢复已暂停的 Tool。
后续消息后续消息的直接链接
session.followUps 负责运行进行期间提交的消息 FIFO 队列。
session.followUps.count()sessionfollowupscount的直接链接
返回已排队的后续消息数量。
const queued = session.followUps.count()
session.followUps.isEmpty()sessionfollowupsisempty的直接链接
返回后续消息队列是否为空。
if (!session.followUps.isEmpty()) {
// Messages are waiting to be processed
}
审批审批的直接链接
session.approval 负责待处理的 Tool 审批关卡。
session.approval.isArmed()sessionapprovalisarmed的直接链接
返回当前是否有 Tool 正在等待审批决定。
if (session.approval.isArmed()) {
// Show the approval prompt
}
使用 session.respondToToolApproval() 响应。
显示状态显示状态的直接链接
session.displayState 负责 UI 用于渲染的规范 AgentControllerDisplayState 快照,以及使其与每个 Session 事件保持同步的 reducer。
session.displayState.get()sessiondisplaystateget的直接链接
返回用于 UI 渲染的当前 AgentControllerDisplayState 快照。
const displayState = session.displayState.get()
session.displayState.restoreTasks(tasks)sessiondisplaystaterestoretaskstasks的直接链接
在 UI 重放持久化的任务 Tool 历史记录后,恢复快照中的任务部分。这是对快照的纯更新,不会发出事件,因此调用后请显式重新渲染。
session.displayState.restoreTasks(replayedTasks)
每个事件之后,Session 都会发出包含最新快照的 display_state_changed。可使用 session.subscribe() 订阅,也可从 session.displayState.get() 读取当前值。
状态状态的直接链接
session.state 负责对话中经过 schema 验证的 AgentController 状态。它保存当前快照,并使用传给 AgentController 的 stateSchema 验证更新。更新会被串行处理,每次更改都会发出 state_changed 事件。
session.state.get()sessionstateget的直接链接
返回当前状态快照的只读副本。
const state = session.state.get()
session.state.set(updates)sessionstatesetupdates的直接链接
将部分更新合并到状态中。更新会排队,使并发调用按顺序应用;更新经过 schema 验证后,会发出包含已更改键的 state_changed。
await session.state.set({ yolo: true })
session.state.update(updater)sessionstateupdateupdater的直接链接
针对当前快照运行 updater,并在写入队列中以原子方式应用其结果。对于必须读取最新状态的“读取-修改-写入”更改,请使用此方法。updater 返回要合并的 updates、要发出的可选 events,以及 update() 最终 resolve 的 result 值。
const added = await session.state.update(current => ({
updates: { count: (current.count ?? 0) + 1 },
result: (current.count ?? 0) + 1,
}))
持久化边界持久化边界的直接链接
Session 是实时运行时对象。它的事件总线、任意 session.state、权限规则、权限授权、待处理审批、暂停、后续消息、运行状态和流状态不会在重新创建控制器或进程后自动保留。重新创建 Session 时,宿主必须恢复所需的这些状态。
配置存储后,线程、消息和 token 用量会持久化。线程设置会恢复模式和模型选择,还可恢复观测记忆设置和子 Agent 模型选择,包括按 Agent 类型的覆盖项。聊天频道可以映射回已存储线程,但 AgentControllerChannels 保存的频道到 Session 映射和自动审批状态仍只存在于内存中。