Announcing Genkit Middleware: Intercept, extend, and harden your agentic apps
TL;DR · AI 摘要
Genkit middleware provides composable hooks to intercept, extend, and harden agentic applications with pre-built solutions for retries, fallbacks, tool approval, skills, and filesystem access.
核心要点
- 支持重试、回退、工具审批等预置中间件
- 提供文件系统访问和技能注入功能
- 可自定义中间件扩展应用能力
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- Genkit Middleware
- 核心功能
- 拦截生成调用
金句 / Highlights
值得收藏与分享的关键句。
Genkit middleware provides composable hooks that intercept generation calls, including the tool execution loop, and inject custom behaviors.
Pre-built middleware includes retry, fallback, tool approval, skills, and filesystem access features.
Custom middleware can be created to extend application capabilities for specific use cases.
宣布推出 Genkit 中间件:拦截、扩展和强化你的代理型应用
URL 来源: https://developers.googleblog.com/announcing-genkit-middleware-intercept-extend-and-harden-your-agentic-apps/
发布日期: 2026-05-14
Genkit 是一个开源框架,用于构建全栈、AI 驱动且代理型的应用程序,支持任何平台,并兼容 TypeScript、Go、Dart 和 Python。构建生产就绪的代理型应用程序和 AI 功能需要的不仅仅是强大的模型和精心设计的提示词。你可能还需要重试和回退机制以确保最大可靠性,在破坏性工具调用前进行人工审批,以及在每一层实现可观测性。
Genkit 通过 中间件 解决了这些问题:可组合的钩子可以拦截生成调用(包括工具执行循环),并注入自定义行为。目前,中间件系统已在 TypeScript、Go 和 Dart 中可用,Python 支持即将推出。
**Genkit 中间件的工作原理**
Genkit 中的每个 generate() 调用都会运行一个 工具循环:模型生成输出,请求的工具执行,结果反馈到新的模型调用中,直到模型完成为止,循环重复。中间件钩子附加在该循环的三个层级上:
| 钩子 | 运行时间 | 典型用途 | | --- | --- | --- | | Generate | 每次工具循环迭代运行一次 | 上下文注入、消息重写、对话级逻辑 | | Model | 每次模型 API 调用运行一次 | 重试、回退、缓存、延迟记录 | | Tool | 每次工具执行运行一次 | 人工介入、沙盒化、工具级日志 |
**预建中间件**
Genkit 提供了几种针对常见用例的预建中间件解决方案。以下是当前可用的内容:
**1. 重试**
当模型 API 调用因临时错误(如 RESOURCE_EXHAUSTED, UNAVAILABLE 等)失败时,使用带有抖动的指数退避自动重试。仅重试模型调用,周围的工具循环不会重新播放。
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-flash-latest"),
ai.WithPrompt("Summarize the quarterly earnings report."),
ai.WithUse(&middleware.Retry{
MaxRetries: 3,
InitialDelayMs: 1000,
BackoffFactor: 2,
}),
)Go
已复制
**2. 回退**
当主模型在指定的一组错误代码上失败时切换到备用模型。当主模型超出配额时,这非常有用,可以回退到完全不同的提供商。
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-flash-latest"),
ai.WithPrompt("Analyze this complex document..."),
ai.WithUse(&middleware.Fallback{
Models: []ai.ModelRef{
anthropic.ModelRef("claude-sonnet-4-6", nil), // 回退到 Claude
},
Statuses: []core.StatusName{core.RESOURCE_EXHAUSTED},
}),
)Go
已复制
**3. 工具审批**
将工具执行限制为允许列表。不在列表中的任何工具都会触发中断,从而在操作继续之前启用人工确认。
resp, _ := genkit.Generate(ctx, g,
ai.WithPrompt("Delete the temp files"),
ai.WithTools(deleteFilesTool),
ai.WithUse(&middleware.ToolApproval{
AllowedTools: []string{}, // 空 = 每个工具调用都会中断
}),
)
if len(resp.Interrupts()) > 0 {
interrupt := resp.Interrupts()[0]
// 提示用户进行审批,然后使用审批标志恢复。
approved, _ := deleteFilesTool.RestartWith(interrupt,
ai.WithResumedMetadata[DeleteInput](map[string]any{"toolApproved": true}),
)
resp, err := genkit.Generate(ctx, g,
ai.WithMessages(resp.History()...),
ai.WithTools(deleteFilesTool),
ai.WithToolRestarts(approved),
ai.WithUse(&middleware.ToolApproval{}),
)
fmt.Println(resp.Text())
}Go
已复制
**4. 技能**
扫描目录中的 SKILL.md 文件,并将其内容注入系统提示中。还暴露了一个 use_skill 工具,以便模型按需加载特定技能。
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("How do I deploy this service?"),
ai.WithUse(&middleware.Skills{SkillPaths: []string{"./skills"}}),
)Go
已复制
**5. 文件系统**
通过注入工具(如 list_files, read_file, 启用写入时的 write_file 和 edit_file),为模型提供对本地文件系统的范围访问权限。路径安全性得到强制执行,因此模型永远无法逃离根目录。
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("Create a hello world program in the workspace"),
ai.WithUse(&middleware.Filesystem{
RootDir: "./workspace",
AllowWriteAccess: true,
}),
)Go
已复制
**构建自定义中间件**
预建中间件涵盖了常见的场景,但该系统的真正强大之处在于编写你自己的中间件。想象一下,你在构建一个代理型客户服务应用,并需要确保模型从不提及竞争对手的产品或内部定价数据。与其在每个提示中编码这些规则,你可以通过中间件确定性地强制执行它们。
所有语言中的自定义中间件都遵循一个简单的契约:提供一个名称和一个返回所需钩子的工厂函数。每次调用 generate() 时都会调用该工厂函数,而你只需实现所需的钩子即可。
以下是一个完整的自定义内容过滤器,代码量约为 20 行:
// ContentFilter 拒绝包含任何禁止术语的模型响应。
type ContentFilter struct {
ForbiddenTerms []string `json:"forbiddenTerms"`
}
func (ContentFilter) Name() string { return "app/contentFilter" }func (f ContentFilter) New(ctx context.Context) (*ai.Hooks, error) {
return &ai.Hooks{
WrapModel: func(ctx context.Context, p *ai.ModelParams, next ai.ModelNext) (*ai.ModelResponse, error) {
resp, err := next(ctx, p)
if err != nil {
return nil, err
}
text := strings.ToLower(resp.Text())
for _, term := range f.ForbiddenTerms {
if strings.Contains(text, strings.ToLower(term)) {
return nil, fmt.Errorf("content filter: response contains %q", term)
}
}
return resp, nil
},
}, nil
}Go
Copied
你甚至可以组合和堆叠不同的中间件解决方案。中间件堆栈从左到右执行,第一个列出的中间件是外层包装器,依此类推:
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-flash-latest"),
ai.WithPrompt("What CRM should our customer use?"),
ai.WithUse(
&middleware.Retry{MaxRetries: 3}, // 外层:重试内层堆栈
&ContentFilter{ // 内层:验证模型输出
ForbiddenTerms: []string{"CompetitorCRM", "RivalCo", "internal price"},
},
),
)Go
Copied
这里 Retry 包裹了 ContentFilter,而 ContentFilter 又包裹了模型调用。顺序很重要,Genkit 明确了这一点。
如果你认为自己构建的中间件对其他开发者有价值,可以将其发布为一个包,供其他人使用!
**开发者 UI 体验**
你可以使用 Genkit 开发者 UI 来检查、测试和调试你的应用程序,包括中间件的执行。当你注册中间件时,它会在开发人员 UI 中可见:你可以检查其配置,跟踪每个钩子层的执行,并测试不同的组合。
**开始使用**
我们对 Genkit 中间件为你的应用解锁的能力感到兴奋,并期待看到你为解决具体用例而构建的自定义中间件。查看 中间件文档 以深入了解,或者如果你是框架新手,可以开始使用 Genkit。
有新的预构建中间件的想法吗?提交问题。我们很乐意了解什么可以改善你的开发体验!
快乐编码! 🚀
[](https://developers.googleblog.com/announcing-genkit-middleware-intercept-extend-and-harden-your-agentic-apps/) Previous
Next
[](https://developers.googleblog.com/build-long-running-ai-agents-that-pause-resume-and-never-lose-context-with-adk/)