Repository: livekit/agents
File: livekit-agents/livekit/agents/beta/tools/end_call.py (Python)

Code before:
Do not call when:
- The user asks to pause, hold, or transfer.
- Intent is unclear.

This is the final action the agent can take.
Once called, no further interaction is possible with the user.
Don't generate any other text or response when the tool is called.
"""


class EndCallTool(Toolset):
    def __init__(
        self,
        *,
        extra_instructions: str = "",
        delete_room: bool = True,
        end_instructions: str
        | Callable[[RunContext], Awaitable[None]]
        | None = "say goodbye to the user",
    ):
        """
        This tool allows the agent to end the call and disconnect from the room.

        Args:
            extra_instructions: Additional instructions to add to the end call tool.
            delete_room: Whether to delete the room when the user ends the call.
            end_instructions: If a string is provided, it will be used as the instructions of
                `session.generate_reply` when the user ends the call. If a callback, it will be called
                when the user ends the call.
        """
        super().__init__()
        self._delete_room = delete_room
        self._extra_instructions = extra_instructions
        self._end_instructions = end_instructions

        self._end_call_tool = function_tool(
            self._end_call,
            name="end_call",
            description=f"{END_CALL_INSTRUCTIONS}\n{extra_instructions}",
        )

    async def _end_call(self, ctx: RunContext) -> None:
        try:
            logger.debug("end_call tool called")
            ctx.session.once("close", self._on_session_close)
            if isinstance(self._end_instructions, str):
                await ctx.session.generate_reply(
                    instructions=self._end_instructions, tool_choice="none"
                )
            elif callable(self._end_instructions):
                await self._end_instructions(ctx)

Review comment (suggestion):
```suggestion
            delete_room: Whether to delete the room when the user ends the call. deleting the room disconnects all remote users, including SIP callers.
```

Code after:
- The agent determines the conversation is complete and should end.

Do not call when:
- The user asks to pause, hold, or transfer.
- Intent is unclear.

This is the final action the agent can take.
Once called, no further interaction is possible with the user.
Don't generate any other text or response when the tool is called.
"""


class EndCallTool(Toolset):
    def __init__(
        self,
        *,
        extra_description: str = "",
        delete_room: bool = True,
        end_instructions: str | None = "say goodbye to the user",
        on_tool_called: Callable[[Toolset.ToolCalledEvent], Awaitable[None]] | None = None,
        on_tool_completed: Callable[[Toolset.ToolCompletedEvent], Awaitable[None]] | None = None,
    ):
        """
        This tool allows the agent to end the call and disconnect from the room.

        Args:
            extra_description: Additional description to add to the end call tool.
            delete_room: Whether to delete the room when the user ends the call. deleting the room disconnects all remote users, including SIP callers.
            end_instructions: Tool output to the LLM for generating the tool response.
            on_tool_called: Callback to call when the tool is called.
            on_tool_completed: Callback to call when the tool is completed.
        """
        super().__init__()
        self._delete_room = delete_room
        self._extra_description = extra_description

        self._end_instructions = end_instructions
        self._on_tool_called = on_tool_called
        self._on_tool_completed = on_tool_completed

        self._end_call_tool = function_tool(
            self._end_call,
            name="end_call",
            description=f"{END_CALL_DESCRIPTION}\n{extra_description}",
        )
        self._shutdown_session_task: asyncio.Task[None] | None = None

    async def _end_call(self, ctx: RunContext) -> Any | None:
        logger.debug("end_call tool called")
        llm_v = ctx.session.current_agent._get_activity_or_raise().llm