Implementation:Openai Openai agents python RunState Approve Reject
Overview
This page documents the concrete API for inspecting, approving, and rejecting pending tool calls on a RunState object after an agent run has been interrupted.
Method Signatures
All three methods are defined on the RunState class in src/agents/run_state.py (lines 208-227):
get_interruptions()
def get_interruptions(self) -> list[ToolApprovalItem]:
"""Return pending interruptions if the current step is an interruption."""
Returns the list of ToolApprovalItem objects that are awaiting a human decision. Returns an empty list if the run was not interrupted or there are no pending approvals.
approve()
def approve(self, approval_item: ToolApprovalItem, always_approve: bool = False) -> None:
"""Approve a tool call and rerun with this state to continue."""
Parameters:
- approval_item: The
ToolApprovalItemto approve, obtained fromget_interruptions() - always_approve: When
True, all future calls to this tool are automatically approved for the remainder of the run (default:False)
Raises: UserError if the RunState has no associated context.
reject()
def reject(self, approval_item: ToolApprovalItem, always_reject: bool = False) -> None:
"""Reject a tool call and rerun with this state to continue."""
Parameters:
- approval_item: The
ToolApprovalItemto reject, obtained fromget_interruptions() - always_reject: When
True, all future calls to this tool are automatically rejected for the remainder of the run (default:False)
Raises: UserError if the RunState has no associated context.
Import
from agents import RunState
Example: Interactive Approval Loop
state = result.to_state()
interruptions = state.get_interruptions()
for item in interruptions:
# Present the pending tool call to the user
user_decision = input(f"Approve {item.tool_name}? (y/n): ")
if user_decision == "y":
state.approve(item)
else:
state.reject(item)
Example: Blanket Approval for a Trusted Tool
state = result.to_state()
interruptions = state.get_interruptions()
for item in interruptions:
if item.tool_name == "read_file":
# Trust all future read_file calls
state.approve(item, always_approve=True)
elif item.tool_name == "delete_file":
# Never allow delete_file
state.reject(item, always_reject=True)
else:
# Approve this specific call only
state.approve(item)
Example: Selective Approval with Multiple Interruptions
state = result.to_state()
interruptions = state.get_interruptions()
# Approve the first tool call, reject the second
if len(interruptions) >= 2:
state.approve(interruptions[0])
state.reject(interruptions[1])
Internal Behavior
Both approve() and reject() delegate to the RunContextWrapper:
def approve(self, approval_item: ToolApprovalItem, always_approve: bool = False) -> None:
if self._context is None:
raise UserError("Cannot approve tool: RunState has no context")
self._context.approve_tool(approval_item, always_approve=always_approve)
def reject(self, approval_item: ToolApprovalItem, always_reject: bool = False) -> None:
if self._context is None:
raise UserError("Cannot reject tool: RunState has no context")
self._context.reject_tool(approval_item, always_reject=always_reject)
The RunContextWrapper maintains an internal _approvals dictionary that maps tool names to approval records. These records track individual call approvals/rejections as well as blanket always_approve/always_reject flags.
Source References
src/agents/run_state.pylines 208-227:get_interruptions(),approve(), andreject()methods