Module livekit.agents.beta.workflows.name
Classes
class GetNameResult (first_name: str | None = None,
middle_name: str | None = None,
last_name: str | None = None)-
Expand source code
@dataclass class GetNameResult: first_name: str | None = None middle_name: str | None = None last_name: str | None = NoneGetNameResult(first_name: 'str | None' = None, middle_name: 'str | None' = None, last_name: 'str | None' = None)
Instance variables
var first_name : str | Nonevar last_name : str | Nonevar middle_name : str | None
class GetNameTask (first_name: bool = True,
last_name: bool = False,
middle_name: bool = False,
name_format: NotGivenOr[str] = NOT_GIVEN,
verify_spelling: bool = False,
extra_instructions: str = '',
chat_ctx: NotGivenOr[llm.ChatContext] = NOT_GIVEN,
turn_detection: NotGivenOr[TurnDetectionMode | None] = NOT_GIVEN,
tools: NotGivenOr[list[llm.Tool | llm.Toolset]] = NOT_GIVEN,
stt: NotGivenOr[stt.STT | None] = NOT_GIVEN,
vad: NotGivenOr[vad.VAD | None] = NOT_GIVEN,
llm: NotGivenOr[llm.LLM | llm.RealtimeModel | None] = NOT_GIVEN,
tts: NotGivenOr[tts.TTS | None] = NOT_GIVEN,
allow_interruptions: NotGivenOr[bool] = NOT_GIVEN,
require_confirmation: NotGivenOr[bool] = NOT_GIVEN)-
Expand source code
class GetNameTask(AgentTask[GetNameResult]): def __init__( self, first_name: bool = True, last_name: bool = False, middle_name: bool = False, name_format: NotGivenOr[str] = NOT_GIVEN, verify_spelling: bool = False, extra_instructions: str = "", chat_ctx: NotGivenOr[llm.ChatContext] = NOT_GIVEN, turn_detection: NotGivenOr[TurnDetectionMode | None] = NOT_GIVEN, tools: NotGivenOr[list[llm.Tool | llm.Toolset]] = NOT_GIVEN, stt: NotGivenOr[stt.STT | None] = NOT_GIVEN, vad: NotGivenOr[vad.VAD | None] = NOT_GIVEN, llm: NotGivenOr[llm.LLM | llm.RealtimeModel | None] = NOT_GIVEN, tts: NotGivenOr[tts.TTS | None] = NOT_GIVEN, allow_interruptions: NotGivenOr[bool] = NOT_GIVEN, require_confirmation: NotGivenOr[bool] = NOT_GIVEN, ) -> None: if not (first_name or middle_name or last_name): raise ValueError("At least one of first_name, middle_name, or last_name must be True") self._collect_first_name = first_name self._collect_last_name = last_name self._collect_middle_name = middle_name self._verify_spelling = verify_spelling self._require_confirmation = require_confirmation if is_given(name_format): self._name_format = name_format else: parts = [] if first_name: parts.append("{first_name}") if middle_name: parts.append("{middle_name}") if last_name: parts.append("{last_name}") self._name_format = " ".join(parts) spelling_instructions = ( "" if not verify_spelling else ( "After receiving the name, always verify the spelling by asking the user to confirm " "or spell out the name letter by letter. " "When confirming, spell out each name part letter by letter to the user. " ) ) confirmation_instructions = ( "Call `confirm_name` after the user confirmed the name is correct." ) extra = extra_instructions if extra_instructions else "" super().__init__( instructions=Instructions( _BASE_INSTRUCTIONS.format( name_format=self._name_format, modality_specific=_AUDIO_SPECIFIC, spelling_instructions=spelling_instructions, confirmation_instructions=( confirmation_instructions if require_confirmation is not False else "" ), extra_instructions=extra, ), text=_BASE_INSTRUCTIONS.format( name_format=self._name_format, modality_specific=_TEXT_SPECIFIC, spelling_instructions=spelling_instructions, confirmation_instructions=( confirmation_instructions if require_confirmation is True else "" ), extra_instructions=extra, ), ), chat_ctx=chat_ctx, turn_detection=turn_detection, tools=tools or [], stt=stt, vad=vad, llm=llm, tts=tts, allow_interruptions=allow_interruptions, ) self._first_name: str = "" self._middle_name: str = "" self._last_name: str = "" async def on_enter(self) -> None: self.session.generate_reply( instructions=f"Ask the user for their name, follow this order '{self._name_format}' but do not mention the format." ) @function_tool() async def update_name( self, ctx: RunContext, first_name: str | None = None, middle_name: str | None = None, last_name: str | None = None, ) -> str | None: """Update the name provided by the user. Args: first_name: The user's first name. middle_name: The user's middle name, if collected. last_name: The user's last name, if collected. """ errors: list[str] = [] if self._collect_first_name and not (first_name and first_name.strip()): errors.append("first name is required but was not provided") if self._collect_middle_name and not (middle_name and middle_name.strip()): errors.append("middle name is required but was not provided") if self._collect_last_name and not (last_name and last_name.strip()): errors.append("last name is required but was not provided") if errors: raise ToolError(f"Incomplete name: {'; '.join(errors)}") self._first_name = first_name.strip() if first_name else "" self._middle_name = middle_name.strip() if middle_name else "" self._last_name = last_name.strip() if last_name else "" full_name = self._name_format.format( first_name=self._first_name, middle_name=self._middle_name, last_name=self._last_name, ).strip() if not self._confirmation_required(ctx): if not self.done(): self.complete( GetNameResult( first_name=self._first_name if self._collect_first_name else None, middle_name=self._middle_name if self._collect_middle_name else None, last_name=self._last_name if self._collect_last_name else None, ) ) return None confirm_tool = self._build_confirm_tool( first_name=self._first_name, middle_name=self._middle_name, last_name=self._last_name, ) current_tools = [t for t in self.tools if t.id != "confirm_name"] current_tools.append(confirm_tool) await self.update_tools(current_tools) if self._verify_spelling: return ( f"The name has been updated to {full_name}\n" f"Spell out the name letter by letter for verification: {full_name}\n" f"Prompt the user for confirmation, do not call `confirm_name` directly" ) return ( f"The name has been updated to {full_name}\n" f"Repeat the name back to the user and prompt for confirmation, " f"do not call `confirm_name` directly" ) def _build_confirm_tool( self, *, first_name: str, middle_name: str, last_name: str ) -> llm.FunctionTool: @function_tool() async def confirm_name() -> None: """Call after the user confirms the name is correct.""" if ( first_name != self._first_name or middle_name != self._middle_name or last_name != self._last_name ): self.session.generate_reply( instructions="The name has changed since confirmation was requested, ask the user to confirm the updated name." ) return if not self.done(): self.complete( GetNameResult( first_name=self._first_name if self._collect_first_name else None, middle_name=self._middle_name if self._collect_middle_name else None, last_name=self._last_name if self._collect_last_name else None, ) ) return confirm_name @function_tool(flags=ToolFlag.IGNORE_ON_ENTER) async def decline_name_capture(self, reason: str) -> None: """Handles the case when the user explicitly declines to provide their name. Args: reason: A short explanation of why the user declined to provide their name """ if not self.done(): self.complete(ToolError(f"couldn't get the name: {reason}")) def _confirmation_required(self, ctx: RunContext) -> bool: if is_given(self._require_confirmation): return self._require_confirmation return ctx.speech_handle.input_details.modality == "audio"Abstract base class for generic types.
On Python 3.12 and newer, generic classes implicitly inherit from Generic when they declare a parameter list after the class's name::
class Mapping[KT, VT]: def __getitem__(self, key: KT) -> VT: ... # Etc.On older versions of Python, however, generic classes have to explicitly inherit from Generic.
After a class has been declared to be generic, it can then be used as follows::
def lookup_name[KT, VT](mapping: Mapping[KT, VT], key: KT, default: VT) -> VT: try: return mapping[key] except KeyError: return defaultAncestors
- livekit.agents.voice.agent.AgentTask
- livekit.agents.voice.agent.Agent
- typing.Generic
Methods
async def decline_name_capture(self, reason: str) ‑> None-
Expand source code
@function_tool(flags=ToolFlag.IGNORE_ON_ENTER) async def decline_name_capture(self, reason: str) -> None: """Handles the case when the user explicitly declines to provide their name. Args: reason: A short explanation of why the user declined to provide their name """ if not self.done(): self.complete(ToolError(f"couldn't get the name: {reason}"))Handles the case when the user explicitly declines to provide their name.
Args
reason- A short explanation of why the user declined to provide their name
async def on_enter(self) ‑> None-
Expand source code
async def on_enter(self) -> None: self.session.generate_reply( instructions=f"Ask the user for their name, follow this order '{self._name_format}' but do not mention the format." )Called when the task is entered
async def update_name(self,
ctx: RunContext,
first_name: str | None = None,
middle_name: str | None = None,
last_name: str | None = None) ‑> str | None-
Expand source code
@function_tool() async def update_name( self, ctx: RunContext, first_name: str | None = None, middle_name: str | None = None, last_name: str | None = None, ) -> str | None: """Update the name provided by the user. Args: first_name: The user's first name. middle_name: The user's middle name, if collected. last_name: The user's last name, if collected. """ errors: list[str] = [] if self._collect_first_name and not (first_name and first_name.strip()): errors.append("first name is required but was not provided") if self._collect_middle_name and not (middle_name and middle_name.strip()): errors.append("middle name is required but was not provided") if self._collect_last_name and not (last_name and last_name.strip()): errors.append("last name is required but was not provided") if errors: raise ToolError(f"Incomplete name: {'; '.join(errors)}") self._first_name = first_name.strip() if first_name else "" self._middle_name = middle_name.strip() if middle_name else "" self._last_name = last_name.strip() if last_name else "" full_name = self._name_format.format( first_name=self._first_name, middle_name=self._middle_name, last_name=self._last_name, ).strip() if not self._confirmation_required(ctx): if not self.done(): self.complete( GetNameResult( first_name=self._first_name if self._collect_first_name else None, middle_name=self._middle_name if self._collect_middle_name else None, last_name=self._last_name if self._collect_last_name else None, ) ) return None confirm_tool = self._build_confirm_tool( first_name=self._first_name, middle_name=self._middle_name, last_name=self._last_name, ) current_tools = [t for t in self.tools if t.id != "confirm_name"] current_tools.append(confirm_tool) await self.update_tools(current_tools) if self._verify_spelling: return ( f"The name has been updated to {full_name}\n" f"Spell out the name letter by letter for verification: {full_name}\n" f"Prompt the user for confirmation, do not call `confirm_name` directly" ) return ( f"The name has been updated to {full_name}\n" f"Repeat the name back to the user and prompt for confirmation, " f"do not call `confirm_name` directly" )Update the name provided by the user.
Args
first_name- The user's first name.
middle_name- The user's middle name, if collected.
last_name- The user's last name, if collected.