Skip to content

RequestContext 与 Streaming:把 Agent 放进真实应用

问题场景

离线 Demo 只需要固定输入,真实应用会多出请求级变量:

  • 当前用户是免费版还是企业版。
  • 用户语言、地区、权限不同。
  • 某次请求只允许部分工具。
  • 同一个 Agent 在后台任务、聊天 UI、Workflow 中被复用。
  • 长回答需要边生成边显示。

这些信息不应该硬编码进 Agent,也不应该全塞进 Memory。新版 Mastra 文档主要使用 RequestContext 表示「本次请求有效」的上下文;早期资料里可能仍称为 Runtime Context。本章统一使用当前包里的 RequestContext API,同时保留术语说明,避免和长期 Memory 混淆。

RequestContext 解决什么

官方文档说明,Agents、Tools 和 Workflows 都可以接收 RequestContext。它适合传入请求级值,例如用户等级、语言、租户、功能开关、工具选择策略。

ts
import { RequestContext } from '@mastra/core/request-context'

type StudyRequestContext = {
  'user-tier': 'free' | 'pro'
  language: 'zh-CN' | 'en-US'
}

const requestContext = new RequestContext<StudyRequestContext>()
requestContext.set('user-tier', 'pro')
requestContext.set('language', 'zh-CN')

await studyAgent.generate('请给我学习计划', {
  requestContext,
})

官方依据

Mastra Request Context 文档说明,请求级值可以通过 requestContext 传给 Agent、Network、Workflow 或 Tool,并可在运行过程中被底层 primitive 读取。

RequestContext 不是 Memory

维度RequestContextMemory
生命周期单次请求或一次运行多轮对话、长期存储
典型内容权限、套餐、语言、租户、请求头偏好、历史问题、学习进度
来源服务端中间件、前端请求、后台任务Agent 对话、工具结果、手动写入
是否进入模型上下文取决于代码如何使用通常会影响对话上下文
风险误把敏感字段写进 prompt记忆串用户、过期信息污染回答

设计原则:权限和租户信息放 RequestContext;需要跨会话记住的信息才放 Memory。

在 Agent、Tool、Workflow 中读取

ts
const studyAgent = new Agent({
  id: 'study-agent',
  instructions: ({ requestContext }) => {
    const tier = requestContext.get('user-tier')

    return tier === 'pro'
      ? '回答可以包含扩展阅读和进阶练习。'
      : '回答聚焦免费课程资料,不推荐付费资源。'
  },
  tools: ({ requestContext }) => {
    const tier = requestContext.get('user-tier')
    return tier === 'pro'
      ? { searchCourseTool, createStudyPlanTool, generateExerciseTool }
      : { searchCourseTool }
  },
})

Workflow step 和 Tool 的 execute 也能读取 requestContext。这让同一套代码可以按租户、权限或语言切换行为,而不需要复制多个 Agent。

Streaming 解决什么

.generate() 适合等待完整结果;.stream() 适合聊天 UI、长文本、工具调用进度和 Workflow 状态展示。

官方 Streaming 文档区分两类流:

类型返回内容适合用途
Agent streamtextStream 和事件 chunk聊天、长回答、工具调用过程
Workflow stream结构化运行事件步骤状态、进度条、后台任务
ts
const stream = await studyAgent.stream('请解释 Agent Loop')

for await (const chunk of stream.textStream) {
  process.stdout.write(chunk)
}

const fullText = await stream.text
const usage = await stream.usage

如果要调试工具调用,不只看 textStream,还要看完整事件:

ts
const stream = await studyAgent.stream('请搜索 Tool 资料')

for await (const event of stream.fullStream) {
  if (event.type === 'tool-call') {
    console.log(event)
  }
}

事件如何帮助调试

Mastra Streaming events 文档列出常见事件:starttext-deltatool-calltool-resultfinish,Workflow 还会出现 step-startstep-finish 等事件。

mermaid
sequenceDiagram
  participant UI as Chat UI
  participant Agent as Study Agent
  participant Tool as searchCourseTool
  participant Model as LLM

  UI->>Agent: stream(prompt, requestContext)
  Agent-->>UI: start
  Agent->>Model: 生成下一步
  Model-->>Agent: tool-call
  Agent-->>UI: tool-call event
  Agent->>Tool: execute()
  Tool-->>Agent: hits
  Agent-->>UI: tool-result event
  Agent->>Model: 工具结果 + 上下文
  Model-->>Agent: text-delta...
  Agent-->>UI: finish + usage

Vibe coding 提示词

text
请帮我把 Study Agent 改造成支持 RequestContext 的版本。
要求:
- 定义 StudyRequestContext 类型。
- 读取 user-tier 和 language。
- 不把 userId、apiKey、tenant secret 写入 prompt。
- 免费用户只暴露 searchCourseTool。
- Pro 用户可以使用计划和练习工具。
- 给出一段 stream 调用示例,用 fullStream 打印 tool-call 和 tool-result。

验证方式

验证项方法
上下文不会跨请求污染连续用 free/pro 两个 requestContext 调用
工具选择按权限变化检查 tools 函数返回值或 Studio 中可用工具
语言策略生效同一 prompt 切换 language
流式事件完整打印 fullStream,确认有 tool-calltool-result
token 和结束原因可见等待 stream.usagestream.finishReason

常见错误

错误后果修复
把权限信息存进 Memory用户套餐变化后仍读旧信息权限用 RequestContext
在 prompt 里暴露敏感请求头泄露风险只传必要的非敏感派生值
只消费 textStream看不到工具调用和审批事件调试时消费 fullStream
UI 把工具事件当普通文本显示用户看到内部结构按 event type 分别渲染

小练习

为 Study Agent 设计两个 RequestContext:freepro。写出两者能用的工具、回答深度、RAG topK 上限和是否允许导出学习计划。先设计表格,再让 AI 生成代码。