Middleware
Add pre and post-processing logic to your agent operations
Overview
Middleware in Magma allows you to intercept and modify agent behavior at key points in the execution flow. Using middleware, you can add custom logic that runs before or after completions are generated and tools are executed. You can manipulate the inputs of middleware directly, or throw an error to modify the flow of execution.
Middleware Types
Magma supports four types of middleware:
preCompletion
: Runs before an LLM completion is generatedonCompletion
: Runs after an LLM completion is generatedpreToolExecution
: Runs before a tool is executedonToolExecution
: Runs after a tool is executedonMainFinish
: Runs after the agent has generated its last completion in the main looppostProcess
: Runs after the agent has generated its last completion in the main loop (difference between this and onMainFinish explained in code snippet)
Throwing an error from preCompletion middleware will remove the failing user message from the message history, and return the error message as the result from main. No completion will be generated.
Throwing an error from onCompletion middleware will remove the failing assistant message from the message history, and trigger a regeneration of the completion with your error message as context. This middleware obeys the middleware failure rules
Throwing an error from preToolExecution middleware will remove the failing tool call from the message history, and trigger a regeneration of the completion with your error message as context. This middleware obeys the middleware failure rules
Throwing an error from onToolExecution middleware will replace the return value of the tool with the error that was thrown.
Throwing an error from onMainFinish middleware will remove the failing assistant message from the message history, and trigger a regeneration of the completion with your error message as context. This middleware obeys the middleware failure rules
PostProcess works the same as onMainFinish when throwing an error. However, if you return a value from PostProcess, the value is only changed in the return from main, not in the agent message history. This can be particularly useful for translating agent responses into different languages without affecting the agent message history.
Middleware Error handling
If a middleware function throws an error, the agent flow will be modified to handle it accordingly.
preCompletion
: The agent will not generate a completion, and the error message will be returned as if it were the agent’s response.onCompletion
: The agent will be notified of the error, and a completion will be re-generated.preToolExecution
: The agent will not execute the tool, and the error message will be returned as if it were the tool’s response.onToolExecution
: The agent will replace the tool’s response with the error message.onMainFinish
: The agent will be notified of the error, and a completion will be re-generated.postProcess
: The agent will be notified of the error, and a completion will be re-generated.
Middleware Failure Rules
For middleware errors that trigger completion regenerations, they can fail a maximum of 5 times.
After 5 retries, the behavior depends on whether the failing middleware is marked as critical
If a critical middleware condition cannot be met, the agent will throw an error.
If a non-critical middleware condition cannot be met, the agent will proceed normally, using the last generation.
Implementation
To add middleware to your agent, use the @middleware
decorator:
Chaining Middleware
You can add as many middleware functions as you want to your agent. Middleware functions of the same type are executed in order of definition.
Or, if you would like more explicit control, you can specify the order
argument in the middleware decorator. When using order, middleware functions will be executed from least to greatest order
value.
Common Use Cases
Middleware is particularly useful for:
- Input validation and sanitization
- Response filtering and modification
- Logging and monitoring
- Rate limiting
- Access control
- Response formatting
Best Practices
- Keep middleware functions focused and single-purpose
- Handle errors appropriately within middleware
- Use TypeScript types for better type safety
- Add clear documentation about what each middleware does
- Consider the order of middleware execution
- Return meaningful error messages when validation fails