RequestContext 与 Streaming:把 Agent 放进真实应用
问题场景
离线 Demo 只需要固定输入,真实应用会多出请求级变量:
- 当前用户是免费版还是企业版。
- 用户语言、地区、权限不同。
- 某次请求只允许部分工具。
- 同一个 Agent 在后台任务、聊天 UI、Workflow 中被复用。
- 长回答需要边生成边显示。
这些信息不应该硬编码进 Agent,也不应该全塞进 Memory。新版 Mastra 文档主要使用 RequestContext 表示「本次请求有效」的上下文;早期资料里可能仍称为 Runtime Context。本章统一使用当前包里的 RequestContext API,同时保留术语说明,避免和长期 Memory 混淆。
RequestContext 解决什么
官方文档说明,Agents、Tools 和 Workflows 都可以接收 RequestContext。它适合传入请求级值,例如用户等级、语言、租户、功能开关、工具选择策略。
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
| 维度 | RequestContext | Memory |
|---|---|---|
| 生命周期 | 单次请求或一次运行 | 多轮对话、长期存储 |
| 典型内容 | 权限、套餐、语言、租户、请求头 | 偏好、历史问题、学习进度 |
| 来源 | 服务端中间件、前端请求、后台任务 | Agent 对话、工具结果、手动写入 |
| 是否进入模型上下文 | 取决于代码如何使用 | 通常会影响对话上下文 |
| 风险 | 误把敏感字段写进 prompt | 记忆串用户、过期信息污染回答 |
设计原则:权限和租户信息放 RequestContext;需要跨会话记住的信息才放 Memory。
在 Agent、Tool、Workflow 中读取
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 stream | textStream 和事件 chunk | 聊天、长回答、工具调用过程 |
| Workflow stream | 结构化运行事件 | 步骤状态、进度条、后台任务 |
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,还要看完整事件:
const stream = await studyAgent.stream('请搜索 Tool 资料')
for await (const event of stream.fullStream) {
if (event.type === 'tool-call') {
console.log(event)
}
}事件如何帮助调试
Mastra Streaming events 文档列出常见事件:start、text-delta、tool-call、tool-result、finish,Workflow 还会出现 step-start、step-finish 等事件。
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 + usageVibe coding 提示词
请帮我把 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-call 和 tool-result |
| token 和结束原因可见 | 等待 stream.usage、stream.finishReason |
常见错误
| 错误 | 后果 | 修复 |
|---|---|---|
| 把权限信息存进 Memory | 用户套餐变化后仍读旧信息 | 权限用 RequestContext |
| 在 prompt 里暴露敏感请求头 | 泄露风险 | 只传必要的非敏感派生值 |
只消费 textStream | 看不到工具调用和审批事件 | 调试时消费 fullStream |
| UI 把工具事件当普通文本显示 | 用户看到内部结构 | 按 event type 分别渲染 |
小练习
为 Study Agent 设计两个 RequestContext:free 和 pro。写出两者能用的工具、回答深度、RAG topK 上限和是否允许导出学习计划。先设计表格,再让 AI 生成代码。