Feedback Collection with Outbound Calls

View as Markdown

An automated post-trip feedback agent automatically calls passengers after a bus trip to capture structured ratings, verify punctuality and cleanliness, log complaints, and record audit trails.

Since these are outbound calls initiated by the system, unanswered calls or busy signals are treated as standard operational outcomes rather than system failures.

What it does

  • Dials passengers after completed trips using outbound telephony primitives
  • Gathers a structured 1–5 comfort rating, punctuality confirmation, and driver/cleanliness feedback
  • Answers questions and logs detailed complaints when something went wrong during the trip
  • Automatically logs unanswered or busy calls with disposition codes (CALL_UNANSWERED, CALL_BUSY) for scheduled retry
  • Clears audio buffers immediately on barge-in when the passenger speaks
  • Plays the full closing confirmation before cleanly disconnecting the call leg

This sample

TransitExpress Feedback Agent on AgentDuet with Gemini Live. Full source: agentduet-samples / outbound-feedback.

State flow: Outbound make_call()dial(ring_time_seconds=25)LIVE on answer → Gemini Live voice survey → disconnect()

Prerequisites

  • Python 3.12+
  • Get an API key and connector UUID at agentduet.com
  • Google Gemini API key (GEMINI_API_KEY) with Gemini Live access

Tutorial

Step 1: Clone the sample

$git clone https://github.com/AgentDuet/agentduet-samples.git
$cd agentduet-samples/use-cases/outbound-feedback

Step 2: Install

$python3.12 -m venv .venv
$source .venv/bin/activate
$pip install -r requirements.txt

Step 3: Configure .env

$cp .env.example .env
AGENTDUET_API_KEY=your-connector-api-key
AGENTDUET_CONNECTOR_UUID=your-connector-uuid
AGENTDUET_SUBSCRIBER=+1XXXXXXXXXX # Originating line
DESTINATION_NUMBER=+1XXXXXXXXXX # Passenger phone number
GEMINI_API_KEY=your-gemini-api-key
GEMINI_MODEL=models/gemini-3.1-flash-live-preview
GEMINI_VOICE=Zephyr
SAMPLE_RATE=24000

Step 4: Run

$python main.py

Step 5: Test the Outbound Flow

  1. Answer the Call: The agent opens conversationally: “Hi there! I’m calling from TransitExpress’s virtual support team about your bus ride from New York to D.C. Do you mind if I ask you a couple of quick questions?”
  2. Agree to Survey: Say “Sure” or “Go ahead”. The agent thanks you and asks for your comfort score (1 to 5).
  3. Punctuality & Cleanliness: Provide feedback on punctuality and driver service/cleanliness.
  4. Closing: The agent saves the structured record to data/feedback_results.jsonl, delivers a warm goodbye, and disconnects cleanly.

Handling Unanswered Dispositions

Dial OutcomeDispositionOperational Behavior
AnsweredCONNECTEDInteractive voice survey conducts Q&A and logs full feedback.
Ring TimeoutCALL_UNANSWEREDPassenger did not answer within 25s. Logged to JSONL; queued for automated retry.
Line BusyCALL_BUSYLine engaged. Logged with timestamp for next retry window.
DeclinedCALL_REJECTEDCall rejected. Logged and excluded from immediate retries.

Key APIs

PieceRole
session.make_call(Address.telco(number))Mints the outbound call leg
call.dial(ring_time_seconds=25)Places outbound SIP call with ring timeout
call.callee.audio_stream()Reads passenger microphone audio for streaming
call.send_audio(chunk)Streams synthesized voice to the passenger
call.clear_send_audio_buffer()Immediate barge-in interruption clearing
call.disconnect()Clean call hangup after closing speech completes
data/feedback_results.jsonlPersistent storage for survey responses and dispositions