Middleware
Middleware in AG-UI provides a powerful way to transform, filter, and augment the event streams that flow through agents. It enables you to add cross-cutting concerns like logging, authentication, rate limiting, and event filtering without modifying the core agent logic. Examples below assume the relevant RxJS operators/utilities (map, tap, catchError, switchMap, timer, etc.) are imported.
What is Middleware?
Middleware sits between the agent execution and the event consumer, allowing you to:- Transform events – Modify or enhance events as they flow through the pipeline
- Filter events – Selectively allow or block certain events
- Add metadata – Inject additional context or tracking information
- Handle errors – Implement custom error recovery strategies
- Monitor execution – Add logging, metrics, or debugging capabilities
How Middleware Works
Middleware forms a chain where each middleware wraps the next, creating layers of functionality. When an agent runs, the event stream flows through each middleware in sequence.agent.use(...) is applied in runAgent(). connectAgent() currently calls connect() directly and does not run middleware.
Function-Based Middleware
For simple transformations, you can use function-based middleware. This is the most concise way to add middleware:Class-Based Middleware
For more complex scenarios requiring state or configuration, use class-based middleware:runNext(input, next)normalizes chunk events into fullTEXT_MESSAGE_*/TOOL_CALL_*sequences.runNextWithState(input, next)also provides accumulatedmessagesandstateafter each event.
Built-in Middleware
AG-UI provides several built-in middleware components for common use cases:FilterToolCallsMiddleware
Filter tool calls based on allowed or disallowed lists:FilterToolCallsMiddleware filters emitted TOOL_CALL_* events. It does not block tool execution in the upstream model/runtime.
Middleware Patterns
Common patterns include logging, auth viaforwardedProps, and rate limiting. See the JS middleware reference for concrete implementations.
Combining Middleware
You can combine multiple middleware to create sophisticated processing pipelines:Execution Order
Middleware executes in the order it’s added, with each middleware wrapping the next:- First middleware receives the original input
- It can modify the input before passing to the next middleware
- Each middleware processes events from the next in the chain
- The final middleware calls the actual agent
Best Practices
- Keep middleware focused – Each middleware should have a single responsibility
- Handle errors gracefully – Use RxJS error handling operators
- Avoid blocking operations – Use async patterns for I/O operations
- Document side effects – Clearly indicate if middleware modifies state
- Test middleware independently – Write unit tests for each middleware
- Consider performance – Be mindful of processing overhead in the event stream