CLI tool for managing VAPI voice assistants via the API. Applies configuration that the VAPI web dashboard cannot save reliably (endCallPhrases, endCallMessage, idle messages, etc.), and provides utilities for inspecting assistants, calls, transcripts, and phone numbers.
Built for the AI Win Capture System pattern: an automated voice agent interviews team members, extracts structured data from the conversation, and sends it via webhook to your data pipeline.
Caller dials phone number
|
v
VAPI Voice Agent (structured interview)
- LLM: GPT-4.1-mini (conversation)
- STT: Deepgram Nova-3 (speech-to-text)
- TTS: VAPI built-in voice (text-to-speech)
|
v (call ends → end-of-call-report webhook)
Your Data Pipeline (e.g. Power Automate → Dataverse)
|
v
Team queries captured data (e.g. Copilot Studio in Teams)
This repo contains the VAPI management scripts — the voice agent configuration and call inspection tools. The data pipeline (webhook receiver, database, query agent) is built separately using your platform of choice.
- Python 3.10+
- VAPI account — sign up at vapi.ai
- VAPI API Key — Dashboard → Organization → API Keys
# 1. Clone the repo
git clone <your-repo-url>
cd vapi-assistant-manager
# 2. Create and activate a virtual environment
python3 -m venv .venv
source .venv/bin/activate # macOS/Linux
# .venv\Scripts\activate # Windows
# 3. Install dependencies
pip install -r requirements.txt
# 4. Configure environment variables
cp .env.example .env
# Edit .env and add your VAPI API key
# 5. Set your assistant name in config/assistant_config.py
# Update ASSISTANT_NAME to match your VAPI dashboard assistant name
# 6. Verify connection
python vapi_manager.py get-assistant| Command | Description |
|---|---|
python vapi_manager.py status |
Compare live assistant config against desired state (field-by-field diff with checkmarks) |
python vapi_manager.py update --dry-run |
Preview what changes would be applied without sending them |
python vapi_manager.py update |
Apply configuration changes that the dashboard cannot save |
python vapi_manager.py get-assistant |
Dump the full current assistant config as JSON |
python vapi_manager.py list-calls |
List recent calls with IDs, dates, and durations |
python vapi_manager.py get-call <call_id> |
Show transcript, structured data, and metadata for a specific call |
python vapi_manager.py provision-number |
Provision a free VAPI phone number and assign it to the assistant |
python vapi_manager.py list-numbers |
List all phone numbers on the account |
# 1. Confirm assistant is found
python vapi_manager.py get-assistant
# 2. Review which settings need to be applied
python vapi_manager.py status
# 3. Preview the patch payload
python vapi_manager.py update --dry-run
# 4. Apply changes
python vapi_manager.py update
# 5. Verify all fields show ✓
python vapi_manager.py statusThis file defines three things:
-
ASSISTANT_NAME— Must match the assistant name in your VAPI dashboard. Can be overridden by theVAPI_ASSISTANT_NAMEenvironment variable. -
PROTECTED_FIELDS— Fields theupdatecommand will never overwrite (default:{"model"}). This protects your system prompt from accidental overwrites — prompt changes should always be reviewed manually in the dashboard. -
ASSISTANT_UPDATE_PAYLOAD— The desired state of your assistant. Only fields listed here are checked bystatusand applied byupdate. Everything else on the live assistant is left untouched.
Common fields to manage via API (because the dashboard silently drops them):
| Field | What it does |
|---|---|
endCallPhrases |
Phrases that end the call immediately when the caller says them |
endCallMessage |
What the AI says before hanging up |
messagePlan.silenceTimeoutMessage |
What the AI says when silence timeout triggers |
messagePlan.idleMessages |
Nudge messages when the caller goes quiet |
startSpeakingPlan |
Response timing (how long the AI waits before speaking) |
stopSpeakingPlan |
Interruption handling (how many words before AI stops talking) |
See VAPI API docs for the full list of available fields.
VAPI_API_KEY=your-vapi-api-key
VAPI_ASSISTANT_NAME=Your-Assistant-Name # optional, overrides config
The file vapi_system_prompt_wins.md contains a battle-tested system prompt template for structured voice interviews. It includes:
- Identity & mission — Who the AI is and what it's trying to accomplish
- Style rules — Short, professional responses; one question at a time
- Patience rules — Critical for preventing the AI from interrupting callers mid-thought
- 15 structured questions across 5 sections (project basics, win analysis, competition, key people, lessons)
- Error handling — Graceful recovery for unclear responses, rushed callers, and technical issues
To customize: copy the file, update the identity/company name, and modify the questions to match your interview goals. Paste the final prompt into VAPI Dashboard → your assistant → Model section → System Prompt.
After each call, VAPI sends an end-of-call-report webhook containing:
- Call metadata (ID, duration, phone number, recording URL)
- Full transcript
- AI-generated summary
- Structured data extracted from the transcript (based on your schema)
Configure the webhook in VAPI Dashboard → your assistant → Advanced → Server URL. Add an X-Vapi-Secret header for authentication.
The structured data schema is configured in VAPI Dashboard → your assistant → Analysis → Structured Data Plan. See VAPI structured outputs docs for details.
Example pipeline: Power Automate (webhook receiver) → Dataverse (database) → Copilot Studio (Teams query agent). But any webhook-compatible system works (Zapier, n8n, custom server, etc.).
| Problem | Cause | Fix |
|---|---|---|
endCallPhrases disappear after saving in dashboard |
Known VAPI dashboard limitation | Use python vapi_manager.py update to set via API |
Structured data is empty {} |
Assistant not republished after adding schema | Make any change in VAPI dashboard → Save |
| AI interrupts callers mid-sentence | waitSeconds or endpointing too low |
Increase startSpeakingPlan.waitSeconds in config |
| AI waits too long to respond | waitSeconds too high |
Decrease startSpeakingPlan.waitSeconds |
VAPI API error 401: Unauthorized |
Invalid API key | Check VAPI_API_KEY in .env |
Assistant 'X' not found |
Name mismatch | Ensure ASSISTANT_NAME in config matches VAPI dashboard exactly |
All API calls are logged to vapi_manager.log for debugging.
.
├── vapi_manager.py # CLI tool — run this
├── vapi_client.py # VAPI API client library (used internally)
├── config/
│ ├── __init__.py
│ └── assistant_config.py # Your assistant's desired configuration
├── vapi_system_prompt_wins.md # System prompt template for interviews
├── requirements.txt # Python dependencies
├── .env.example # Environment variable template
└── .gitignore
vapi_client.py is a reusable Python wrapper around the VAPI REST API. It handles:
- Bearer token authentication
- Automatic retry (up to 3 times) with exponential backoff on 429 rate limits
- Clear error messages for 401, 404, and 422 responses
You don't run this file directly — it's imported by vapi_manager.py. You can also import it in your own scripts:
from vapi_client import VAPIClient
client = VAPIClient("your-api-key")
assistants = client.list_assistants()
calls = client.list_calls()
call = client.get_call("call-id")