how to get egress id from agent
# ask-ai
c
how to get egress id from agent
t
Thanks for reaching out, Sai. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about how to get an egress ID from an agent. Short answer: the agent does not generate or inherently hold the egress ID. You must either capture the egress_id when you start egress via the server SDK (EgressClient) or query the server for active egress sessions and correlate them to the agent/room. How to do that (options): • Start egress and capture the ID a. Use the server SDK’s EgressClient to start the egress (room composite, track, etc.). b. The start call returns an object containing
egress_id
. Store that ID for later use. Example (Python):
Copy code
info = await lkapi.egress.start_room_composite(RoomCompositeEgressRequest(room_name="my-room", layout="speaker-dark"))
  print("Egress ID:", info.egress_id)
• Associate egress to the agent via metadata ◦ When creating an agent dispatch, include room or purpose metadata so the agent can correlate actions to that room. ◦ In the agent, use the dispatch/context (e.g.,
ctx.room.name
) to match the egress started by the server to the agent’s work. • List active egress sessions and filter by room ◦ Use the server SDK to list ongoing egress (e.g.,
list_egress(room_name="my-room")
) and read each
egress_id
to find the session you need. If you want, tell me: • Which SDK/language you’re using (Python, JS, Go, etc.) • Whether you start egress from your server or trigger it from the agent I’ll provide exact code/snippets or the best pattern to pass/store the egress_id for your flow. Sources: Python SDKs | livekit/livekit_composite | DeepWiki | server-sdk-js | livekit/livekit_composite | DeepWiki | Agent dispatch | LiveKit docs | Outbound Calling Script | LiveKit docs
c
how to get file name
t
Thanks — I’m responding to your question about “how to get file name.” Quick clarifying questions so I can give an exact answer: • Which file do you mean — the egress output file (recording/export), a track file, or an uploaded asset? • Do you start egress from your server or from the agent? • Which SDK/language are you using (Python, JavaScript, Go, REST)? Note: egress filepaths can be specified when starting egress (so you already know the name), and you can also list active egress sessions to inspect their metadata. If you tell me the answers above I’ll provide the precise code/snippet or pattern. Sources: Universal Egress | server-sdk-js | livekit/livekit_composite | DeepWiki
c
egress output file
t
Thanks — you're asking how to get the egress output file name. I can help, but I need one detail to give an exact answer: Which SDK or language are you using to start/manage egress? (Python, JavaScript, Go, or REST) If you already specify the
filepath
when starting egress, that is the output file name — tell me if you need to retrieve the final generated name from EgressInfo after completion or list active egresses, and I’ll provide the exact snippet for your SDK.
c
give me an example
t
You asked for an example to get the egress output file name. Below is a concise Python example showing: • start a room composite egress while specifying
filepath
• capture the returned
egress_id
• poll/list the egress info to read the final output filepath/name Adjust to your SDK client instance and error handling as needed.
Copy code
# Example (Python) — requires LiveKit server SDK client with egress methods
from livekit.api import LiveKitAPI, RoomCompositeEgressRequest
import asyncio
import time

async def start_and_get_output_file(lkapi: LiveKitAPI, room_name: str):
    # 1) Start room composite egress and capture egress_id
    req = RoomCompositeEgressRequest(
        room_name=room_name,
        layout="speaker-dark",
        # Specify the desired output filepath. This determines the file name.
        # Example for local or cloud path depending on your egress sink:
        filepath="recordings/my-room-{room_name}-{time}.mp4"
    )
    info = await lkapi.egress.start_room_composite(req)
    egress_id = info.egress_id
    print("Started egress_id:", egress_id)

    # 2) Poll for completion (or you can use webhook/events instead)
    while True:
        # list_egress or get_egress depending on SDK; using list_egress filtered by room
        egress_list = await lkapi.egress.list_egress(room_name=room_name)
        target = next((e for e in egress_list if e.egress_id == egress_id), None)
        if not target:
            print("Egress not found yet; retrying...")
            time.sleep(2)
            continue

        print("Egress status:", target.status)  # e.g., STARTED, COMPLETED, FAILED
        if target.status == "COMPLETED":
            # The API response includes metadata about outputs. Check fields like `output` or `filepath`
            # Print whichever field holds the final file path/name
            print("Final output filepath:", getattr(target, "filepath", None) or getattr(target, "output", None))
            return getattr(target, "filepath", None) or getattr(target, "output", None)
        if target.status == "FAILED":
            raise RuntimeError(f"Egress failed: {target.error}")
        time.sleep(2)

# Usage example
async def main():
    lkapi = LiveKitAPI()  # initialize with your config/auth
    filepath = await start_and_get_output_file(lkapi, "my-room")
    print("Resolved output file:", filepath)
    await lkapi.aclose()

asyncio.run(main())
Notes: • If you explicitly set
filepath
when starting egress, that is the expected output name/location. • You can also inspect the egress info returned by
list_egress
or
get_egress
for the final output filepath/name once status is
COMPLETED
. • Using webhooks/events to receive the completion payload is more efficient than polling — the completion event typically contains the final output info. Tell me if you want the same example in JavaScript, Go, or using REST/webhook handling.
c
do i always have to stop_egress?
t
You're asking whether you always need to call
stop_egress
. Short answer: no — but sometimes. When you don't need to call
stop_egress
• If the room ends (last participant leaves) or you delete the room, egress will automatically stop and finalize the output. Deleting the room at call end is a recommended pattern to avoid extra silence/extra audio in recordings. When you should call
stop_egress
• You want to end recording/streaming before the room ends. • You only want to record specific segments in a long-running room. • You need precise lifecycle control (manual pause/resume, immediate stop on an event). If you want, tell me which SDK/language you use and your desired lifecycle (e.g., delete room on hangup vs. keep room open), and I’ll give the exact code example for stopping egress or for deleting the room to trigger automatic stop. Sources: server-sdk-js | livekit/livekit_composite | DeepWiki
c
ok that makes sense. but how do I actually like get the filename that stop_egress outputs?
t
You're asking how to get the output filename when you stop egress. Stop the egress and read the returned EgressInfo (or the
egress_ended
webhook) — it contains the final file info. Quick examples: Python
Copy code
info = await lkapi.egress.stop_egress(api.StopEgressRequest(egress_id="EGRESS_ID"))
if info.file_info:
    print("File path:", info.file_info.location)
    print("Download URL:", info.file_info.download_url)
Go
Copy code
info, err := egressClient.StopEgress(ctx, &livekit.StopEgressRequest{EgressId: "EGRESS_ID"})
if err != nil { return err }
if info.FileInfo != nil {
    fmt.Println("File path:", info.FileInfo.Location)
    fmt.Println("Download URL:", info.FileInfo.DownloadUrl)
}
Notes: • If you set
filepath
when starting egress, that is the expected output name. • You can also receive the final
EgressInfo
via the
egress_ended
webhook instead of calling
stop_egress
. Sources: server-sdk-ruby | livekit/livekit_composite | DeepWiki | Python SDKs | livekit/livekit_composite | DeepWiki
c
but if the room ends the egress is automatically stopped. so how do i get the filename then?
t
Good question — when the room ends and egress is stopped automatically, you still get the final file info — just capture it asynchronously rather than from a direct
stop_egress
call. Two reliable ways: • Use the egress_ended webhook (recommended) ◦ LiveKit sends an
egress_ended
event when the egress finishes. The event payload contains the
EgressInfo
including
file_info.location
and
file_info.download_url
. ◦ Implement a webhook endpoint that receives that event and reads the final filename/path from
file_info
. • Query the server SDK after completion ◦ Poll or call
get_egress
/
list_egress
filtered by room or
egress_id
. Once status is
COMPLETED
, read
file_info.location
(and
download_url
). ◦ This is useful if you cannot use webhooks, but webhooks are more efficient. Example webhook handling (conceptual):
Copy code
# On your webhook route receiving egress_ended payload
payload = request.json
egress_info = payload.get("egress_info") or payload.get("data")  # depends on webhook format
file_info = egress_info.get("file_info")
if file_info:
    print("Final file path:", file_info.get("location"))
    print("Download URL:", file_info.get("download_url"))
If you want, tell me whether you prefer a webhook or SDK example and which SDK/language you use (Python, JS, Go, REST) and I’ll provide a concrete snippet.
c
give me python code for egress_ended
t
Below is a concise Python example showing a webhook endpoint that handles the
egress_ended
event, verifies the request signature (optional but recommended), and extracts the final file info (
file_info.location
and
file_info.download_url
). This uses FastAPI and assumes LiveKit sends JSON with an event type and
egress_info
payload. 1) Install requirements: • fastapi • uvicorn • python-dotenv (optional, for loading a secret) 2) Example:
Copy code
# webhook_egress.py
from fastapi import FastAPI, Request, HTTPException
from pydantic import BaseModel
import hmac
import hashlib
import os
import json

app = FastAPI()
# Set LIVEKIT_WEBHOOK_SECRET in env if you want to verify signatures
WEBHOOK_SECRET = os.getenv("LIVEKIT_WEBHOOK_SECRET", None)

class EgressEndedPayload(BaseModel):
    event: str
    egress_info: dict | None = None

def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    # LiveKit webhook signature is HMAC-SHA256 of the raw body using the webhook secret.
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

@app.post("/webhook")
async def handle_webhook(request: Request):
    body = await request.body()
    # Optional signature header name; replace if your setup differs
    signature = request.headers.get("x-livekit-signature", "")

    if WEBHOOK_SECRET:
        if not signature:
            raise HTTPException(status_code=400, detail="Missing signature")
        if not verify_signature(body, signature, WEBHOOK_SECRET):
            raise HTTPException(status_code=401, detail="Invalid signature")

    try:
        payload = json.loads(body)
    except json.JSONDecodeError:
        raise HTTPException(status_code=400, detail="Invalid JSON")

    event_type = payload.get("event") or payload.get("type")  # depends on your LiveKit setup
    if event_type not in ("egress_ended", "EGRESS_ENDED"):
        return {"status": "ignored", "event": event_type}

    # Egress info may be under `egress_info` or `data.egress_info` depending on your webhook format
    egress_info = payload.get("egress_info") or payload.get("data", {}).get("egress_info")
    if not egress_info:
        return {"status": "no_egress_info"}

    # Extract file info
    file_info = egress_info.get("file_info") or egress_info.get("FileInfo")
    if not file_info:
        return {"status": "no_file_info"}

    location = file_info.get("location") or file_info.get("Location")
    download_url = file_info.get("download_url") or file_info.get("DownloadUrl")

    # Do something with the filename/path (store in DB, notify user, start post-processing, etc.)
    print("Egress completed. File location:", location)
    print("Download URL:", download_url)

    return {"status": "ok", "location": location}

# Run with: uvicorn webhook_egress:app --reload --port 8000
Notes: • If you set
filepath
when starting egress, the
file_info.location
will normally contain that path. For cloud sinks you may get an S3/GCS URI; for local sinks it may be a filesystem path. • Confirm your LiveKit webhook payload shape — adjust keys (
event
,
egress_info
,
data
) accordingly. • Use the webhook secret and signature verification in production for security.