Skip to content
TriedDocs
Monitor

Live monitoring

Watch calls while they happen, listen in silently, take over from the agent, steer the agent, or end the call.

Live Monitoring shows the calls that are in progress right now and streams each one's transcript as it happens. From the same screen you can listen to the audio without being heard, take the call over from the agent, or hang it up.

Use it to supervise a new agent on its first real calls, to step in when a caller needs a person, and to check that tool calls and flow transitions happen when you expect.

Open it from MONITOR > Live Monitoring.

Live Monitoring with the live call list and a streaming transcript

The live call list#

The left column lists calls with call_status ongoing or registered, newest first, and refreshes every 4 seconds. The header shows how many calls are live.

Each entry shows:

  • An icon for web call, inbound phone call or outbound phone call.
  • The agent name, and a Live badge (ongoing) or Connecting badge (registered).
  • The from and to numbers, or "Web call".
  • The call ID and the elapsed time.

The first call is selected automatically. Click another to switch.

Following a call#

The right side shows the selected call: agent name, status badge, call ID with a copy button, numbers and direction, and the elapsed time. Streaming appears while the server is pushing updates.

The transcript feed shows agent and user turns with their time from the call start, plus:

  • Tool Invocation and Tool Result lines for tool calls.
  • Node Transition lines with the new node (conversation flow agents).
  • DTMF digits.
  • A line saying who took over the call, after a take-over.

The feed scrolls with new turns. If you scroll up to read, it stops following; Jump to latest brings you back.

When the call ends, the badge changes to Ended with the disconnection reason, and Open in Call History opens the full record.

Listen#

Listen joins the call as a hidden, subscribe-only participant. You hear the caller and the agent; they cannot hear you and do not see you in the room.

Needs keys

Needs keys Audio listening needs LiveKit. With mock telephony, Listen falls back to transcript mode and you follow the streamed transcript only.

Take over#

Take over removes the agent from the call and connects you to the caller. A confirmation explains that the agent leaves and that this cannot be undone for the call.

A call taken over from Live Monitoring

When you take over:

  • The agent participant is removed from the room and you join with your microphone.
  • disconnection_reason is set to call_take_over right away and kept when the call later ends.
  • metadata.taken_over_by (your email) and metadata.taken_over_at (epoch ms) are added to the call.
  • A transfer item with event: transfer_bridged, destination: dashboard:<your email> and reason: take_over is added to transcript_with_tool_calls.
  • The action is written to the audit log as call.take_over.

Only ongoing calls can be taken over. With mock telephony there is no audio, so a text box appears instead: type what you want to say and press Send. Each message is added to the transcript as an agent turn.

End Call#

End Call hangs up the call after a confirmation. The call ends with disconnection_reason: manual_stopped. This is the same as POST /v2/stop-call/:call_id.

Steering the agent without taking over#

There is no audio whisper to the agent. To change what the agent does on a live call, use PATCH /update-live-call/:call_id:

Field Effect
override_dynamic_variables Merged over the call's dynamic variables. The agent sees them on its next turn.
metadata Merged into the call's metadata.
data_storage_setting Changes how this call's data is stored.
call_control.additional_context Text (up to 5000 characters) added to the agent's context. It appears in the transcript as "Context added during the call".
call_control.trigger_response When true, the agent responds right away instead of waiting for the caller.
curl -X PATCH https://api.tried.com.au/update-live-call/call_7e2f4c1a9b8d0e3f5a6b7c8d \
  -H "Authorization: Bearer $TRIED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"call_control":{"additional_context":"A 3pm slot today just became free. Offer it.","trigger_response":true}}'

It returns 400 when the call has already ended.

Limits and permissions#

  • Viewers: at most 5 people watch one live call at a time, counting both transcript streams and Listen. A person with several connections counts once. The sixth person gets HTTP 429 ("This call already has 5 viewers"). With REDIS_URL set, the cap holds across API instances.
  • Roles: Listen and Take over need the Admin or Developer role. Members can follow transcripts.
  • Audit: Listen is recorded as call.listen and Take over as call.take_over.
  • Streams stop after 30 minutes or when the call reaches a terminal status.

API#

Endpoint Description
GET /v2/calls/:call_id/stream Server-sent events. Sends event: call with the full call object on every change, then event: end.
GET /v2/calls/:call_id/ws WebSocket with the same data: messages {"event":"call","call":{...}}, then {"event":"end","call_id":"..."}. Send {"type":"ping"} to get {"event":"pong"}.
POST /v2/calls/:call_id/listen Returns mode (audio or transcript), stream_url, livekit_url and access_token.
POST /v2/calls/:call_id/leave Frees your Listen slot.
GET /v2/calls/:call_id/viewers Who is watching: max_viewers and a list of viewers with since and modes.
POST /v2/calls/:call_id/take-over Returns mode (audio or text), livekit_url, access_token and the updated call.
POST /v2/calls/:call_id/supervisor-say After a take-over without audio: { "content": "..." } adds your words to the transcript.
POST /v2/stop-call/:call_id Ends the call (manual_stopped).

Both the stream and the WebSocket check the call for changes every 400 ms (TRIED_MONITOR_POLL_MS sets the WebSocket interval).

The WebSocket authenticates like any other endpoint, with the Authorization: Bearer header (or a dashboard session). Browsers cannot set that header on a WebSocket, so connect from your server.

import WebSocket from "ws";

const ws = new WebSocket(`wss://api.tried.com.au/v2/calls/${callId}/ws`, {
  headers: { Authorization: `Bearer ${process.env.TRIED_API_KEY}` },
});
ws.on("message", (raw) => {
  const msg = JSON.parse(String(raw));
  if (msg.event === "call") console.log(msg.call.call_status, msg.call.transcript_with_tool_calls.length);
  if (msg.event === "end") ws.close();
});