Post-Hook Retry
Request another model decision from a tool post-hook with RetryAgentRun.
Demonstrates retry tool call from post hook.
"""
Retry Tool Call From Post Hook
=============================
Demonstrates retry tool call from post hook.
"""
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.exceptions import RetryAgentRun
from agno.models.openai import OpenAIChat
from agno.run import RunContext
from agno.tools import FunctionCall, tool
from agno.utils.log import logger
# ---------------------------------------------------------------------------
# Create Agent
# ---------------------------------------------------------------------------
def post_hook(run_context: RunContext, fc: FunctionCall):
logger.info(f"Post-hook: {fc.function.name}")
logger.info(f"Arguments: {fc.arguments}")
if run_context.session_state is None:
run_context.session_state = {}
shopping_list = (
run_context.session_state.get("shopping_list", [])
if run_context.session_state
else []
)
if len(shopping_list) < 3:
raise RetryAgentRun(
f"Shopping list is: {shopping_list}. Minimum 3 items in the shopping list. "
+ f"Add {3 - len(shopping_list)} more items."
)
@tool(post_hook=post_hook)
def add_item(run_context: RunContext, item: str) -> str:
"""Add an item to the shopping list."""
if run_context.session_state is None:
run_context.session_state = {}
if "shopping_list" not in run_context.session_state:
run_context.session_state["shopping_list"] = []
run_context.session_state["shopping_list"].append(item)
return f"The shopping list is now {run_context.session_state['shopping_list']}"
agent = Agent(
model=OpenAIChat(id="gpt-5.2"),
session_id="retry_tool_call_from_post_hook_session",
db=SqliteDb(
session_table="retry_tool_call_from_post_hook_session",
db_file="tmp/retry_tool_call_from_post_hook.db",
),
# Initialize the session state with empty shopping list
session_state={"shopping_list": []},
tools=[add_item],
markdown=True,
)
# ---------------------------------------------------------------------------
# Run Agent
# ---------------------------------------------------------------------------
if __name__ == "__main__":
agent.print_response("Add milk", stream=True)
print(
f"Final session state: {agent.get_session_state(session_id='retry_tool_call_from_post_hook_session')}"
)RetryAgentRun sends feedback to the model for its next decision; it does not replay the same call through a fixed retry/backoff loop. The tool appends the item before raising, and that state change remains. The model can add another item or repeat one; this example does not enforce uniqueness.
The fixed session ID and SQLite file retain the shopping list between executions. Use a new session ID to demonstrate the empty-list case again. A prompt asking for milk alone does not guarantee that the model will supply two additional items.
Run the Example
Set up your virtual environment
uv venv --python 3.12
source .venv/bin/activateInstall dependencies
uv pip install -U agno openai sqlalchemyExport your OpenAI API key
export OPENAI_API_KEY="your_openai_api_key_here"Run the example
Save the code above as retry_tool_call_from_post_hook.py, then run:
python retry_tool_call_from_post_hook.pyFull source: cookbook/91_tools/exceptions/retry_tool_call_from_post_hook.py