CreateDispatch succeeds, but how do we know a worker actually received the job?

Hi everyone, I’m using LiveKit Agent Dispatch for outbound calls. Is there any push-based mechanism or event that indicates a dispatch has been successfully assigned to a worker? My current understanding is that CreateDispatch only confirms dispatch creation, and if no worker ever picks up the job, there doesn’t seem to be a direct way to detect that without implementing our own timeout/watchdog logic. Am I missing something?

Hi, you should be able to use listDispatch and look at the returned jobState.

Thanks @darryncampbell . I got it that but I was looking for a pushed based solution and I think as of now livekit doesn’t have it.

For push you can use webhook that will tell you when a room is create, participant joins, etc.

@mh, To turn the webhook suggestion above into a concrete signal: the dispatched worker joins the room as a participant with kind AGENT, so a participant_joined webhook filtered to that kind is your push confirmation a worker actually took the job [ docs.livekit.io/home/server/webhooks; ParticipantInfo.Kind.AGENT in livekit/protocol]:

from livekit import api
from livekit.protocol import models

receiver = api.WebhookReceiver(api.TokenVerifier(API_KEY, API_SECRET))

@app.post("/livekit/webhook")
async def lk_webhook(req):
    event = receiver.receive((await req.body()).decode(), req.headers["Authorization"])
    if event.event == "participant_joined" and event.participant.kind == models.ParticipantInfo.AGENT:
        # worker accepted the dispatch and joined the room
        on_worker_joined(event.room.name, event.participant.identity)

One honest caveat on the “pure push, no watchdog” goal: push gives you the positive event (a worker joined), but the negative case (nobody ever picks up) can’t be pushed, since an absence isn’t an event. So arm a short timer at CreateDispatch and cancel it when this webhook arrives. The webhook removes the polling, but no-pickup detection still needs that timeout.

That isn’t a LiveKit gap, it’s inherent to event-driven signalling.