Skip to main content
You have: Robin that knows the date and the caller’s number, from Know the time. The caller goes quiet, and the agent checks they are still there, then lets them go.

What you add

All the settings live in the shared package, so both frameworks use the same ones.
salon/agent.py
  1. PACE is one of snappy, balanced or patient. It says how long the agent waits after the caller pauses.
  2. IdleNudges is a quiet caller’s script: a nudge after 20 seconds, a second after 15 more, and a hang-up after 10 more. Code says these lines. The model is not asked.
  3. MAX_DURATION_S is the longest a call may run. Here it is 15 minutes.
  4. END_CALL is what the model reads about when to hang up. The example’s text names a real failure: a tired question must not end the call.
Now wire them into each framework. The turn window turns the pace into that framework’s own timing.
The model says its goodbye in the same reply as the end-call tool. The call then ends after one model request.

Try it

Start the agent as before.
  1. Say “Hello” and then stay silent. After about 20 seconds you should hear “Are you still there?”
  2. Stay silent again. You should hear the second line, then the goodbye line, and the call ends.
  3. On a new call, ask “Can you tell me my appointment time?” Robin answers, and the call does not end.
  4. Say “No, that’s all, goodbye.” Robin says goodbye and hangs up.

Why it works this way

LiveKit and Pipecat time a caller’s pause in different ways. One pace name gives each framework its own matching settings, so a caller is paused the same way on both. The idle timer runs only while the agent listens, so it never asks “are you there?” during its own slow tool. A call limit stops a call that would run for hours.

What you have now

Next: See every call

Send one Langfuse trace for each call.
Go deeper: Turn taking and Call lifecycle.