Skip to content

Commit 2d4f33a

Browse files
committed
add lk.agent.name attr & wait_for_agent utility (#4670)
1 parent 1e8e72b commit 2d4f33a

4 files changed

Lines changed: 68 additions & 2 deletions

File tree

livekit-agents/livekit/agents/types.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222
```
2323
"""
2424

25+
ATTRIBUTE_AGENT_NAME = "lk.agent.name"
26+
"""
27+
The name of the agent, stored in the agent's attributes.
28+
This is set when the agent joins a room and can be used to identify the agent type.
29+
"""
30+
2531
TOPIC_CHAT = "lk.chat"
2632
TOPIC_TRANSCRIPTION = "lk.transcription"
2733
TOPIC_CLIENT_EVENTS = "lk.agent.events"

livekit-agents/livekit/agents/utils/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .log import log_exceptions
99
from .misc import is_given, nodename, shortuuid, time_ms
1010
from .moving_average import MovingAverage
11-
from .participant import wait_for_participant, wait_for_track_publication
11+
from .participant import wait_for_agent, wait_for_participant, wait_for_track_publication
1212

1313
EventEmitter = rtc.EventEmitter
1414

@@ -33,6 +33,7 @@
3333
"hw",
3434
"is_given",
3535
"ConnectionPool",
36+
"wait_for_agent",
3637
"wait_for_participant",
3738
"wait_for_track_publication",
3839
]

livekit-agents/livekit/agents/utils/participant.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,62 @@
44

55
from livekit import rtc
66

7+
from ..types import ATTRIBUTE_AGENT_NAME
8+
9+
10+
async def wait_for_agent(
11+
room: rtc.Room,
12+
*,
13+
agent_name: str | None = None,
14+
) -> rtc.RemoteParticipant:
15+
"""
16+
Wait for an agent participant to join the room.
17+
18+
Args:
19+
room: The room to wait for the agent in.
20+
agent_name: If provided, waits for an agent with matching lk.agent.name attribute.
21+
If None, returns the first agent participant found.
22+
23+
Returns:
24+
The agent participant.
25+
26+
Raises:
27+
RuntimeError: If the room is not connected.
28+
"""
29+
if not room.isconnected():
30+
raise RuntimeError("room is not connected")
31+
32+
fut: asyncio.Future[rtc.RemoteParticipant] = asyncio.Future()
33+
34+
def matches_agent(p: rtc.RemoteParticipant) -> bool:
35+
if p.kind != rtc.ParticipantKind.PARTICIPANT_KIND_AGENT:
36+
return False
37+
if agent_name is None:
38+
return True
39+
return p.attributes.get(ATTRIBUTE_AGENT_NAME) == agent_name
40+
41+
def on_participant_connected(p: rtc.RemoteParticipant) -> None:
42+
if matches_agent(p) and not fut.done():
43+
fut.set_result(p)
44+
45+
def on_attributes_changed(changed: list[str], p: rtc.Participant) -> None:
46+
if isinstance(p, rtc.RemoteParticipant) and matches_agent(p) and not fut.done():
47+
fut.set_result(p)
48+
49+
room.on("participant_connected", on_participant_connected)
50+
room.on("participant_attributes_changed", on_attributes_changed)
51+
52+
try:
53+
# Check existing participants
54+
for p in room.remote_participants.values():
55+
if matches_agent(p):
56+
return p
57+
58+
return await fut
59+
finally:
60+
room.off("participant_connected", on_participant_connected)
61+
room.off("participant_attributes_changed", on_attributes_changed)
62+
763

864
async def wait_for_participant(
965
room: rtc.Room,

livekit-agents/livekit/agents/worker.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
)
5252
from .log import DEV_LEVEL, logger
5353
from .plugin import Plugin
54-
from .types import NOT_GIVEN, NotGivenOr
54+
from .types import ATTRIBUTE_AGENT_NAME, NOT_GIVEN, NotGivenOr
5555
from .utils import http_server, is_given
5656
from .utils.hw import get_cpu_monitor
5757
from .version import __version__
@@ -1172,6 +1172,9 @@ async def _on_accept(args: JobAcceptArguments) -> None:
11721172
availability_resp.availability.participant_identity = args.identity
11731173
availability_resp.availability.participant_name = args.name
11741174
availability_resp.availability.participant_metadata = args.metadata
1175+
availability_resp.availability.participant_attributes[ATTRIBUTE_AGENT_NAME] = (
1176+
self._agent_name
1177+
)
11751178
if args.attributes:
11761179
availability_resp.availability.participant_attributes.update(args.attributes)
11771180
await self._queue_msg(availability_resp)

0 commit comments

Comments
 (0)