This message was deleted.
# ask-ai
s
This message was deleted.
t
Thanks for reaching out, G.. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I can help troubleshoot why
report.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 | DeepWiki
Thanks — this is clear and helpful. I’ll walk you through targeted troubleshooting steps so we can pinpoint why
report.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
).
Thanks — this is helpful context. You’re seeing the TypeScript error because
AgentSession
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:
Copy code
// 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:
Copy code
<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 | LiveKit
Thanks — this is great detail. I’m responding to the logs and code you just shared where you call
ctx.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:
Copy code
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).