Participant Model

View as Markdown

Every Call has two parties and one agent. On outbound calls, inbound audio for the remote party is typically on the callee track - selecting the wrong stream is a common integration error.

Parties vs agent

  • Parties: caller (who placed the call) and callee (who was called).
  • One of them is always the subscriber (your connector’s line); the other is the external participant.
  • The agent is your code. It listens via caller / callee .audio_stream() and speaks with send_audio(). It is not a third party identity.

caller / callee are membership, not liveness - who the call is between, not who has picked up yet.

Inbound seeding

FieldValue
callerExternal participant
calleeYour subscriber

Outbound

After make_call + dial, the dialed party is typically on the callee track - stream call.callee.audio_stream().

The one rule: is the agent in the audio path?

ShapeCallsMeaning
Ambient1Parties talk directly. Agent listens / speaks to one side or both.
In-path1 per partyParties do not hear each other; agent relays (e.g. live translator).

Ambient modes (after connect())

ModeWho hears the agent
spy()Nobody
whisper()Subscriber only
barge()Both parties

Subscriber on inbound = your staff line (callee). On outbound = your line (caller).

Worked examples

ScenarioCallsShape
Voice assistant answers for the subscriber1answer(); agent is the callee’s voice
Call monitor / coach1connect() then spywhisper / barge
Live translator2One Call per human; agent in-path on both

Per-party audio

1async for chunk in call.caller.audio_stream():
2 ... # only the caller
3
4async for chunk in call.callee.audio_stream():
5 ... # only the callee