steep-balloon-41261
02/21/2026, 10:50 AMtall-airline-16756
02/21/2026, 10:50 AMtall-airline-16756
02/21/2026, 10:50 AMreport.duration is always empty. I’m responding to your snippet where you call const report = ctx.makeSessionReport(session) inside the Close event handler and then find report.duration is never set.
I don’t have the implementation details for makeSessionReport or the report schema, so I need a few clarifying items to narrow the cause:
1. Which SDK / codebase and version are you using for ctx.makeSessionReport? (library name + version or commit)
2. Where is makeSessionReport implemented in your codebase? Can you share the function (or a short excerpt) that populates the report fields?
3. Does the session object contain start/end timestamps or other timing fields before you call makeSessionReport? For example, what are the values of session.startTime, session.endTime, or similar right before the call?
4. Do you ever call makeSessionReport at other lifecycle points (e.g., on Pause, End, or after explicit teardown)? If yes, does duration appear then?
5. Is anything asynchronous finishing after the Close event that could set timestamps (e.g., final VAD/STT/TTS processing)? If so, are you waiting for those to complete before generating the report?
While you gather that info, here are immediate checks that commonly reveal the issue:
• Confirm session timestamps: Log the session’s start and end timestamps immediately before makeSessionReport(session). If end or endTime is missing, duration can’t be computed.
◦ Example: <http://logger.info|logger.info>({ start: session.startTime, end: session.endTime })
• Ensure finalization happens before report creation: Some flows emit Close before all timers or final events are written. If your code relies on an async teardown or a “session ended” flag set later, generate the report after those complete.
• Inspect makeSessionReport logic: If makeSessionReport computes duration as end - start, ensure it checks the same timestamp fields present on session. There may be a mismatch in names (e.g., startedAt vs startTime).
• Race condition: If Close fires early, try delaying the report briefly (or better, await any promise that marks session completion) to see if duration appears:
◦ Quick test: await new Promise(r => setTimeout(r, 250)); const report = ctx.makeSessionReport(session)
If you paste the makeSessionReport function or the session fields’ contents right before the call, I can point to the exact line that should compute duration or suggest a fix.
Sources: Agent session | LiveKit Documentation | TTS Metrics | LiveKit Documentation | Streamline troubleshooting with Agent Observability | Agents (Python) | livekit/livekit_composite | DeepWikitall-airline-16756
02/21/2026, 10:53 AMreport.duration is never set.
First, quick acknowledgement: you call ctx.makeSessionReport(session) inside the AgentSessionEventTypes.Close handler and report.duration is always falsy. That suggests the report generator doesn’t see the start/end timing it needs (or it runs before those times are set).
Please provide these quick facts so I can give a precise fix:
• Which SDK/package and version provides ctx.makeSessionReport (package name + version)?
• Can you paste the implementation of makeSessionReport (or the module/file where it’s defined)?
• Right before const report = ctx.makeSessionReport(session), what properties exist on session? Please run and paste the output of:
◦ <http://logger.info|logger.info>({ start: session.startTime, end: session.endTime, startedAt: session.startedAt, endedAt: session.endedAt, timestamps: session.timestamps })
◦ Or simply: <http://logger.info|logger.info>({ session }) (if safe to share).
• Do you perform any async cleanup after Close (e.g., awaiting final STT/TTS/VAD callbacks)? If so, do those set end timestamps after Close fires?
While you gather that, try these focused checks (each is quick to run and will reveal the likely cause):
1) Confirm session timestamps exist
• Add logging immediately before making the report:
◦ <http://logger.info|logger.info>('session times', { start: session.startTime, end: session.endTime, startedAt: session.startedAt, endedAt: session.endedAt })
• If both start and end are undefined or end is missing, duration can’t be computed.
2) Check for a race (Close fires before final timestamps)
• Temporarily delay report creation to test:
◦ await new Promise(r => setTimeout(r, 250)); const report = ctx.makeSessionReport(session)
• If duration appears after a short wait, you have a race: some component sets session end time after Close triggers.
3) Verify makeSessionReport’s field names match session fields
• If makeSessionReport computes duration as `session.startedAt`/`session.endedAt` but your session uses `startTime`/`endTime` (or similar), duration will be absent. Share the function and I’ll check for naming mismatches.
4) Ensure Close is the correct lifecycle event to finalize timing
• Some systems emit Close before finalization. If there’s a separate “Ended” or “Finalized” event, try generating the report there or after awaiting the finalizer.
5) Inspect report computation logic
• If possible, find the line that sets report.duration. Common patterns:
◦ report.duration = session.end - session.start
◦ report.duration = session.endedAt ? session.endedAt - session.startedAt : undefined
• If start or end are zero/undefined/NaN, the assignment will leave duration falsy.
If you paste the makeSessionReport code and the session object log, I’ll point out the exact mismatch and provide a minimal code fix (or a safe ordering change to ensure the timestamps are set before you call makeSessionReport).tall-airline-16756
02/21/2026, 10:54 AMAgentSession does not expose an endTime property. I’m responding to your question about why report.duration from ctx.makeSessionReport(session) is never set.
What’s happening
• The session report’s duration is derived from the session’s internal created_at and ended_at timestamps.
• Those timestamps are set when the session lifecycle is finalized. AgentSession itself doesn’t expose an endTime property, so attempting to read session.endTime will fail (TypeScript error you saw).
What to check and quick fixes
1. Ensure the session is properly finalized before generating the report
◦ Use the SDK’s recommended teardown method (for example, session.aclose() or session.shutdown()), or ensure any async finalization has completed before calling ctx.makeSessionReport(session).
◦ Generate the report after the finalizer completes or after an event that guarantees the ended_at timestamp is written.
1. Avoid reading non-existent fields on AgentSession
◦ Instead of session.endTime, rely on the report returned by ctx.makeSessionReport(session) once the session is finalized. The duration will be populated there when created_at and ended_at exist.
1. Test for a race condition
◦ Temporarily delay report creation in the Close handler to check whether timestamps are written slightly after Close fires:
// quick test
await new Promise(r => setTimeout(r, 250));
const report = ctx.makeSessionReport(session);
<http://logger.info|logger.info>('Report after delay', { report });
• If duration appears after the delay, ensure you wait for finalization rather than calling makeSessionReport immediately on Close.
1. Confirm SDK version / compatibility
◦ Some SDK versions populate lifecycle metrics automatically; others require explicit shutdown. Tell me which SDK/package and version you’re using and I’ll confirm whether your version requires an explicit close call to set ended_at.
What I can do next
• If you share the SDK/package + version and a short snippet of how you currently close the session (e.g., do you call session.shutdown() or similar), I’ll recommend the exact ordering or code change to guarantee duration is set.
• If you can paste the ctx.makeSessionReport implementation or the report shape you receive now (JSON), I’ll inspect how duration is computed and point to the exact mismatch or fix.
If you prefer, start by running the quick timestamp log before making the report and paste the output:
<http://logger.info|logger.info>('session timestamps', {
created_at: session.created_at,
ended_at: session.ended_at,
// any other timestamp-like fields on session
});
That will immediately show whether the ended timestamp exists when you call makeSessionReport.
Sources: Agent session | LiveKit Documentation | Where to find your Agent Logs | LiveKittall-airline-16756
02/21/2026, 11:02 AMctx.makeSessionReport(session) from a shutdown callback (with a 2s delay) and the produced report includes startedAt and timestamp but no duration.
Direct answer (why duration is missing)
• The report you logged contains startedAt and timestamp (the report’s fields), but it does not include duration. That means makeSessionReport did not compute or populate duration from those timestamps.
• The SDK you’re using expects the report’s lifecycle timestamps to be finalized (often `created_at`/`ended_at` or `startedAt`/`timestamp`) before computing duration. In your output the report has:
◦ startedAt: 1771671641942
◦ timestamp: 1771671659684
◦ but no duration field was set by makeSessionReport
Immediate actionable checks and fixes 1) Compute duration yourself as a quick reliable workaround
• You already have two timestamps in the report. If timestamp represents the session end, compute duration yourself:
const report = ctx.makeSessionReport(session);
if (!report.duration && report.startedAt && report.timestamp) {
report.duration = report.timestamp - report.startedAt;
}
• Then use report.duration as you planned (e.g., convert to seconds).
2) Confirm what startedAt and timestamp mean
• Based on your log, startedAt looks like session start and timestamp looks like when the report was created/end. If the SDK uses different names internally (e.g., `created_at`/`ended_at`), confirm those mappings. If they map as above, computing duration with timestamp - startedAt is correct.
3) Ensure session is finalized before making the report
• You have a 2s delay in the shutdown callback; that usually helps with races. Since timestamps are present, finalization likely happened — the missing duration suggests either:
◦ makeSessionReport does not auto-compute duration in this codepath, or
◦ a version/implementation detail where duration is only set in certain flows (e.g., when session is closed via session.aclose() / session.shutdown() rather than just on disconnect).
• If your SDK has explicit finalize/close calls (like session.aclose() or session.shutdown()), call/await one of those before generating the report.
4) Check SDK/version behavior
• Some SDK versions populate lifecycle metrics automatically; others require an explicit shutdown to populate ended_at and derived fields. Tell me the SDK/package and version if you want me to confirm expected behavior for your version.
5) Log the raw report fields you rely on
• Add this to verify values: <http://logger.info|logger.info>('raw report fields', { startedAt: report.startedAt, timestamp: report.timestamp, duration: report.duration })
• If you consistently see both timestamps but no duration, computing it locally (step 1) is safe.
Why computing it locally is acceptable
• Duration is simply end minus start. If your report reliably contains startedAt and timestamp representing start and end, calculating duration client-side gives you the value you need immediately while we confirm whether makeSessionReport should have set it.
Next step I can take for you
• If you’d like, paste the SDK/package name + version (or the implementation of ctx.makeSessionReport) and I’ll:
◦ confirm whether that SDK version should populate duration automatically, and
◦ point to the exact place in the flow to await/fix so makeSessionReport sets duration for you.
If you want the quick fix now, add the computation in step 1 and I’ll review any follow-ups (e.g., formatting duration, guarding for NaN).