Background Hooks (Global)
Run non-guardrail agent hooks as background tasks using AgentOS
Run non-guardrail hooks as FastAPI background tasks by enabling run_hooks_in_background at the AgentOS level. Hooks represented by BaseGuardrail remain in the foreground at their normal pre- or post-run stage. An ordinary validation callable is not automatically a guardrail and runs in the background under this global setting.
These examples use background callbacks attached to a normal AgentOS HTTP response. They execute after the response completes in the serving process; they are not durable queue jobs. A process shutdown or callback failure can prevent pending callbacks from finishing. Use the durable job queue for run execution that must survive a restart.
Create a Python file
import asyncio
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIResponses
from agno.os import AgentOS
from agno.run.agent import RunInput
# Pre-hook for logging requests
def log_request(run_input: RunInput, agent):
"""
This pre-hook is queued while the run starts and executes after the response.
Background pre-hooks cannot modify run_input for the active run.
"""
print(f"[Background Pre-Hook] Request received for agent: {agent.name}")
print(f"[Background Pre-Hook] Input: {run_input.input_content}")
# Post-hook for logging analytics
async def log_analytics(run_output, agent, session):
"""
This post-hook will run in the background after the response is sent.
It won't block the API response.
"""
print(f"[Background Post-Hook] Logging analytics for run: {run_output.run_id}")
print(f"[Background Post-Hook] Agent: {agent.name}")
print(f"[Background Post-Hook] Session: {session.session_id}")
# Simulate a slow operation
await asyncio.sleep(2)
print("[Background Post-Hook] Analytics logged successfully!")
# Another post-hook for sending notifications
async def send_notification(run_output, agent):
"""
Another background task that sends notifications without blocking the response.
"""
print(f"[Background Post-Hook] Sending notification for agent: {agent.name}")
# Simulate a slow operation
await asyncio.sleep(3)
print("[Background Post-Hook] Notification sent!")
# Create an agent with hooks
agent = Agent(
id="background-task-agent",
name="BackgroundTaskAgent",
model=OpenAIResponses(id="gpt-5.2"),
instructions="You are a helpful assistant",
db=SqliteDb(db_file="tmp/agent.db"),
pre_hooks=[log_request],
post_hooks=[log_analytics, send_notification],
markdown=True,
)
# Create AgentOS with background hooks enabled
agent_os = AgentOS(
agents=[agent],
run_hooks_in_background=True, # Non-guardrail hooks run in background
)
# Get the FastAPI app
app = agent_os.get_app()
if __name__ == "__main__":
agent_os.serve(app="background_hooks_global:app", port=7777, reload=True)Set up your virtual environment
uv venv --python 3.12
source .venv/bin/activateInstall dependencies
uv pip install -U "agno[os]" openaiExport your OpenAI API key
export OPENAI_API_KEY="your_openai_api_key_here"Run the server
python background_hooks_global.pyTest the endpoint
curl -X POST http://localhost:7777/agents/background-task-agent/runs \
-F "message=Hello, how are you?" \
-F "stream=false"The response is returned after the model and foreground work complete. Check the server logs to see the background hooks executing after the response is sent.
What Happens
- Foreground pre-guardrails validate input before model processing.
- The agent processes the request and foreground post-guardrails validate output.
- The response completes.
- Queued non-guardrail pre-hooks and post-hooks run as response callbacks.
- The client does not wait for those callbacks to finish.
With run_hooks_in_background=True on AgentOS, non-guardrail hooks for all agents run in the background. Guardrail hooks remain synchronous. Use the @hook decorator for per-hook control.