Livekit-agents@1.5.9 Latest

Highlights

:telephone:Answering Machine Detection :telephone:

Introducing the headline feature of 1.5.9: AMD reliably distinguishes humans from machines and classifies every outbound call as human, voicemail, IVR, or unavailable. This feature is available in the core framework with no plugins required.

Read more about it in our blog post or see our docs.

Asynchronous Tools

AsyncToolset lets tools run in the background while the voice agent keeps talking. Here’s an example:

class TravelToolset(AsyncToolset):
    @function_tool
    async def book_flight(self, ctx: AsyncRunContext, origin: str, dest: str) -> str:
        await ctx.update(f"Searching flights from {origin} to {dest}...")
        # agent replies to user that it's searching the flight

        flights = await search_flights(origin, dest)
        await ctx.update(f"Found {len(flights)} options, booking the best one...")
        # agent will update to user when it's idle

        booking = await confirm_booking(flights[0])
        return f"Booked! Confirmation: {booking.id}"
        # final result will also be updated when both user and agent is idle

agent = Agent(tools=[TravelToolset(id="travel")], instructions="...")

Dynamic Tool Discovery

ToolSearchToolset — exposes a tool_search function. Matched tools are added directly to the LLM’s tool list on the next turn, so the model uses native tool calls. Simpler for the model.

ToolProxyToolset — exposes exactly two fixed tools: tool_search (returns schemas) and call_tool (executes by name). The tool list remains unchanged, preserving prompt cache across turns for providers like OpenAI and Anthropic.

Both support:

  • Nested toolsets (MCPToolset), standalone tools, ProviderTool, and RawFunctionTool

  • Atomic toolset loading: if a tool picked belongs to a nested toolset, the whole toolset is loaded.

  • Pluggable search via SearchStrategy protocol

  • Built-in keywod and BM25 search strategy

See an example here: https://github.com/livekit/agents/blob/main/examples/voice_agents/tool_search_agent.py

Plugin Additions

Here are the newest plugins additions since 1.5.0:

  • STT: Inworld, Simplismart, SLNG, xAI

  • LLM: Perplexity,

  • TTS: Mistral AI, Rime Streaming, SLNG, SmallestAI, Soniox

  • Realtime: NVIDIA

  • Avatar: Runway

Deprecations

The Hedra plugin has been deprecated. Please browse our other avatar integrations instead at https://docs.livekit.io/agents/models/avatar/.

Changelog

New Contributors

Full Changelog: https://github.com/livekit/agents/compare/livekit-agents@1.5.8…livekit-agents@1.5.9

Cc: @CWilson Great update.

Two practical notes for adopters:

  • AsyncToolset is the framework-native version of the session.say("checking that for you...") filler-while-tool-runs pattern that keeps coming up on voice-agent latency threads. Before 1.5.9 you had to manually fire a holding line right before a slow tool call, then return the real result whenever the LLM finished. ctx.update() does it natively and the framework picks the moment to deliver each update (“when the agent is idle”). Direct replacement for the perceived-latency workaround.
  • ToolProxyToolset’s prompt-cache angle is the real engineering win for agents with large tool catalogs. Each turn that injects different tool schemas into the prompt invalidates the provider’s cache. ToolProxyToolset keeps the offered tool list stable (just tool_search + call_tool), so OpenAI and Anthropic prompt-cache hits survive across turns. On a 50+ tool agent, that is a meaningful LLM-cost reduction, not just a UX nicety.

Also worth noting #5698 (fix: do not republish tracks on reconnect) lands here for anyone who hit the track-state-after-reconnect issue from earlier this week.