Is there an api to fetch session details
# ask-ai
f
Is there an api to fetch session details
t
Thanks for reaching out, Palwisha. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I can help with that. You're asking whether there's an API to fetch session details; yes, LiveKit provides ways to retrieve room/session and participant information. What you can use • Server SDKs (Go, JavaScript/TypeScript, Kotlin, Ruby, etc.) expose a RoomService-like API to list participants and inspect room state. Use the
RoomServiceClient
(or the equivalent in your chosen SDK) to list participants and get room metadata — this gives you the core session details. • For agent sessions with observability enabled, the LiveKit Cloud Dashboard exposes session recordings, traces, transcripts, and logs. Those observability artifacts can be viewed in the dashboard or downloaded as JSON. To help further • Which language or SDK are you using (Go, JS/TS, Kotlin, Ruby, etc.)? • Do you need participant lists, room metadata, connection states, or the observability artifacts (recording/transcript/logs)? • Are you looking for a server-side API call or a client-side method? If you tell me your SDK/language and the exact session fields you need, I’ll give a short code example or the exact method to call. Sources: livekit/livekit_composite | DeepWiki | Streamline troubleshooting with Agent Observability | Where to find your Agent Logs | LiveKit
f
python
api call to make from server
t
Thanks — I’ll show the exact server-side API calls in Python to fetch room (session) details and participants using the LiveKit Server SDK. Prerequisites • Install the server SDK:
pip install livekit-api
• Have your LiveKit URL, API key, and API secret available. Example: async Python usage (recommended)
Copy code
import asyncio
from livekit import api

async def fetch_session_details():
    client = api.LiveKitAPI(
        url="<https://your-livekit-instance.com>",
        api_key="your-api-key",
        api_secret="your-api-secret"
    )

    # List all active rooms (sessions)
    rooms = await client.room.list_rooms()
    for r in rooms:
        print(f"Room: {r.name}, SID: {r.sid}, Num participants: {len(r.participants)}")

    # Get a specific room by name
    room_name = "my-room-name"
    room_info = await client.room.get_room(room_name=room_name)
    print("Room metadata:", room_info.metadata)
    print("Room created at:", room_info.created_at)

    # List participants in that room
    participants = await client.room.list_participants(room_name=room_name)
    for p in participants:
        print(f"Participant: {p.identity}, State: {p.state}, SID: {p.sid}, Metadata: {p.metadata}")

    # Get a specific participant
    participant = await client.room.get_participant(room_name=room_name, identity="alice")
    print("Participant tracks:", [t.track_sid for t in participant.tracks])

    await client.aclose()

asyncio.run(fetch_session_details())
Synchronous alternative (if you prefer sync code) • The SDK is async-first. If you must run sync, run the async calls inside an event loop (as shown) or use an async runner wrapper. Which fields you can get • Room properties: name, sid, metadata, created_at, participants list, etc. • Participant properties: identity, sid, state, metadata, tracks, etc. Questions to help me tailor this • Do you want a minimal snippet for a single endpoint (e.g., get_room + list_participants) to plug into your server? • Are you running inside a framework (FastAPI, Django) where I should show an endpoint example? • Do you need observability artifacts (recordings, transcripts) instead of realtime session state?
f
I am mainly looking for trancripts
t
Thanks — I’m responding to your request about getting transcripts from sessions in Python. Short answer • Transcripts are available via LiveKit’s Agent Observability (session transcripts, logs, audio). You can view and download them from the LiveKit Cloud Dashboard for completed agent sessions. • There is no documented server-side API in the provided sources that explicitly returns session transcripts via the Python Server SDK. However, you can get transcripts in real time inside your agent code using the transcription events. What you can do right now 1) Download post-session transcripts (dashboard) • If observability is enabled for the agent/project, open the session in the LiveKit Cloud Dashboard under Agent insights and download the transcript, audio, and logs as JSON or text. 2) Receive transcripts in real time from your agent (Python) • Subscribe to the transcription events in your agent runtime to get user speech as it is transcribed. Example event handler pattern:
Copy code
@session.on("user_input_transcribed")
def on_transcript(transcript):
    if transcript.is_final:
        print("Final transcript:", transcript.transcript)
This gives you immediate access to final transcript turns during the session. 3) Session recording and retention notes • Observability (recording transcripts/logs/audio) must be enabled in the project’s Data & privacy settings. Recorded data is stored in the US and retained for 30 days. If you need a programmatic POST-session workflow • There is no explicit documented API to fetch transcripts via the Python server SDK in the provided sources. If your goal is automated retrieval after a session, you have two practical options now: ◦ Use the real-time transcription events during the session and store transcripts in your own backend (recommended for automation). ◦ Manually download transcripts from the dashboard for now. Follow-up questions so I can help further • Do you need transcripts in real time (during the call) or only after the session ends? • Are you running agent code where you can handle events like
user_input_transcribed
? If so, I can provide a fuller code example integrated into your agent loop. • If you require automated post-session retrieval, would storing transcripts during the session to your own storage (S3, DB) work for your use case? Tell me which option you prefer and I’ll give the exact Python example or integration steps. Sources: Streamline troubleshooting with Agent Observability | Transcriber | LiveKit Documentation
f
I need when sessions ends: currenly im doing: def save_session_report(ctx, metadata: dict, egress_id: str = None) -> str | None: """Generate session report, POST transcripts, and upload report to S3. Returns the S3 key on success, or None on failure. """ interview_id = metadata.get("interview_id", "unknown") candidate_name = metadata.get("candidate", {}).get("name", "Unknown") try: logger.info(f"[CLEANUP] Generating session report for interview_id={interview_id}") livekit_report_obj = ctx.make_session_report() logger.info("[CLEANUP] Session report object created, serializing...") livekit_report = serialize_object(livekit_report_obj) logger.info(f"[CLEANUP] Session report serialized, events count: " f"{len(livekit_report.get('events', []))}") except AttributeError as e: logger.error(f"[CLEANUP] Failed to create session report (missing attribute): {e}") return None except Exception as e: logger.error(f"[CLEANUP] Failed to serialize session report: {e}", exc_info=True) return None transcript_entries = extract_transcript_entries(livekit_report) logger.info(f"[CLEANUP] Extracted {len(transcript_entries)} transcript entries") if transcript_entries: logger.info(f"[CLEANUP] Posting {len(transcript_entries)} transcripts to backend...") post_transcripts_to_backend(interview_id, transcript_entries) logger.info("[CLEANUP] Transcripts posted") else: logger.warning("[CLEANUP] No transcript entries found to post") where: def extract_transcript_entries(livekit_report: dict) -> list[dict]: """Extract transcript entries from a serialized LiveKit session report.""" transcript_entries = [] events = livekit_report.get("events", []) for event in events: if event.get("type") != "conversation_item_added": continue item = event.get("item", {}) if item.get("type") != "message": continue role = item.get("role", "") content_parts = item.get("content", []) content = " ".join(str(c) for c in content_parts if c) if not content.strip(): continue speaker = "interviewer" if role == "assistant" else "candidate" created_at = item.get("created_at", 0) timestamp_ms = int(created_at * 1000) if created_at else 0 transcript_entries.append( { "speaker": speaker, "timestamp_ms": timestamp_ms, "text": content, } ) return transcript_entries but i want to fetch from session as well
t
Thanks — I see you already generate a session report with
ctx.make_session_report()
and extract/post transcripts from that serialized report. You want to additionally fetch transcripts from the session after it ends. Short answer • Post-session transcripts are available via Agent Observability in the LiveKit Cloud Dashboard (you can view/download JSON there). • There is no documented server-side API in the provided sources that directly returns session transcripts via the Python Server SDK. • Best practical solutions: 1) persist transcripts during the session (recommended), or 2) rely on the dashboard/manual download for post-session artifacts. I’ll show how to implement option (1) and how to adapt your existing code to use transcripts produced during the session. Recommended approaches 1) Capture and store transcripts during the session (recommended) • Subscribe to the transcription event in your agent runtime and write transcript turns to your backend or S3 as they arrive. This gives you an automated post-session transcript without needing a separate API call after the session ends. • Example pattern (integrate into your agent session code):
Copy code
# Pseudocode/event handler style
@session.on("user_input_transcribed")
def on_transcript(transcript):
    # Only save final transcripts, to avoid partial fragments
    if transcript.is_final:
        entry = {
            "speaker": "candidate" if transcript.source == "user" else "interviewer",
            "timestamp_ms": int(transcript.created_at * 1000) if transcript.created_at else 0,
            "text": transcript.transcript,
        }
        save_transcript_entry_to_db_or_s3(interview_id, entry)
• Advantages: immediate, reliable, and automatable. You control retention and export format. 2) Continue using
ctx.make_session_report()
but ensure observability/recording is enabled • Your existing flow that calls
ctx.make_session_report()
and then
serialize_object(...)
already pulls transcript-like conversation events from the session report. • Ensure observability (recording) is enabled in project Data & privacy settings so that session events and transcripts are captured. Recorded observability data is stored for 30 days. • If
make_session_report()
reliably returns the events you need, keep your
extract_transcript_entries
logic but consider persisting the output immediately in your cleanup path (you’re already posting to backend — this is consistent). 3) Dashboard download / manual retrieval • For occasional or manual workflows, you can open the session in the LiveKit Cloud Dashboard under Agent insights and download transcripts, audio, and logs as JSON/text. • This is not automated and doesn’t suit fully automatic post-session workflows. Notes about APIs and egress • The provided sources do not document a Python Server SDK API that returns session transcripts directly after session end. If automated post-session retrieval via an API is essential, you can: ◦ Store transcripts in your backend during the session (approach #1). ◦ Or, if you enable egress/export to your own storage (planned/available for some flows), you can pull artifacts from that storage. Watch for export/egress features to be available for automated post-session retrieval. Suggested changes to your current save_session_report flow • If you prefer the session-report approach, make sure you: a. Enable observability (recording) for the project/agent so
make_session_report()
contains transcript events. b. Immediately persist the serialized report or the extracted transcript entries to your storage (S3/DB) inside your
save_session_report
so you don’t rely on manual dashboard downloads. c. Optionally combine both approaches: persist real-time transcripts as they arrive and still generate the session report at the end as a secondary verification/source of truth. Follow-up questions so I can give copy-paste code • Do you have access to the agent runtime to add the
user_input_transcribed
handler (real-time capture)? If yes, I can provide a ready-to-use Python snippet that saves to S3. • Do you want the transcript entries saved as one JSON file per session, or as per-turn records in a database? • Is observability/recording currently enabled for your project? If not, do you want steps to enable it? Tell me which option you prefer and I’ll provide the exact Python example to integrate with your current cleanup flow.
f
can you tell how to update them
t
Thanks — I’ll walk you through concrete, copy‑pasteable changes to update your flow so transcripts are reliably captured and persisted when a session ends. I’ll cover two complementary options you can apply together: (A) capture transcripts in real time (recommended) and (B) make your end-of-session
save_session_report
more robust so it always saves transcripts even if some events are missing. Before you start • Ensure Agent Observability / recording is enabled in your project’s Data & privacy settings so session events are captured and the final session report includes conversation events. Recorded data is retained for 30 days. A. Capture transcripts in real time (recommended) Why: This guarantees you have a machine-readable transcript saved automatically even if report generation later misses something. Store each final turn to S3 or your DB as it arrives. 1) Add a handler in your agent runtime for the transcription event (server-side Python). • Listen for the
user_input_transcribed
or equivalent transcription event. • Save final transcript turns immediately. Example (outline you can adapt to your agent framework):
Copy code
def handle_transcript_event(session, interview_id, transcript):
    # Only keep final transcript fragments
    if not getattr(transcript, "is_final", False):
        return

    speaker = "candidate" if getattr(transcript, "source", "") == "user" else "interviewer"
    timestamp_ms = int(getattr(transcript, "created_at", 0) * 1000) if getattr(transcript, "created_at", None) else 0
    entry = {
        "speaker": speaker,
        "timestamp_ms": timestamp_ms,
        "text": getattr(transcript, "transcript", "").strip(),
    }
    if entry["text"]:
        save_transcript_entry(interview_id, entry)  # implement below

# Example subscription (replace with your session framework)
@session.on("user_input_transcribed")
def on_user_input_transcribed(transcript):
    handle_transcript_event(session, interview_id, transcript)
2) Implement
save_transcript_entry
to persist to S3 or DB. • Option: append to an in-memory list per-session and flush on end; or immediately upload/append to S3 (e.g., JSONL) per final turn. Simple JSONL append to S3 approach:
Copy code
import json
import boto3
from botocore.exceptions import BotoCoreError, ClientError

s3 = boto3.client("s3")
BUCKET = "your-bucket"
PREFIX = "transcripts/"

def s3_append_jsonl(interview_id, entry):
    key = f"{PREFIX}{interview_id}.jsonl"
    line = json.dumps(entry) + "\n"
    try:
        # Try to fetch existing object and append (simple approach - works for small files)
        existing = None
        try:
            resp = s3.get_object(Bucket=BUCKET, Key=key)
            existing = resp["Body"].read()
        except ClientError as e:
            # object may not exist; will create new
            existing = None

        if existing:
            data = existing + line.encode("utf-8")
            s3.put_object(Bucket=BUCKET, Key=key, Body=data)
        else:
            s3.put_object(Bucket=BUCKET, Key=key, Body=line.encode("utf-8"))
    except (BotoCoreError, ClientError) as e:
        logger.error("Failed to append transcript to S3: %s", e)
Notes: • For high throughput, use multipart uploads or write to a DB; avoid repeatedly reading/writing the whole object. • You can also buffer entries in memory and flush on session end. B. Strengthen your end-of-session save_session_report Why: Keep your existing report generation but make it detect missing transcripts and consolidate with the real-time saved transcripts. 1) Update save_session_report to: • Generate the LiveKit report as you do. • Extract events as you already do. • If no events or few transcripts found, fallback to the transcripts you persisted during the session (S3/DB). • Combine both sources and dedupe by timestamp or text. Updated flow (pseudo-code):
Copy code
def save_session_report(ctx, metadata: dict, egress_id: str = None) -> str | None:
    interview_id = metadata.get("interview_id", "unknown")
    try:
        livekit_report_obj = ctx.make_session_report()
        livekit_report = serialize_object(livekit_report_obj)
    except AttributeError as e:
        logger.error("Failed to create session report (missing attribute): %s", e)
        return None
    except Exception as e:
        logger.error("Failed to serialize session report: %s", e, exc_info=True)
        return None

    transcript_entries = extract_transcript_entries(livekit_report)
    <http://logger.info|logger.info>("Extracted %d transcript entries from session report", len(transcript_entries))

    # Fallback: load persisted real-time transcripts from S3/DB if empty or incomplete
    if not transcript_entries:
        <http://logger.info|logger.info>("No transcripts in session report; loading persisted transcripts as fallback")
        persisted = load_persisted_transcripts(interview_id)  # implement this
        transcript_entries = persisted or []

    # Optionally merge and dedupe both sources
    persisted = load_persisted_transcripts(interview_id)
    if persisted:
        combined = merge_and_dedupe_transcripts(transcript_entries, persisted)
    else:
        combined = transcript_entries

    if combined:
        <http://logger.info|logger.info>("Posting %d transcripts to backend...", len(combined))
        post_transcripts_to_backend(interview_id, combined)
        <http://logger.info|logger.info>("Transcripts posted")
    else:
        logger.warning("No transcript entries found to post")

    # serialize and upload full session report as well
    s3_key = upload_report_to_s3(interview_id, livekit_report, egress_id)
    return s3_key
2) Implement
load_persisted_transcripts
and
merge_and_dedupe_transcripts
•
load_persisted_transcripts(interview_id)
should read your S3/DB JSONL or JSON file and return a list of entries. •
merge_and_dedupe_transcripts(a, b)
should merge lists and remove duplicates by (timestamp_ms, speaker, text) or by fuzzy text match if needed. Example merge:
Copy code
def merge_and_dedupe_transcripts(a, b):
    seen = set()
    merged = []
    for entry in (a or []) + (b or []):
        key = (entry.get("timestamp_ms"), entry.get("speaker"), entry.get("text"))
        if key in seen:
            continue
        seen.add(key)
        merged.append(entry)
    merged.sort(key=lambda e: e.get("timestamp_ms", 0))
    return merged
C. Additional best practices • Prefer storing transcripts to your own durable store during the session. That’s the most reliable automation path. • Keep per-session transcript file naming stable (e.g., transcripts/{interview_id}.jsonl) so your end-of-session job can always find it. • If you must rely only on
ctx.make_session_report()
, ensure observability/recording is turned on and test that sample sessions produce the expected
conversation_item_added
events. • Use a consistent timezone/epoch handling: store timestamps as UTC ms since epoch. Questions so I can give a tailored, ready-to-run snippet • Which persistence do you prefer for real-time entries: S3 (JSONL), RDS/SQL, or a document DB (DynamoDB/Mongo)? • Are you using an agent framework where you can add
@session.on("user_input_transcribed")
handlers? If yes, tell me how transcripts are represented (attributes), and I’ll produce exact code for saving to S3 and for the fallback load function. • Do you want a full example that replaces your S3 append with a safer approach (e.g., buffer + batch upload) for production? Tell me your preferred storage and I’ll give the exact complete code to plug into your current flow.