# Genkit 推出中间件系统：增强智能体AI应用的可控性与可靠性

- 来源：Google Developers Blog（RSS）
- 发布时间：2026-05-14 00:00
- AIHOT 分数：62
- AIHOT 标记：精选
- AIHOT 链接：https://aihot.virxact.com/items/cmp5qtyt20gjgsljxg925uv7t
- 原文链接：https://developers.googleblog.com/announcing-genkit-middleware-intercept-extend-and-harden-your-agentic-apps

## 精选理由

Genkit 的中间件系统把 agent 行为变成可编程的拦截点，重试、fallback、人机审批都能挂上，对用 Genkit 上生产的团队来说，是个能让应用更「硬」的更新。

## AI 摘要

Google开源框架Genkit近日推出其核心中间件系统，旨在提升智能体AI应用的可靠性与可控性。该系统允许开发者在生成调用、模型及工具层进行拦截，以注入自定义行为，如重试机制、模型回退以及人工介入的工具审批流程。通过创建并堆叠自定义中间件，开发者能够实现对模型输出的确定性控制。所有中间件的执行流程均可通过专用的开发者界面进行实时查看与调试，有效支持使用TypeScript、Go、Dart和Python构建生产就绪的智能体应用。

## 正文

Genkit 是一个开源框架，用于构建面向任何平台的全栈、AI 驱动及智能体应用，支持 TypeScript、Go、Dart 和 Python。构建一个可用于生产的智能体应用和 AI 功能，需要的不仅仅是强大的模型和精心的提示词设计。你可能需要重试和回退机制以实现最大可靠性，在破坏性工具调用前需要人工审批，并且需要对每一层进行可观测性监控。

Genkit 通过中间件解决了这个问题：可组合的钩子，它们能拦截生成调用（包括工具执行循环）并注入自定义行为。该中间件系统目前已支持 TypeScript、Go 和 Dart，Python 支持即将推出。

Genkit 中间件的工作原理

Genkit 中的每次 `generate()` 调用都会运行一个工具循环：模型产生输出，执行任何被请求的工具，结果反馈给新的模型调用，然后循环重复，直到模型完成。中间件钩子附着在此循环的三个层级上：

钩子 运行时机 典型用途

生成 每个工具循环迭代一次 上下文注入、消息重写、对话级别逻辑

模型 每次模型 API 调用一次 重试、回退、缓存、延迟日志记录

工具 每次工具执行一次 人在回路、沙箱隔离、按工具记录日志

预构建的中间件

Genkit 提供了几种针对常见用例的预构建中间件解决方案。以下是目前已可用的：

1. 重试

在遇到瞬时错误（如 RESOURCE_EXHAUSTED、UNAVAILABLE 等）时，使用带抖动的指数退避策略自动重试失败的模型 API 调用。仅重试模型调用，不会重放整个工具循环。

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, }), )

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), // fall back to Claude }, Statuses: []core.StatusName{core.RESOURCE_EXHAUSTED}, }), )

3. 工具审批

将工具执行限制在一个允许列表中。任何不在列表中的工具都会触发中断，从而在操作执行前启用人在回路确认。

resp, _ := genkit.Generate(ctx, g, ai.WithPrompt("Delete the temp files"), ai.WithTools(deleteFilesTool), ai.WithUse(&middleware.ToolApproval{ AllowedTools: []string{}, // empty = every tool call interrupts }), )

if len(resp.Interrupts()) > 0 { interrupt := resp.Interrupts()[0]

// Prompt the user for approval, then resume with the approval flag. 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()) }

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"}}), )

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, }), )

构建自定义中间件

预构建的中间件涵盖了常见场景，但该系统的真正强大之处在于编写你自己的中间件。想象一下，你正在构建一个智能体客服应用，需要确保模型绝不提及竞争对手产品或内部定价数据。与其将这些规则编码到每个提示词中，不如通过中间件以确定性的方式强制执行它们。

自定义中间件在所有语言中都遵循一个简单的约定：提供一个名称和一个返回所需钩子的工厂函数。该工厂函数在每次 `generate()` 调用时被调用一次，并且你只需实现你需要的钩子。

以下是一个完整的、约 20 行代码的自定义内容过滤器：

// ContentFilter rejects model responses containing any forbidden term. 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 }

你甚至可以组合和堆叠不同的中间件解决方案。中间件从左到右堆叠，第一个列出的是最外层包装器，依此类推：

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}, // outer: retries the inner stack &ContentFilter{ // inner: validates model output ForbiddenTerms: []string{"CompetitorCRM", "RivalCo", "internal price"}, }, ), )

这里，Retry 包裹了 ContentFilter，而 ContentFilter 又包裹了模型调用。顺序很重要，Genkit 使其明确化。

如果你认为自己构建了一个对其他开发者有价值的中间件，你可以将其作为软件包发布，让其他人从中受益！

开发者 UI 体验

你可以使用 Genkit 开发者 UI 来检查、测试和调试你的应用程序，包括中间件的执行。当你注册中间件时，它会在开发者 UI 中变得可见：你可以检查其配置、追踪通过每个钩子层的执行过程，并测试不同的组合。

我们对 Genkit 中间件为你的应用解锁的能力感到兴奋，并期待看到你将构建哪些自定义中间件来解决你的用例。请查看中间件文档以深入了解，或者如果你是框架新手，可以从 Genkit 入门开始。

对新的预构建中间件有想法？请提交一个 issue。我们很乐意听取哪些改进能提升你的开发体验！

编码愉快！🚀

AI

公告

学习

影响
