跳转至

Tool Context

ToolContext dataclass

Bases: RunContextWrapper[TContext]

The context of a tool call.

Source code in src/agents/tool_context.py
@dataclass
class ToolContext(RunContextWrapper[TContext]):
    """The context of a tool call."""

    tool_name: str = field(default_factory=_assert_must_pass_tool_name)
    """The name of the tool being invoked."""

    tool_call_id: str = field(default_factory=_assert_must_pass_tool_call_id)
    """The ID of the tool call."""

    tool_arguments: str = field(default_factory=_assert_must_pass_tool_arguments)
    """The raw arguments string of the tool call."""

    tool_call: ResponseFunctionToolCall | None = None
    """The tool call object associated with this invocation."""

    agent: AgentBase[Any] | None = None
    """The active agent for this tool call, when available."""

    run_config: RunConfig | None = None
    """The active run config for this tool call, when available."""

    def __init__(
        self,
        context: TContext,
        usage: Usage | object = _MISSING,
        tool_name: str | object = _MISSING,
        tool_call_id: str | object = _MISSING,
        tool_arguments: str | object = _MISSING,
        tool_call: ResponseFunctionToolCall | None = None,
        *,
        agent: AgentBase[Any] | None = None,
        run_config: RunConfig | None = None,
        turn_input: list[TResponseInputItem] | None = None,
        _approvals: dict[str, _ApprovalRecord] | None = None,
        tool_input: Any | None = None,
    ) -> None:
        """Preserve the v0.7 positional constructor while accepting new context fields."""
        resolved_usage = Usage() if usage is _MISSING else cast(Usage, usage)
        super().__init__(
            context=context,
            usage=resolved_usage,
            turn_input=list(turn_input or []),
            _approvals={} if _approvals is None else _approvals,
            tool_input=tool_input,
        )
        self.tool_name = (
            _assert_must_pass_tool_name() if tool_name is _MISSING else cast(str, tool_name)
        )
        self.tool_arguments = (
            _assert_must_pass_tool_arguments()
            if tool_arguments is _MISSING
            else cast(str, tool_arguments)
        )
        self.tool_call_id = (
            _assert_must_pass_tool_call_id()
            if tool_call_id is _MISSING
            else cast(str, tool_call_id)
        )
        self.tool_call = tool_call
        self.agent = agent
        self.run_config = run_config

    @classmethod
    def from_agent_context(
        cls,
        context: RunContextWrapper[TContext],
        tool_call_id: str,
        tool_call: ResponseFunctionToolCall | None = None,
        agent: AgentBase[Any] | None = None,
        *,
        run_config: RunConfig | None = None,
    ) -> ToolContext:
        """
        Create a ToolContext from a RunContextWrapper.
        """
        # Grab the names of the RunContextWrapper's init=True fields
        base_values: dict[str, Any] = {
            f.name: getattr(context, f.name) for f in fields(RunContextWrapper) if f.init
        }
        tool_name = tool_call.name if tool_call is not None else _assert_must_pass_tool_name()
        tool_args = (
            tool_call.arguments if tool_call is not None else _assert_must_pass_tool_arguments()
        )
        tool_agent = agent
        if tool_agent is None and isinstance(context, ToolContext):
            tool_agent = context.agent
        tool_run_config = run_config
        if tool_run_config is None and isinstance(context, ToolContext):
            tool_run_config = context.run_config

        tool_context = cls(
            tool_name=tool_name,
            tool_call_id=tool_call_id,
            tool_arguments=tool_args,
            tool_call=tool_call,
            agent=tool_agent,
            run_config=tool_run_config,
            **base_values,
        )
        return tool_context

tool_name class-attribute instance-attribute

tool_name: str = (
    _assert_must_pass_tool_name()
    if tool_name is _MISSING
    else cast(str, tool_name)
)

The name of the tool being invoked.

tool_arguments class-attribute instance-attribute

tool_arguments: str = (
    _assert_must_pass_tool_arguments()
    if tool_arguments is _MISSING
    else cast(str, tool_arguments)
)

The raw arguments string of the tool call.

tool_call_id class-attribute instance-attribute

tool_call_id: str = (
    _assert_must_pass_tool_call_id()
    if tool_call_id is _MISSING
    else cast(str, tool_call_id)
)

The ID of the tool call.

tool_call class-attribute instance-attribute

tool_call: ResponseFunctionToolCall | None = tool_call

The tool call object associated with this invocation.

agent class-attribute instance-attribute

agent: AgentBase[Any] | None = agent

The active agent for this tool call, when available.

run_config class-attribute instance-attribute

run_config: RunConfig | None = run_config

The active run config for this tool call, when available.

context instance-attribute

context: TContext

The context object (or None), passed by you to Runner.run()

usage class-attribute instance-attribute

usage: Usage = field(default_factory=Usage)

The usage of the agent run so far. For streamed responses, the usage will be stale until the last chunk of the stream is processed.

tool_input class-attribute instance-attribute

tool_input: Any | None = None

Structured input for the current agent tool run, when available.

__init__

__init__(
    context: TContext,
    usage: Usage | object = _MISSING,
    tool_name: str | object = _MISSING,
    tool_call_id: str | object = _MISSING,
    tool_arguments: str | object = _MISSING,
    tool_call: ResponseFunctionToolCall | None = None,
    *,
    agent: AgentBase[Any] | None = None,
    run_config: RunConfig | None = None,
    turn_input: list[TResponseInputItem] | None = None,
    _approvals: dict[str, _ApprovalRecord] | None = None,
    tool_input: Any | None = None,
) -> None

Preserve the v0.7 positional constructor while accepting new context fields.

Source code in src/agents/tool_context.py
def __init__(
    self,
    context: TContext,
    usage: Usage | object = _MISSING,
    tool_name: str | object = _MISSING,
    tool_call_id: str | object = _MISSING,
    tool_arguments: str | object = _MISSING,
    tool_call: ResponseFunctionToolCall | None = None,
    *,
    agent: AgentBase[Any] | None = None,
    run_config: RunConfig | None = None,
    turn_input: list[TResponseInputItem] | None = None,
    _approvals: dict[str, _ApprovalRecord] | None = None,
    tool_input: Any | None = None,
) -> None:
    """Preserve the v0.7 positional constructor while accepting new context fields."""
    resolved_usage = Usage() if usage is _MISSING else cast(Usage, usage)
    super().__init__(
        context=context,
        usage=resolved_usage,
        turn_input=list(turn_input or []),
        _approvals={} if _approvals is None else _approvals,
        tool_input=tool_input,
    )
    self.tool_name = (
        _assert_must_pass_tool_name() if tool_name is _MISSING else cast(str, tool_name)
    )
    self.tool_arguments = (
        _assert_must_pass_tool_arguments()
        if tool_arguments is _MISSING
        else cast(str, tool_arguments)
    )
    self.tool_call_id = (
        _assert_must_pass_tool_call_id()
        if tool_call_id is _MISSING
        else cast(str, tool_call_id)
    )
    self.tool_call = tool_call
    self.agent = agent
    self.run_config = run_config

from_agent_context classmethod

from_agent_context(
    context: RunContextWrapper[TContext],
    tool_call_id: str,
    tool_call: ResponseFunctionToolCall | None = None,
    agent: AgentBase[Any] | None = None,
    *,
    run_config: RunConfig | None = None,
) -> ToolContext

Create a ToolContext from a RunContextWrapper.

Source code in src/agents/tool_context.py
@classmethod
def from_agent_context(
    cls,
    context: RunContextWrapper[TContext],
    tool_call_id: str,
    tool_call: ResponseFunctionToolCall | None = None,
    agent: AgentBase[Any] | None = None,
    *,
    run_config: RunConfig | None = None,
) -> ToolContext:
    """
    Create a ToolContext from a RunContextWrapper.
    """
    # Grab the names of the RunContextWrapper's init=True fields
    base_values: dict[str, Any] = {
        f.name: getattr(context, f.name) for f in fields(RunContextWrapper) if f.init
    }
    tool_name = tool_call.name if tool_call is not None else _assert_must_pass_tool_name()
    tool_args = (
        tool_call.arguments if tool_call is not None else _assert_must_pass_tool_arguments()
    )
    tool_agent = agent
    if tool_agent is None and isinstance(context, ToolContext):
        tool_agent = context.agent
    tool_run_config = run_config
    if tool_run_config is None and isinstance(context, ToolContext):
        tool_run_config = context.run_config

    tool_context = cls(
        tool_name=tool_name,
        tool_call_id=tool_call_id,
        tool_arguments=tool_args,
        tool_call=tool_call,
        agent=tool_agent,
        run_config=tool_run_config,
        **base_values,
    )
    return tool_context

is_tool_approved

is_tool_approved(
    tool_name: str, call_id: str
) -> bool | None

Return True/False/None for the given tool call.

Source code in src/agents/run_context.py
def is_tool_approved(self, tool_name: str, call_id: str) -> bool | None:
    """Return True/False/None for the given tool call."""
    approval_entry = self._approvals.get(tool_name)
    if not approval_entry:
        return None

    # Check for permanent approval/rejection
    if approval_entry.approved is True and approval_entry.rejected is True:
        # Approval takes precedence
        return True

    if approval_entry.approved is True:
        return True

    if approval_entry.rejected is True:
        return False

    approved_ids = (
        set(approval_entry.approved) if isinstance(approval_entry.approved, list) else set()
    )
    rejected_ids = (
        set(approval_entry.rejected) if isinstance(approval_entry.rejected, list) else set()
    )

    if call_id in approved_ids:
        return True
    if call_id in rejected_ids:
        return False
    # Per-call approvals are scoped to the exact call ID, so other calls require a new decision.
    return None

approve_tool

approve_tool(
    approval_item: ToolApprovalItem,
    always_approve: bool = False,
) -> None

Approve a tool call, optionally for all future calls.

Source code in src/agents/run_context.py
def approve_tool(self, approval_item: ToolApprovalItem, always_approve: bool = False) -> None:
    """Approve a tool call, optionally for all future calls."""
    self._apply_approval_decision(
        approval_item,
        always=always_approve,
        approve=True,
    )

reject_tool

reject_tool(
    approval_item: ToolApprovalItem,
    always_reject: bool = False,
) -> None

Reject a tool call, optionally for all future calls.

Source code in src/agents/run_context.py
def reject_tool(self, approval_item: ToolApprovalItem, always_reject: bool = False) -> None:
    """Reject a tool call, optionally for all future calls."""
    self._apply_approval_decision(
        approval_item,
        always=always_reject,
        approve=False,
    )

get_approval_status

get_approval_status(
    tool_name: str,
    call_id: str,
    *,
    existing_pending: ToolApprovalItem | None = None,
) -> bool | None

Return approval status, retrying with pending item's tool name if necessary.

Source code in src/agents/run_context.py
def get_approval_status(
    self, tool_name: str, call_id: str, *, existing_pending: ToolApprovalItem | None = None
) -> bool | None:
    """Return approval status, retrying with pending item's tool name if necessary."""
    status = self.is_tool_approved(tool_name, call_id)
    if status is None and existing_pending:
        fallback_tool_name = self._resolve_tool_name(existing_pending)
        status = self.is_tool_approved(fallback_tool_name, call_id)
    return status