Add outbound-sales example: batch dial-out bot with text-mode evals - #224
Draft
jamsea wants to merge 7 commits into
Draft
Add outbound-sales example: batch dial-out bot with text-mode evals#224jamsea wants to merge 7 commits into
jamsea wants to merge 7 commits into
Conversation
Hailey calls leads from leads.csv in batches of 5 over Daily PSTN, asks for the IT decision maker, saves contact info to results.csv via a save_contact_info tool, and hangs up via an end_call tool. Scaffolded with the new Pipecat CLI (pipecat init --eval). The same bot.py runs real calls on DailyTransport with full audio, or in text-only eval mode (-t eval) for fast behavior testing with 'pipecat eval suite evals.yaml' (3 scenarios: happy path, transfer, refusal; all passing). Uses pipecat-ai from git main until the 1.4.0 release ships the CLI and evals on PyPI.
…fixes - CannedGreetingGate: first reply skips the LLM round-trip; the greeting is emitted as LLM-shaped frames so TTS, context, and evals all see a normal response (plain TTSSpeakFrame never surfaces in text-mode evals) - DialoutManager passes callerId; server defaults it from CALLER_ID env - Default voice: Cartesia Sierra (California Girl) - Dockerfile installs git for the pipecat git dependency (drop after 1.4.0) - pcc-deploy.toml: image reference for Pipecat Cloud deploys
…server PCC call logs showed Smart Turn judging short utterances (a bare "Hello?") as incomplete and falling back to its 3s silence timeout, which read as a long pause before Hailey answered. Keep Smart Turn's don't-interrupt judgement but cap the fallback at 1s, and add UserBotLatencyObserver so calls log exact user-stop to bot-speak times.
Latency breakdowns showed tool-call turns pay two LLM TTFBs (the call, then the spoken reply). Speak a short filler on on_function_calls_started for save_contact_info to cover the gap. Tried gpt-4.1-mini for the ~0.3s faster TTFB but the eval suite rejected it (missed end_call tool calls in 2 of 6 runs), so the model stays gpt-4.1.
The dial-out room is created with enable_recording="cloud" and the bot starts the recording on on_dialout_answered. Recordings are listed and downloaded afterwards via Daily's REST API (/recordings + access-link). Downloaded files land in server/recordings/ (gitignored).
Replace the shared results.csv file with a POST /call_result endpoint on server.py that logs each outcome and keeps it in memory; the dialer polls GET /results. This matches how a real deployment works (bots in separate containers can't share a file) and drops results.py entirely. Also: start audio-only cloud recording from the bot's meeting token so it begins before the phone leg connects, speak the canned greeting via TTSSpeakFrame (LLM-response frames only in eval mode so the harness can see it), add deploy notes to pcc-deploy.toml, and add a CLAUDE.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SUPER DUPER DRAFTY DRAFT
What this adds
Meet Hailey, an outbound sales agent built with Pipecat. She calls a list of leads in batches of 5 over Daily PSTN, tries to reach the IT decision maker, collects their contact info, and reports the outcome to the webhook server.
Key pieces:
server/bot.py: Hailey's pipeline,save_contact_infoandend_calltools, dial-out retry logic, canned greeting gate, latency observerserver/server.py: FastAPI server;POST /dialoutstarts calls,POST /call_resultrecords outcomes (in-memory demo store),GET /resultsis polled by the dialerserver/dialer.py: batch dialer, 5 calls at a time, resumableserver/scenarios/+evals.yaml: text-mode Pipecat evals so the bot's behavior can be tested in seconds with no phone calls or audioDesign notes:
TTSSpeakFrame. In eval mode it's pushed as LLM response frames instead, since text-mode evals only see LLM text events.How to test
See the README: run
server.pyanddialer.pyin two terminals with aleads.csv, or run the evals withuv run pipecat evals run.🤖 Generated with Claude Code