@googledevs: Building agentic apps is easy. Making them production-ready is hard. Announcing Genkit Middleware: A composable way to …
Summary
Google announces Genkit Middleware, a composable middleware system for the Genkit open-source framework to add retries, fallbacks, human-in-the-loop approvals, and observability to agentic applications. It is available now for TypeScript, Go, and Dart, with Python support coming soon.
View Cached Full Text
Cached at: 05/15/26, 07:00 AM
Building agentic apps is easy. Making them production-ready is hard. 🛠️
Announcing Genkit Middleware: A composable way to intercept, extend, and harden your agentic apps.
✅ Retries & Fallbacks ✅ Human-in-the-loop approvals ✅ Full observability
Now live for TypeScript, Go,
Announcing Genkit Middleware: Intercept, extend, and harden your agentic apps
Source: https://developers.googleblog.com/announcing-genkit-middleware-intercept-extend-and-harden-your-agentic-apps/ Genkitis an open-source framework forbuilding full-stack, AI-powered and agentic applications for any platformwith support for TypeScript, Go, Dart, and Python. Building a production-ready agentic applications and AI features requires more than powerful models and careful prompting. You might need retries and fallbacks for maximum reliability, human approval before destructive tool calls, and observability across every layer.
Genkit solves this withmiddleware: composable hooks that intercept generation calls, including the tool execution loop, and inject custom behaviors. The middleware system is available today in TypeScript, Go, and Dart, with Python support coming soon.
How Genkit middleware works
Everygenerate\(\)call in Genkit runs atool loop: the model produces output, any requested tools execute, the results feed back into a new model call, and the cycle repeats until the model is done. Middleware hooks attach at three layers of this loop:
HookWhen it runsTypical useGenerateOnce per tool-loop iterationContext injection, message rewriting, conversation-level logicModelOnce per model API callRetry, fallback, caching, latency loggingToolOnce per tool executionHuman-in-the-loop, sandboxing, per-tool logging
Pre-built middleware
Genkit offers several pre-built middleware solutions for common use-cases. Here’s what’s available today:
1. Retry
Automatically retries failed model API calls on transient errors (RESOURCE\_EXHAUSTED, UNAVAILABLE, etc.) using exponential backoff with jitter. Only the model call is retried; the surrounding tool loop is not replayed.
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
Copied
2. Fallback
Switches to an alternative model when the primary model fails on a specified set of error codes. Useful for falling back to a completely different provider when your primary model exceeds its quota.
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},
}),
)
Go
Copied
3. Tool approval
Restricts tool execution to an allow-list. Any tool not on the list triggers an interrupt, enabling human-in-the-loop confirmation before the action proceeds.
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())
}
Go
Copied
4. Skills
Scans a directory forSKILL\.mdfiles and injects their content into the system prompt. Also exposes ause\_skilltool so the model can load specific skills on demand.
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("How do I deploy this service?"),
ai.WithUse(&middleware.Skills{SkillPaths: []string{"./skills"}}),
)
Go
Copied
5. Filesystem
Gives the model scoped access to the local filesystem through injected tools (list\_files,read\_file,plus write\_fileandedit\_filewhen writes are enabled). Path safety is enforced so the model can never escape the root directory.
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
Copied
Building custom middleware
The pre-built middleware covers common scenarios, but the real power of the system is in writing your own. Imagine you’re building an agentic customer-support app and need to ensure the model never mentions competitor products or internal pricing data. Rather than encoding these rules in every prompt, you can enforce them deterministically with middleware.
Custom middleware follows a simple contract across all languages: provide a name and a factory function that returns the hooks you want. The factory is called once pergenerate\(\)invocation, and you implement only the hooks you need.
Here’s a complete, custom content filter in ~20 lines of code:
// 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
}
Go
Copied
You can even compose and stack different middleware solutions. Middleware stacks left-to-right, with the first listed being the outermost wrapper and so on:
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"},
},
),
)
Go
Copied
HereRetrywrapsContentFilter, which wraps the model call. Order matters, and Genkit makes it explicit.
If you think you’ve built a middleware that will be valuable to other developers, you can publish it as a package for others to benefit from!
The Developer UI experience
You can use the GenkitDeveloper UIto inspect, test, and debug your application, including middleware execution. When you register middleware, it becomes visible in the Dev UI: you can inspect its configuration, trace execution through each hook layer, and test different combinations.
Sorry, your browser doesn’t support playback for this video
Get started
We’re excited for the capabilities that Genkit middleware unlocks for your apps, and we’re looking forward to seeing what custom middleware you’ll build to solve for your use-cases. Check out themiddleware documentationto dive deeper, orget started with Genkitif you’re new to the framework.
Have an idea for a new pre-built middleware?File an issue. We’d love to hear what would improve your development experience!
Happy coding! 🚀
Similar Articles
Genkit Middleware (10 minute read)
Google announces Genkit middleware, composable hooks that intercept AI generation calls enabling retries, fallbacks, tool approval, and skills for building reliable agentic applications.
@akshay_pachaar: Karpathy's Agentic Engineering finally has proper tooling! (built by Google) Karpathy defined agentic engineering as th…
Google released Agents CLI, a unified command-line tool that integrates scaffolding, evaluation, and deployment of agents on Google Cloud, enabling coding assistants to practice agentic engineering without context switching.
@googledevs: The agentic era is here. Google just dropped major updates for devs, including: Gemini 3.5 Flash: 4x faster performance…
Google I/O 2026 announced major developer updates including Gemini 3.5 Flash (4x faster), Antigravity 2.0 CLI for agent development, and AI Studio mobile app, marking the shift to an agentic era.
@googledevs: Agent development is moving forward. While production scaling traditionally required manual infrastructure setup and pr…
Google announces the official launch of Managed Agents in the Gemini API, enabling agent development with zero infrastructure overhead. The article also highlights AGENTS.md, an open format for providing context to AI coding agents, adopted by over 60k open-source projects.
@mfpiccolo: https://x.com/mfpiccolo/status/2064358779940995141
The article introduces iii, an open-source platform for building production-ready agentic backends using composable workers that replace traditional service integration, offering a React-like paradigm for backend engineering.