> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.agentduet.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.agentduet.com/_mcp/server.

# Feedback Collection with Outbound Calls

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](https://pypi.org/project/agentduet/1.0.0/) with **Gemini Live**. Full source: [agentduet-samples / outbound-feedback](https://github.com/AgentDuet/agentduet-samples/tree/main/use-cases/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](https://agentduet.com)
- Google Gemini API key (`GEMINI_API_KEY`) with Gemini Live access

## Tutorial

### Step 1: Clone the sample

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

### Step 2: Install

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

### Step 3: Configure `.env`

```bash
cp .env.example .env
```

```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

```bash
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 Outcome | Disposition | Operational Behavior |
|---|---|---|
| **Answered** | `CONNECTED` | Interactive voice survey conducts Q&A and logs full feedback. |
| **Ring Timeout** | `CALL_UNANSWERED` | Passenger did not answer within 25s. Logged to JSONL; queued for automated retry. |
| **Line Busy** | `CALL_BUSY` | Line engaged. Logged with timestamp for next retry window. |
| **Declined** | `CALL_REJECTED` | Call rejected. Logged and excluded from immediate retries. |

## Key APIs

| Piece | Role |
|---|---|
| `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.jsonl` | Persistent storage for survey responses and dispositions |

## Related

- [Voice AI Agent for Appointment Booking](/use-cases/voice-ai-agent-for-appointment-booking)
- [AI Receptionist with CRM Lookup](/use-cases/ai-receptionist-with-crm-lookup)
- [Document Collection with Outbound Calls](/use-cases/document-collection-with-outbound-calls)