Loading...
Loading...
Intercept the AG2 agent loop with `BaseMiddleware` — wrap full turns (`on_turn`), each LLM call (`on_llm_call`), each tool execution (`on_tool_execution`), or each human-input request (`on_human_input`). Use for retry, logging, history trimming, request mutation, tool auditing, guardrails, or rate limiting. Built-ins: `LoggingMiddleware`, `RetryMiddleware`, `HistoryLimiter`, `TokenLimiter`, `TelemetryMiddleware` (see `ag2-telemetry`). For per-tool hooks see also `ag2-add-custom-tool` tool-middleware section.
npx skill4agent add ag2ai/ag2-skills ag2-middlewareBaseMiddleware| Hook | Wraps | Use for |
|---|---|---|
| The whole agent turn | Total latency, request/response inspection, turn-level policies |
| Each LLM API call | Retry, logging, history trim, request mutation, caching |
| Each tool invocation | Validate args, redact results, fallback on failure, access control |
| Each | Audit, rewrite prompts, automated short-circuit, rate limit |
selfag2.middleware| Middleware | Purpose | Constructor |
|---|---|---|
| Logs turn start/end, each LLM call, each tool execution | no args |
| Retries failed LLM calls | |
| Cap event count before LLM call | |
| Char-based token-budget cap before LLM call | |
| OpenTelemetry GenAI spans (see | see telemetry skill |
from ag2 import Agent
from ag2.config import OpenAIConfig
from ag2.middleware import LoggingMiddleware, RetryMiddleware
agent = Agent(
"assistant",
config=OpenAIConfig(model="gpt-4o-mini"),
middleware=[
LoggingMiddleware(),
RetryMiddleware(max_retries=2),
],
)agent.ask(...)reply.ask(...)from ag2.middleware import TokenLimiter
reply = await agent.ask("Summarise the latest messages.", middleware=[LoggingMiddleware()])
next_turn = await reply.ask("Now answer in one paragraph.", middleware=[TokenLimiter(max_tokens=4000)])with[A, B, C]A → B → CC → B → Aenter A
enter B
enter C
<LLM call>
exit C
exit B
exit ARetryMiddlewareBaseMiddlewareimport logging
from collections.abc import Sequence
from ag2 import Agent, Context
from ag2.config import OpenAIConfig
from ag2.events import BaseEvent, ModelResponse, ToolCallEvent
from ag2.middleware import BaseMiddleware, LLMCall, Middleware, ToolExecution
class AuditMiddleware(BaseMiddleware):
def __init__(self, event: BaseEvent, context: Context, logger: logging.Logger) -> None:
super().__init__(event, context)
self.logger = logger
async def on_llm_call(self, call_next: LLMCall, events: Sequence[BaseEvent], context: Context) -> ModelResponse:
self.logger.info("Calling model with %d events", len(events))
response = await call_next(events, context)
self.logger.info("Model returned: %s", response)
return response
async def on_tool_execution(self, call_next: ToolExecution, event: ToolCallEvent, context: Context):
self.logger.info("Executing tool: %s", event.name)
return await call_next(event, context)
agent = Agent(
"assistant",
config=OpenAIConfig(model="gpt-4o-mini"),
middleware=[
Middleware(AuditMiddleware, logger=logging.getLogger("ag2.audit")),
],
)eventcontextMiddleware(YourClass, ...)middleware=[LoggingMiddleware()]middleware=[hook]@tool@agent.toolToolkitag2-add-custom-toolapproval_required()ag2-hitlBaseMiddleware.on_tool_execution()on_turnon_llm_callon_tool_executionBaseMiddlewareon_human_inputreferences/builtin_middleware.mdwebsite/docs/user-guide/middleware.mdxwebsite/docs/user-guide/tools/tool_middleware.mdxBaseMiddlewareag2-telemetryMiddleware(...)middleware=[AuditMiddleware]eventcontextmiddleware=[Middleware(AuditMiddleware, logger=...)][A, B]on_tool_executionevent.nameon_tool_executionTelemetryMiddlewareag2-telemetry