Skip to main content

Prerequisites

You will need:
This guide explains how to measure the Time to First Agent Response for conversations handed off to a human agent via Human-in-the-Loop (HITL). The metric captures how long a user waited from the moment they requested a human agent to the moment an agent was assigned. The result is stored as a formatted string in a conversation variable and can be sent using a Text Card, sent to an external system, or saved to a Botpress table.

1. Create conversation variables

Create the following two variables in your bot, scoped as Conversation variables:
Variable NameTypeDescription
hitlRequestTimestampnumberUnix timestamp (ms) of when the HITL request was made
hitlTimingDisplaystringFormatted summary string of the timing result
In Botpress Studio, go to Variables+ New Variable, set the scope to Conversation, and configure each entry as described above.

2. Capture the request timestamp

Before your Start HITL Card, insert an Execute Code Card that records when the user was handed off to HITL. Use the following code:
conversation.hitlRequestTimestamp = Date.now()
This stores the exact moment the user was handed off to HITL, in milliseconds since the Unix Epoch.
The Unix Epoch is January 1, 1970 at 00:00:00 UTC. Timestamps in “milliseconds since the Unix epoch” are the number of milliseconds elapsed since that moment.

3. Calculate and format the wait time

After your Start HITL Card, insert another Execute Code Card that computes the time until an agent was assigned and formats the result. Use the following code:
const { conversation: upstream } = await client.getConversation({ id: event.conversationId })
const downstreamConvId = upstream.tags?.['hitl#downstream']

if (downstreamConvId) {
  const { conversation: downstream } = await client.getConversation({ id: downstreamConvId })
  const assignedAtMs = parseInt(downstream.tags?.['hitl:assignedAt'] || '0')

  if (assignedAtMs) {
    const requestTime = new Date(conversation.hitlRequestTimestamp)
    const assignedTime = new Date(assignedAtMs)

    const diffMs = assignedAtMs - Number(conversation.hitlRequestTimestamp)
    const diffMins = Math.floor(diffMs / 60000)
    const diffSecs = Math.floor((diffMs % 60000) / 1000)

    const fmt = (d) =>
      d.toLocaleTimeString('en-US', {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        hour12: true,
        timeZone: 'America/New_York'
      })

    conversation.hitlTimingDisplay =
      `HITL Request Time: ${fmt(requestTime)}\n` +
      `HITL Assignment Time: ${fmt(assignedTime)}\n` +
      `Wait Time: ${diffMins}m ${diffSecs}s`
  }
}
What this code does:
  • Fetches the upstream conversation using the current conversation ID.
  • Resolves the downstream HITL conversation via the hitl#downstream tag (set automatically by Botpress when a handoff is initiated).
  • Reads the hitl:assignedAt tag from the downstream conversation (timestamp of when an agent accepted and assigned).
  • Computes the wait time between the request and assignment.
  • Formats and stores the result in conversation.hitlTimingDisplay.
Once the code runs, conversation.hitlTimingDisplay will contain a message in this format:
HITL Request Time: 8:28:07 PM
HITL Assignment Time: 8:28:31 PM
Wait Time: 0m 24s
Times are displayed in the America/New_York timezone. Update the timeZone value in the fmt function if your team operates in a different timezone.

4. Use the data

The conversation.hitlTimingDisplay variable is available for the rest of your Workflow. You can:
  • Display it in chat: Add a Text Card and reference {{conversation.hitlTimingDisplay}} to send the summary to the conversation (useful for testing and QA).
  • Log it to a Botpress Table: Use an Update Table Row or Insert Table Row Card to persist the data for reporting.
  • Send it to an external system: Use an Execute Code Card with an axios or fetch call to forward the values to your analytics platform, CRM, or data warehouse.
You can now measure Time to First Agent Response for HITL conversations and use the result in your bot Workflows, tables, or external systems.
Last modified on March 18, 2026