← Plugin catalog
Developer Tools

Vapi

Vapi v1.2.1

Publisher description

From the marketplace listing

Plan, configure, and validate Vapi voice AI workflows with skills for assistants, prompts, tools, calls, campaigns, squads, phone numbers, webhooks, structured outputs, and simulations.

Language: English · Automatically detected from descriptions.

Files & skills

File archives

Plugin package51 files · 64.3 KBBrowse files →
Skill instructions
create-assistant9.25 KB

View saved version →

---
name: create-assistant
description: Design, create, or validate saved and transient Vapi voice assistants. Use for new phone or web agents, production system prompts and first messages, saved-versus-transient architecture, model/voice/transcriber selection, multilingual compatibility, existing tool attachment, native call-control tools, assistant hooks, and Create Assistant API validation errors.
license: MIT
---

# Vapi Assistant Creation

Design the assistant's behavior before assembling its configuration. Treat persistence and execution as separate decisions: a returned configuration can still describe a saved assistant, and creating a saved assistant does not deploy it, attach a phone number, or prove it is production-ready.

## Source and Safety Rules

- Use the configured Vapi documentation MCP when available for current product guidance. Otherwise use the bundled references and their public Vapi links. Validate the final payload against the current Create Assistant API schema.
- Never print, request in chat, or embed API keys, provider secrets, credential values, private URLs, or real customer data.
- Never invent IDs, destinations, integrations, server URLs, model names, voices, transcribers, schemas, or business policy.
- Keep a saved assistant's `name` at 40 characters or fewer.
- Do not enable paid, HIPAA, PCI, recording, retention, or other compliance behavior unless the user requests it and the current docs support the exact configuration.
- Treat prompts as behavioral instructions, not capabilities or security boundaries. Scheduling, lookup, transfer, messaging, authentication, and other actions require real tools or server-side support.

## Procedure

1. Decide the assistant architecture and requested action.
   - Prefer a **saved assistant** for a reusable agent that should be shared, attached by ID, or managed over time. If the user simply asks to create or build an agent, use this shape unless the request indicates otherwise.
   - Use a **transient assistant** only when the user asks for an inline or call-scoped configuration, or when the use case specifically needs per-call configuration, short-lived testing, or an `assistant-request` response. Put it in the call's `assistant` field; do not send it to `POST /assistant`.
   - If the user asks for JSON, an example, a draft, or an implementation without account mutation, return the appropriate configuration without calling the API.
   - If the user asks to create or save the assistant in Vapi and `VAPI_API_KEY` is available, create a saved assistant with `POST /assistant`. Do not ask for redundant confirmation after an unambiguous create request.
   - If creation is requested but credentials are unavailable, return a save-ready configuration and command, and state clearly that the assistant has not been saved. Do not relabel it as transient.

2. Run a focused requirements intake.
   - Infer what is clear from the request, then collect only missing facts that materially affect the design: business and audience, call direction, primary objective and success criteria, workflows, authoritative business knowledge, real tools or integrations, escalation boundaries, information to collect or avoid, languages, and brand voice.
   - Ask a compact group of clarifying questions when several business facts are required to produce a credible agent. Learn enough about the business before claiming the agent is ready.
   - Decide whether one assistant can own the workflow reliably. Use the `create-squad` skill when distinct specialists, routing, or handoffs are central to the design.
   - Do not ask the user to choose infrastructure providers unless they expressed a preference or the use case creates a real language, latency, compliance, or credential constraint.

3. Design a production-quality system prompt.
   - Use the `vapi-prompt-builder` skill for every new assistant or substantial prompt rewrite when it is available. Otherwise read [Prompt Design](references/prompt-design.md) as the standalone fallback.
   - Write the complete prompt before provider and payload assembly. Cover identity and personality, response guidelines, guardrails, context, workflows or use cases, and compact examples.
   - Keep spoken turns concise, ask one question at a time, define uncertainty and recovery behavior, and make critical values spoken-friendly.
   - Align `firstMessage` and `firstMessageMode` with call direction and the prompt. Do not use a generic greeting when the business, disclosure, or outbound purpose requires something specific.

4. Ground every capability in real configuration.
   - Map every promised action to an existing tool, knowledge source, runtime variable, or documented backend contract. List missing dependencies as `Configuration needed`; do not hide them in the prompt.
   - Reuse exact saved tool IDs in `model.toolIds`. Put documented inline tools in `model.tools`. Use the `create-tool` skill when a reusable tool or external-server implementation is required.
   - Attach the native `endCall` tool to every newly built assistant and define the allowed closing conditions in the prompt. Reuse a verified saved tool ID when available; otherwise use the current documented native-tool shape.
   - For outbound voicemail behavior, attach the native `voicemail` tool and align its message and the assistant prompt. Do not add `voicemailDetectionPlan`, `voicemailDetection`, or other assistant-level automatic voicemail-detection keys.
   - Read [Assistant Hooks](references/hooks.md) only for deterministic event-triggered behavior. Use server events for backend notifications and assistant tools for model-decided actions.

5. Select compatible providers and settings.
   - Read [Provider Policy](references/providers.md) before choosing components, honoring provider requests, pinning defaults, or supporting multiple languages.
   - Omit optional provider components only when the Create Assistant API documents their defaults. Pin components when the use case or reproducibility requires it.
   - Verify every explicit model, voice, transcriber, and language value against current API documentation. Ensure the voice can speak and the transcriber can recognize every promised language.

6. Assemble and validate the configuration.
   - Include a use-case-specific `name`, the appropriate first-message behavior, and a `model` containing the complete system prompt.
   - Add voice, transcriber, tools, hooks, analysis, compliance, transport, and other fields only when they are intentional. Omitted optional fields may use Vapi defaults; do not add fields merely to make the payload look complete.
   - Check for placeholders, unsupported or stale values, leaked secrets, language mismatches, invented business facts, unavailable capabilities, and prompt/configuration contradictions.
   - Separate assumptions and unresolved dependencies from creation-ready JSON. Never put fake IDs, URLs, phone numbers, or credentials into a payload represented as ready to create.

7. Create and verify when requested.
   - Send one `POST /assistant` for a saved assistant and require a `201` response. Verify the returned `id`, name, system prompt, attached tools, and any explicitly configured providers.
   - API-created assistants are saved immediately; there is no separate API publish step. Do not claim the assistant is deployed, routed to a phone number, tested, or production-ready unless those separate actions were completed.
   - On `400`, correct one documented validation issue and retry at most once when the fix is unambiguous. Never repeat an unchanged request. On `401` or `403`, stop and report authentication or permission failure. On `404`, report the missing dependency. On `5xx`, report the service failure.
   - Provide realistic success, edge, and failure test scenarios. Recommend a web call or representative Eval/test set, then iterate from actual results; one successful call is not sufficient evidence of production quality.

## API Implementation Examples

Read [Assistant API Examples](references/api-examples.md) when the user requests implementation code. Use the official TypeScript or Python Server SDK for a backend project in those languages; use cURL for a direct REST example or shell-based verification. After a successful create, return the saved assistant ID, summarize the verified configuration, identify anything still unconfigured, and provide test scenarios. A generated payload is not a saved assistant; a saved assistant is not automatically deployed.

## Output Contract

Return only the sections relevant to the request:

- Architecture: saved or transient, with the reason when it was not explicit
- Assumptions or blocking questions
- Final assistant configuration, including the complete system prompt
- Configuration needed for capabilities that are not yet real
- Creation result and assistant ID, when the API was called successfully
- External test scenarios and recommended next iteration

## Public Sources

- [Assistants quickstart](https://docs.vapi.ai/assistants/quickstart)
- [Transient vs permanent configurations](https://docs.vapi.ai/assistants/concepts/transient-vs-permanent-configurations)
- [Voice AI Prompting Guide](https://docs.vapi.ai/prompting-guide)
- [Create Assistant API](https://docs.vapi.ai/api-reference/assistants/create)
- [Default tools](https://docs.vapi.ai/tools/default-tools) and [Voicemail tool](https://docs.vapi.ai/tools/voicemail-tool)

Referenced files: 5

create-call6.24 KB

View saved version →

---
name: create-call
description: Create one-off outbound phone calls, web calls, scheduled calls, and simple batch calls using the Vapi API. Use when making or testing individual calls or initiating a bounded /call request programmatically. Use create-campaign for a persistent multi-contact Campaign with lifecycle, reporting, cancellation, duplication, or campaign webhooks.
license: MIT
---

# Vapi Call Creation

Initiate outbound phone calls, web calls, and batch calls using Vapi's API. Connect your voice assistants to real phone numbers and test them programmatically.

> **Setup:** Ensure `VAPI_API_KEY` is set. See the `setup-api-key` skill if needed.

## Quick Start — Outbound Phone Call

### cURL

```bash
curl -X POST https://api.vapi.ai/call \
  -H "Authorization: Bearer $VAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "assistantId": "your-assistant-id",
    "phoneNumberId": "your-phone-number-id",
    "customer": {
      "number": "+11234567890"
    }
  }'
```

### TypeScript (Server SDK)

```typescript
import { VapiClient } from "@vapi-ai/server-sdk";

const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! });

const call = await vapi.calls.create({
  assistantId: "your-assistant-id",
  phoneNumberId: "your-phone-number-id",
  customer: {
    number: "+11234567890",
  },
});

console.log("Call created:", call.id);
```

### Python

```python
import requests
import os

response = requests.post(
    "https://api.vapi.ai/call",
    headers={
        "Authorization": f"Bearer {os.environ['VAPI_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "assistantId": "your-assistant-id",
        "phoneNumberId": "your-phone-number-id",
        "customer": {"number": "+11234567890"},
    },
)

call = response.json()
print(f"Call initiated: {call['id']}")
```

## Call Types

### Outbound Phone Call

Requires an assistant, a Vapi phone number, and a customer number.

```json
{
  "assistantId": "assistant-id",
  "phoneNumberId": "phone-number-id",
  "customer": {
    "number": "+11234567890",
    "name": "John Doe",
    "numberE164CheckEnabled": true
  }
}
```

### Web Call

For browser-based calls — no phone number needed. Use the Vapi Web SDK on the client side.

```json
{
  "assistantId": "assistant-id"
}
```

Client-side (JavaScript):
```javascript
import Vapi from "@vapi-ai/web";

const vapi = new Vapi("your-public-key");
vapi.start("your-assistant-id");
```

### Transient Assistant Call

Define an assistant inline instead of referencing a saved one:

```json
{
  "assistant": {
    "name": "Quick Test",
    "firstMessage": "Hello! This is a test call.",
    "model": {
      "provider": "openai",
      "model": "gpt-4.1",
      "messages": [
        {
          "role": "system",
          "content": "You are a test assistant. Confirm the call is working and end politely."
        }
      ]
    },
    "voice": { "provider": "vapi", "voiceId": "Elliot", "version": 2 },
    "transcriber": { "provider": "deepgram", "model": "nova-3", "language": "en" }
  },
  "phoneNumberId": "phone-number-id",
  "customer": {
    "number": "+11234567890"
  }
}
```

## Scheduled Calls

Schedule a call for a future time:

```json
{
  "assistantId": "assistant-id",
  "phoneNumberId": "phone-number-id",
  "customer": {
    "number": "+11234567890"
  },
  "schedulePlan": {
    "earliestAt": "2025-06-15T14:00:00Z",
    "latestAt": "2025-06-15T15:00:00Z"
  }
}
```

- `earliestAt` — Earliest time to attempt the call (ISO 8601)
- `latestAt` — Latest time to attempt the call (optional)
- If using `assistantId`, the latest version of the assistant is used at call time
- For a fixed assistant config, use `assistant` (transient) instead

## Batch Calls

Call multiple numbers in one request:

```json
{
  "assistantId": "assistant-id",
  "phoneNumberId": "phone-number-id",
  "customers": [
    { "number": "+11234567890", "name": "Alice" },
    { "number": "+10987654321", "name": "Bob" },
    { "number": "+15551234567", "name": "Carol" }
  ]
}
```

Combine with `schedulePlan` for scheduled batch calls.

Use this `/call` batch only when the user does not need a persistent Campaign resource. Use the `create-campaign` skill for campaign-level monitoring, contact outcomes, duplication, cancellation, concurrency, or webhooks.

## Call with Metadata

Pass custom data accessible during the call:

```json
{
  "assistantId": "assistant-id",
  "phoneNumberId": "phone-number-id",
  "customer": {
    "number": "+11234567890"
  },
  "metadata": {
    "orderId": "ORD-12345",
    "department": "billing"
  }
}
```

## Managing Calls

```bash
# List calls
curl "https://api.vapi.ai/call?limit=10" \
  -H "Authorization: Bearer $VAPI_API_KEY"

# Get a specific call
curl https://api.vapi.ai/call/{id} \
  -H "Authorization: Bearer $VAPI_API_KEY"

# Get call with transcript and recording
curl https://api.vapi.ai/call/{id} \
  -H "Authorization: Bearer $VAPI_API_KEY"
# Response includes: artifact.transcript, artifact.recordingUrl,
# analysis.summary, and costBreakdown when those outputs are enabled

# Delete a call
curl -X DELETE https://api.vapi.ai/call/{id} \
  -H "Authorization: Bearer $VAPI_API_KEY"
```

## Call Response

A successful call creation returns:

```json
{
  "id": "call-uuid",
  "orgId": "org-uuid",
  "type": "outboundPhoneCall",
  "status": "queued",
  "assistantId": "assistant-id",
  "phoneNumberId": "phone-number-id",
  "customer": {
    "number": "+11234567890"
  },
  "createdAt": "2025-01-15T10:00:00Z"
}
```

Call statuses: `queued` → `ringing` → `in-progress` → `ended`

## Compliance Warning

It is a violation of FCC law to dial phone numbers without consent in an automated manner. Review TCPA consent requirements before launching automated call campaigns.

## References

- [Vapi Outbound Calls Docs](https://docs.vapi.ai/calls/outbound-calling)
- [Call Features](https://docs.vapi.ai/calls/call-features)
- [Voicemail Detection](https://docs.vapi.ai/calls/voicemail-detection)

## Additional Resources

Vapi provides a **documentation MCP server** that gives compatible AI agents access to the Vapi knowledge base. Use its documentation search for advanced configuration, troubleshooting, SDK details, and anything beyond this skill.


See the [Vapi MCP integration guide](https://docs.vapi.ai/cli/mcp) for setup instructions across supported agents.

Referenced files: 1

create-campaign12.6 KB

View saved version →

---
name: create-campaign
description: Create, schedule, duplicate, inspect, cancel, archive, and troubleshoot Vapi outbound Campaigns. Use for persistent multi-contact calling, CSV or API contact personalization, campaign concurrency, campaign webhooks, pre-dial eligibility, contact outcomes, or rerunning an audience. Do not use for a single call or a simple one-off /call batch.
license: MIT
---

# Vapi Outbound Campaigns

Use Campaigns for a persistent outbound run whose contacts, lifecycle, and results must be managed together. Creating a campaign launches it immediately or schedules it; there is no draft or separate start action.

The current public API uses `/v2/campaign`. The unversioned `/campaign` endpoints are legacy and have different behavior. Use `/v2/campaign` for new integrations, and touch `/campaign` only when the user explicitly asks to maintain an existing legacy integration.

## Source and Safety Rules

- Verify live payloads against the current Vapi documentation MCP, [Campaigns documentation](https://docs.vapi.ai/outbound-campaigns/overview), or public API reference. Do not silently fall back from `/v2/campaign` to legacy `/campaign` behavior.
- Use a private API key only on a trusted server. Read it from `VAPI_API_KEY`; never print it, request it in chat, or put it in client-side code, examples, logs, or committed files.
- Treat phone numbers, names, contact variables, call records, transcripts, and recordings as sensitive. Report counts and redacted samples unless the user needs specific records.
- Never invent resource IDs, recipients, consent, schedules, time zones, campaign state, counters, or call outcomes. Resolve saved resources by exact ID or an unambiguous API result.
- Launching can place real, chargeable calls. Before a live create or duplicate, review the exact target, outbound number, audience count, timing, concurrency, and webhook behavior. Obtain confirmation unless the user's current instruction already unambiguously authorizes that exact launch.
- Do not make a legal determination. Tell the user to verify the consent, caller-identification, recording, opt-out, quiet-hours, and telemarketing requirements that apply to every recipient and destination. Use Vapi's [TCPA consent guidance](https://docs.vapi.ai/tcpa-consent) when relevant.
- A timeout or ambiguous response to `POST /v2/campaign` does not prove failure. Search for the intended campaign before retrying so the audience is not called twice.

## Procedure

1. Choose the API and execution mode.
   - Use `POST /call` and the `create-call` skill for one call or a simple one-off batch that does not need campaign-level lifecycle, reporting, cancellation, duplication, or webhooks.
   - Return a plan, CSV, payload, or implementation without calling Vapi when the user asks to draft, explain, review, or prepare.
   - Use live API operations only when the user asks to create, duplicate, cancel, or archive and `VAPI_API_KEY` is available.

2. Resolve the caller and outbound number.
   - Select exactly one saved `assistantId` or `squadId`. Do not use deprecated Workflows for a new campaign.
   - Resolve one outbound-capable `phoneNumberId`. Vapi Free Numbers cannot launch campaigns. The current `/v2/campaign` API does not support legacy `dialPlan` routing across multiple outbound numbers.
   - Inspect the assistant or squad before launch. Ensure its prompt, tools, variables, call-ending behavior, and published configuration match this outbound use case.
   - Configure one voicemail approach on every assistant that may handle a campaign call: the assistant-driven voicemail tool or built-in voicemail detection, never both. Test representative voicemail and call-screening paths before scaling.

3. Prepare and validate contacts.
   - Allow 1 to 10,000 contacts. Prefer E.164 numbers such as `+14155550100`. In an API request, an intentional non-E.164 SIP-trunk destination requires `numberE164CheckEnabled: false` on that customer; the number must still contain only an optional leading `+` followed by letters or digits. The Dashboard CSV importer cannot set this customer-level flag, so use E.164 numbers for that path.
   - For a Dashboard CSV, require lowercase `number`; lowercase `name` is optional. Every other populated column becomes a case-sensitive dynamic variable. Prefer lowercase `snake_case` headers.
   - Keep CSV files within the documented 5 MB Dashboard limit. Reject blank or malformed rows and surface duplicates for review; do not silently drop or merge recipients.
   - For API requests, place per-contact values in `assistantOverrides.variableValues` for an assistant campaign or `squadOverrides.variableValues` for a squad campaign. Do not copy arbitrary source columns into unrelated configuration fields.
   - Keep each contact's combined serialized variable data below 100,000 characters. Confirm that every variable referenced by the caller is present or has intentional fallback behavior.

4. Set timing and concurrency.
   - Omit `schedulePlan` for a new campaign that should dispatch as soon as capacity is available.
   - For a scheduled window, send `schedulePlan.earliestAt` and optional `latestAt` as ISO 8601 date-times. When the user gives local time, establish the IANA time zone, convert it, and show both local and ISO values.
   - Confirm `latestAt` is later than `earliestAt`. The Dashboard schedules up to seven days ahead in 15-minute increments; recheck current API constraints when implementing outside the Dashboard.
   - Choose `maxConcurrency` at or below the organization's available concurrency. It limits this campaign but does not reserve slots or increase the organization's shared call capacity.
   - Leave enough time for the audience. Contacts waiting for capacity may be retried for up to one hour, but retries stop earlier when `latestAt` is reached.

5. Configure campaign webhooks only when needed.
   - Set `server` before using `predialPlan` or `serverMessages`. Prefer a saved credential over inline secrets and use an intentional timeout and backoff plan.
   - Use `predialPlan: { "enabled": true }` for a blocking check immediately before each contact is dialed. The endpoint must return JSON containing Boolean `eligible`; false skips the contact, while timeout, non-2xx, or invalid JSON produces `contact.predial-failed`.
   - Use `serverMessages` for selected asynchronous campaign and contact lifecycle events. Make the receiver idempotent and do not depend on event ordering.
   - Campaign events do not contain the full call artifact. Configure `end-of-call-report` on the relevant assistant when the integration also needs transcripts, recordings, or analysis, and join records by `callId`.

6. Build and review the request.
   - For a fresh campaign, include `name`, exactly one of `assistantId` or `squadId`, `phoneNumberId`, a non-empty `customers` array, and `maxConcurrency`.
   - For a duplicate, include `name` and `duplicateFromCampaignId`, then send only intentional replacements. Omit `customers` to inherit the source audience; a supplied `customers` array replaces it.
   - Add campaign-level `assistantOverrides` or `squadOverrides`, `schedulePlan`, `server`, `serverMessages`, and `predialPlan` only when intentional.
   - Read [Campaign API Reference](references/api-reference.md) for validated REST shapes, duplicate semantics, pagination, and lifecycle requests.
   - Before a live launch, show the resolved caller and phone number, audience count with a redacted sample, local and ISO timing, max concurrency, webhook side effects, and whether calling starts now. Do not expose the full contact payload in routine confirmation output.

7. Create once and verify.
   - Send one `POST /v2/campaign`. Treat the returned campaign ID as the durable identifier.
   - Re-fetch it with `GET /v2/campaign/{id}?includeCounters=true` before claiming creation succeeded. Report the actual status and schedule; creation does not prove any contact was reached.
   - If creation returns an ambiguous timeout or 5xx, use `GET /v2/campaign` with narrow supported filters and creation-time context to look for the campaign. Do not automatically repeat the POST.

8. Inspect and diagnose from contact evidence.
   - Fetch the campaign with `includeCounters=true`. Use `contactCounters` for pending, dispatched, completed, failed, skipped, and pre-dial-failed totals; use `callMetrics.dialed` and `callMetrics.connected` for pickup analysis.
   - Fetch `GET /v2/campaign/{id}/contacts` and paginate when needed. Contact status is the source of truth for each audience member.
   - A skipped or pre-dial-failed contact may have no call ID because no call was placed. When a real `callId` exists, retrieve that call and inspect its ended reason, transcript, recording, analysis, and logs before proposing a root cause.
   - Separate campaign dispatch problems, pre-dial eligibility failures, telephony connection failures, voicemail outcomes, and assistant behavior. Counters alone do not identify the cause.

9. Duplicate to rerun or replace compatible configuration.
   - Campaigns are immutable after creation. Do not patch the caller, contacts, schedule, concurrency, or webhook configuration.
   - Create a new campaign with `duplicateFromCampaignId` and a new `name`. Omitted configuration and contacts are copied from the source; provided fields override the source, and provided `customers` replace copied contacts. The source must also use the current `/v2/campaign` API.
   - Duplication cannot unset every inherited field. In particular, switching between `assistantId` and `squadId` inherits the old mutually exclusive caller and produces an invalid request. Create a fresh campaign when changing caller type or when an inherited option must be removed rather than replaced.
   - Review every inherited field before launch. To run a duplicate near-immediately instead of inheriting an expired schedule, generate `schedulePlan.earliestAt` immediately before the request with enough future margin to remain valid during transport and server validation, such as current UTC time plus 60 seconds. State the resulting delay.
   - Treat a duplicate as another live launch with the same authorization and double-dial safeguards as a fresh campaign.

10. Cancel or archive deliberately.
   - To stop a scheduled or running campaign, send `PATCH /v2/campaign/{id}` with only `{ "status": "cancelled" }`. Pending work stops; calls already in progress may finish. Cancellation is final for that campaign.
   - Re-fetch and verify the terminal state and `endedReason`. Do not describe cancellation as reversing calls already placed.
   - `DELETE /v2/campaign/{id}` archives rather than permanently erases campaign records. If active, the campaign is cancelled first. Archive only when the user separately asks to remove it from active campaign views.

## Failure Handling

- `400`: report the rejected field and compare it with the current `/v2/campaign` schema. Correct one unambiguous request-shape issue before at most one safe retry.
- `401` or `403`: stop for authentication, scope, entitlement, frozen subscription, or permission failure.
- `404`: report the exact missing campaign, assistant, squad, or phone number ID.
- `409`: re-fetch the campaign; an immutable or terminal lifecycle conflict requires a duplicate or no further action, not a repeated patch.
- `429` or `5xx`: report the service condition. Never retry campaign creation until duplicate creation has been ruled out.
- Partial completion: preserve the campaign and report actual contact outcomes. Do not delete, redial, or replace the remaining audience automatically.

## Output Contract

Return only what the request needs:

- Mode: plan, payload, launch, inspect, duplicate, cancel, archive, or diagnose
- Resolved caller, outbound number, contact count, and redacted sample
- Local and ISO schedule, max concurrency, and shared-capacity caveat
- Consent and calling-window assumptions that still require user verification
- Webhook and pre-dial behavior, including remaining live side effects
- Save-ready CSV, JSON, or code when requested
- Campaign ID, verified status, counters, contact outcomes, and call IDs after live operations
- Unresolved failures, evidence, and the smallest safe next action

## Public Sources

- [Campaigns overview](https://docs.vapi.ai/outbound-campaigns/overview)
- [Campaigns quickstart](https://docs.vapi.ai/outbound-campaigns/quickstart)
- [Campaign contact data](https://docs.vapi.ai/outbound-campaigns/contact-data)
- [Campaign scheduling and lifecycle](https://docs.vapi.ai/outbound-campaigns/scheduling-and-lifecycle)
- [Campaign voicemail and call screening](https://docs.vapi.ai/outbound-campaigns/voicemail-and-call-screening)
- [Campaign webhooks](https://docs.vapi.ai/outbound-campaigns/webhooks)
- [Campaign API reference](https://docs.vapi.ai/api-reference/campaigns/campaign-controller-create-v-2)

Referenced files: 2

create-phone-number5.76 KB

View saved version →

---
name: create-phone-number
description: Plan, provision, import, route, update, and verify Vapi phone numbers through the public API. Use for Vapi-hosted US PSTN numbers, explicitly requested SIP addresses, Twilio/Vonage/Telnyx or BYO carrier numbers, secure credential handling, assistant or squad routing, area-code requests, outbound limitations, and phone-provider troubleshooting.
license: MIT
---

# Vapi Phone Number Setup

Default to a payload or implementation plan. Provision, import, route, or release a number only when the user explicitly requests the live mutation. Require a final explicit confirmation immediately before provisioning or another potentially chargeable action.

## Security and Source Rules

- Never ask for carrier passwords, auth tokens, API keys, API secrets, or private keys in chat.
- Use an existing Vapi `credentialId` for provider imports when the current public schema supports it. If a required credential does not exist, stop and state that API prerequisite.
- If the public API requires raw carrier secrets and exposes no credential-based alternative, source them from local environment variables without displaying them, writing them to payload files, or logging the request body.
- Verify provider fields against the current [Create Phone Number API](https://docs.vapi.ai/api-reference/phone-numbers/create) or public OpenAPI schema.
- Never invent phone numbers, SIP realms, credentials, resource IDs, area-code availability, or routing destinations.

## Procedure

1. Determine the execution mode.
   - Return a payload or plan when the user asks for a draft or does not clearly authorize a live mutation.
   - For a live request, confirm that `VAPI_API_KEY` is set without printing it.

2. Choose the transport path.
   - For a nontechnical request for an ordinary number, prefer the documented Vapi-hosted US PSTN path.
   - Use SIP only when the user explicitly asks for SIP. Require an exact supported SIP URI from the user or current public API documentation; if it is unavailable, stop and state the missing prerequisite. Do not invent a regional realm.
   - Use a carrier import only when the user owns the number and the required secure credential path is available.

3. Resolve routing before mutation.
   - List or get assistants and squads through public endpoints. Match a supplied name to one resource.
   - If several resources are plausible, ask the user to choose. Never guess an ID.
   - Route to either one `assistantId` or one `squadId`; clear conflicting destination fields when changing an existing route.

4. Check inventory safely.
   - Review existing phone numbers with `GET /phone-number` to avoid duplicate provisioning.
   - The current public OpenAPI accepts `numberDesiredAreaCode` but does not expose a public available-area-code inventory endpoint. Accept the user's desired three-digit US area code after explaining that fulfillment is not guaranteed.
   - Do not purchase a number merely to test availability. Do not infer global unavailability from one provisioning response.

5. Confirm and execute.
   - Show the provider, area code or exact owned number, routing destination, and whether the action may incur carrier or usage charges.
   - Obtain explicit confirmation immediately before `POST /phone-number` or another potentially chargeable mutation.
   - Validate the response for `id`, provider, number or SIP URI, status when present, and resolved route.

6. Update without destroying configuration.
   - `GET /phone-number/{id}` first.
   - Build the provider-specific update DTO. Change only requested writable fields and preserve the current provider, hooks, server, fallback destination, and provider-specific settings by omission or exact carry-forward as required by the public schema.
   - Do not send response-only fields such as `id`, timestamps, or organization metadata.
   - Re-fetch the number and verify the requested route or setting.

7. Handle failures precisely.
   - `400`: report the rejected field or unavailable request; correct a documented shape error before at most one retry.
   - `401`/`403`: stop for Vapi authentication or permission issues.
   - `404`: report the missing phone number, assistant, squad, or credential.
   - `5xx`: report a Vapi service failure and do not claim success.
   - Separate carrier-side ownership, credential, provisioning, or transport failures from Vapi routing configuration.

## Free Vapi Number Limits

Vapi-hosted free numbers are for US national use and have a limit of five per account. The first free number can be requested without a payment method. Additional free numbers require a payment method on file, but the numbers themselves remain free.

Free Vapi numbers support outbound calls only to US `+1` destinations and do not support international calling. Use an imported provider number or supported SIP/carrier path for international use. Do not describe free numbers as unlimited production telephony.

## Payload-Only Example

This template does not provision anything:

```json
{
  "provider": "vapi",
  "numberDesiredAreaCode": "<confirmed-three-digit-area-code>",
  "assistantId": "<verified-assistant-id>",
  "name": "Main Support Line"
}
```

Read [Provider API Procedures](references/provider-api-procedures.md) for Vapi-hosted, Twilio, Vonage, Telnyx, BYO carrier, and routing examples. Read [Phone Number API Examples](references/api-examples.md) when the user requests TypeScript, Python, or cURL implementation code. Keep placeholders out of live requests.

## Public Sources

- [Phone calling](https://docs.vapi.ai/phone-calling) and [Phone quickstart](https://docs.vapi.ai/quickstart/phone)
- [Create Phone Number API](https://docs.vapi.ai/api-reference/phone-numbers/create)
- [Free Vapi phone numbers](https://docs.vapi.ai/free-telephony)
- [Import a Twilio number](https://docs.vapi.ai/phone-numbers/import-twilio)

Referenced files: 3

create-squad6.94 KB

View saved version →

---
name: create-squad
description: Design, create, update, and verify Vapi Squads and documented handoff tools through the public API. Use for choosing a single assistant versus a multi-assistant Squad, persistent or transient members, entry-member ordering, specialization boundaries, context engineering, variable extraction, model-specific handoff patterns, assistant-version pins, and safe Squad updates.
license: MIT
---

# Vapi Squad Creation

Use a Squad only when multiple focused assistants improve the design. Default to a payload or implementation plan unless the user explicitly requests live Vapi mutations.

## Decide Whether to Use a Squad

Prefer one assistant when one focused prompt and one compatible tool set can handle the use case reliably. Use a Squad for genuine boundaries such as:

- distinct domains or personas;
- different tool or credential access;
- deliberate context isolation;
- separately maintained specialists.

Do not create one assistant per conversational step. Keep related steps in one member and make each handoff boundary earn its latency and operational cost.

## Safety and Source Rules

- Verify squad, member, handoff, context, and version fields against the current public [Squads documentation](https://docs.vapi.ai/squads), [Handoff tool guide](https://docs.vapi.ai/squads/handoff), and OpenAPI schema.
- Never invent assistant IDs, names, tool IDs, destinations, versions, credentials, server URLs, or extracted variables.
- Prompt text does not create a handoff. Configure and attach a documented `handoff` tool.
- Keep member order explicit: the first member starts the call.
- Prefer saved assistants, reusable tools, and a saved Squad for production. Use transient members or Squads only when the request is intentionally ephemeral or a prototype.

## Persistent Squad Procedure

1. Determine the execution mode.
   - Return JSON or a plan when the user asks for a draft or does not clearly authorize live writes.
   - Perform live creates or updates only with explicit intent and an available `VAPI_API_KEY`.

2. Define focused members.
   - State each member's responsibility, tools, and handoff boundaries.
   - Choose the entry member and place it first.
   - Reuse existing assistants by resolving names through `GET /assistant`; create missing assistants first with the `create-assistant` skill.

3. Create handoff relationships after destinations exist.
   - Resolve every destination assistant before building a persistent handoff tool.
   - Use `type: "assistant"` plus a verified `assistantId` for saved cross-assistant destinations.
   - Use clear descriptions that state when the model should hand off and what should be collected first.
   - Create reusable handoff tools through `POST /tool`, then attach them to the source assistants with the configuration-preserving procedure in the `create-tool` skill.
   - For OpenAI models, current public guidance recommends one handoff tool per destination. For Anthropic models, one tool with multiple destinations is supported and recommended.

4. Configure public context controls only when needed.
   - Use `contextEngineeringPlan` on a handoff destination: `all`, `lastNMessages`, `userAndAssistantMessages`, `previousAssistantMessages`, or `none` when supported by the current schema.
   - Use `variableExtractionPlan.schema` only for specific structured values needed downstream. Do not invent values or claim extraction occurred before a real handoff.
   - Keep sensitive tool results out of downstream context when the use case requires isolation.

5. Create and verify the Squad.
   - Build `members` from verified assistant IDs in explicit order.
   - Optionally set `assistantVersion` only to a version returned by the public assistant API when the user wants an immutable pin. Omit it to follow latest.
   - Before a production-affecting create or update, recap member order, handoffs, and target and obtain explicit confirmation unless the user's current instruction already unambiguously authorizes that exact mutation now.
   - Send `POST /squad` only after explicit live-create intent.
   - Validate the returned Squad ID, complete member order, entry member, pins, and handoff attachments before reporting success.

6. Handle failures honestly.
   - On a `400`, correct a documented field placement or limit before at most one justified retry.
   - On `401` or `403`, stop for authentication or permission issues. On `404`, report the missing assistant, tool, or Squad. On `5xx`, report the service failure.
   - If a sequence partially succeeds, list the IDs created so the user can review or clean them up. Do not continue creating dependent resources after a fatal error.

## Persistent Squad Payload

Use verified IDs only:

```json
{
  "name": "Support Squad",
  "members": [
    { "assistantId": "<verified-triage-assistant-id>" },
    { "assistantId": "<verified-billing-assistant-id>" },
    { "assistantId": "<verified-technical-assistant-id>" }
  ]
}
```

The first member is the entry assistant. Handoff tools belong on the relevant source assistants; Squad membership alone does not define every transition.

## Handoff Payload

```json
{
  "type": "handoff",
  "function": { "name": "handoff_to_billing" },
  "destinations": [
    {
      "type": "assistant",
      "assistantId": "<verified-billing-assistant-id>",
      "description": "The caller needs billing, invoice, or payment help.",
      "contextEngineeringPlan": {
        "type": "userAndAssistantMessages"
      },
      "variableExtractionPlan": {
        "schema": {
          "type": "object",
          "properties": {
            "accountNumber": { "type": "string" }
          }
        }
      }
    }
  ]
}
```

Placeholders are acceptable in templates, never in live requests. Read [Squad Configuration](references/squad-configuration.md) for transient Squads, context transfer, version pins, and safe Squad updates. Read [Squad API Examples](references/api-examples.md) when the user requests TypeScript, Python, or cURL implementation code.

## Update Safely

Send only the changed top-level fields to `PATCH /squad/{id}`. Omit `members` for a name-only or other non-member update. When the requested change affects member order, membership, version pins, assistant overrides, or handoff destinations:

1. `GET /squad/{id}`.
2. Copy the complete ordered `members` array and current `membersOverrides` when it must also change.
3. Apply only the requested change, preserving each member's `assistantId` or inline assistant, `assistantVersion`, `assistantOverrides`, and any documented destination fields already present.
4. Patch the complete merged `members` array plus only the other changed top-level fields.
5. Re-fetch and verify order, entry member, pins, overrides, and handoffs.

## Public Sources

- [Introduction to Squads](https://docs.vapi.ai/squads)
- [Handoff tool](https://docs.vapi.ai/squads/handoff)
- [Passing data between assistants](https://docs.vapi.ai/squads/passing-data-between-assistants)
- [Squad API reference](https://docs.vapi.ai/api-reference/squads/get)

Referenced files: 3

create-structured-output9.64 KB

View saved version →

---
name: create-structured-output
description: Design, create, inspect, update, attach, detach, preview, execute, and verify reusable Vapi Structured Outputs through public API or Server SDK workflows. Use for post-call extraction, typed call artifacts, AI-versus-regex extraction, JSON Schema design, backfilling existing calls, or retrieving structured results programmatically.
license: MIT
---

# Vapi Structured Output Creation

Build the smallest reusable post-call extraction that represents the user's actual downstream contract. Keep definition creation, assistant attachment, execution, and result retrieval separate: success at one stage does not prove the next stage occurred.

## Source and Safety Rules

- Use the configured Vapi documentation MCP when available. Otherwise use current public Vapi API documentation and [API Examples](references/api-examples.md). Revalidate request fields and SDK methods before final implementation.
- Use a private Vapi API key only on a trusted server. Read it from `VAPI_API_KEY`; never print, request in chat, or embed it in source, client-side code, or examples.
- Never invent resource IDs, call IDs, extraction fields, enum values, data-retention requirements, or customer data.
- Do not enable `compliancePlan.forceStoreOnHipaaEnabled` unless the user explicitly requests it and confirms that the output cannot contain PHI or other sensitive data.
- Treat call transcripts, messages, tool results, and extracted values as sensitive customer data. Minimize what is logged or reproduced.

## Procedure

1. Choose the output mode.
   - For a schema, payload, review, or implementation example, return an artifact without calling Vapi. State that nothing was saved, attached, or executed.
   - For a reusable saved definition, use `POST /structured-output` only when the user asks to create or save it and credentials are available.
   - For a one-call experiment that does not need a saved definition, pass a transient `structuredOutput` to `POST /structured-output/run` with `previewEnabled: true`.
   - Treat attachment, detachment, and execution against existing calls as separate requested actions. Do not infer them from creation alone.

2. Define the extraction contract.
   - Identify the downstream consumer, required fields, optional fields, allowed categories, formats, and behavior when evidence is absent or ambiguous.
   - Ask only for missing facts that materially change the schema. State safe assumptions for the rest.
   - Split unrelated outputs when they have different consumers, retention policies, or iteration cycles. Keep one output when the fields form one stable business record.

3. Choose AI or regex.
   - Use `type: "ai"` for meaning, classification, summarization, sentiment, outcome detection, normalization, or facts expressed in varied language.
   - Use `type: "regex"` only for deterministic transcript matching with a stable pattern. Use RE2-compatible syntax and choose a top-level schema type that matches the documented regex result: boolean, string, number/integer, or array.
   - Do not use regex to infer meaning. Do not use AI when a literal, stable pattern is the entire requirement.

4. Design the smallest useful JSON Schema.
   - Include only fields the caller can provide or the call evidence can support.
   - Add concise descriptions that distinguish semantically similar fields.
   - Use `enum` for a closed category set, `format` or `pattern` for externally validated strings, and numeric bounds when the business contract defines them.
   - Mark a field required only when every valid call should produce it. Make conditionally available values optional instead of forcing guesses.
   - Prefer a primitive schema for a single value and an object only for a cohesive record. Avoid deep nesting unless the downstream contract needs it.
   - Validate the schema with a standard JSON Schema validator before sending it.

5. Create, inspect, or update the definition.
   - Keep saved names between 1 and 40 characters.
   - On create, send `name` and `schema`; add `type`, `description`, `regex`, `model`, or `compliancePlan` only when intentional.
   - On inspect, resolve the exact resource with list filters or a verified ID, then use `GET /structured-output/{id}`. Do not guess from a partial name.
   - On update, read the current definition first and send only fields that should change. Use `schemaOverride=true` only when intentionally changing the schema's top-level type; otherwise do not use it to bypass schema safety.
   - Re-fetch after mutation and compare the requested fields. A successful HTTP status without the expected returned state is not verified success.

6. Attach or detach safely.
   - Prefer the saved Structured Output's documented `assistantIds` relationship for attachment. Read its current `assistantIds`, add or remove exactly the resolved assistant ID, and preserve every unrelated ID.
   - Patch only `assistantIds` on the Structured Output for this operation. Re-fetch the Structured Output and assistant; verify the relationship and the assistant's `artifactPlan.structuredOutputIds` when returned.
   - If the implementation instead patches the assistant, first read the assistant and send the complete existing `artifactPlan` with only `structuredOutputIds` changed. Preserve recording, logging, transcript, scorecard, storage, and other artifact settings.
   - Do not claim that creating a definition attached it. Do not claim that detaching deleted it or removed results already stored on past calls.

7. Preview before broad execution.
   - Use `POST /structured-output/run` with one real call ID and `previewEnabled: true`. Supply either `structuredOutputId` or a transient `structuredOutput`, not both.
   - Confirm the selected call contains representative evidence and that the returned value satisfies the schema and business meaning.
   - State that preview does not update the call artifact.
   - If extraction is wrong, simplify the schema or improve descriptions before changing models or custom extraction prompts.

8. Execute or backfill only when requested.
   - Use `previewEnabled: false` or omit it to update call artifacts. Pass no more than the currently documented maximum of 100 call IDs per request.
   - Before a multi-call run, state the exact output, call count, and that existing values for this output may be replaced while other structured-output values remain.
   - Use only call IDs supplied by the user or returned by a verified public API query. Report partial failures by call ID; do not imply an all-or-nothing transaction.

9. Retrieve and verify results.
   - After a normal attached call finishes, allow for post-call processing before checking the call.
   - Retrieve each call with `GET /call/{id}` and read `call.artifact.structuredOutputs[structuredOutputId].result`.
   - Validate the result against the intended schema and inspect representative source evidence before calling it accurate. Schema validity proves shape, not factual correctness.
   - Report separately: definition saved, assistant linked, preview returned, call artifact updated, and result validated. Mention only stages actually verified.

## Error Handling

- On `400`, inspect the response for schema, regex, model, relationship, or run constraints. Correct one unambiguous documented issue and retry once; never repeat an unchanged request.
- On `401` or `403`, stop and report authentication or permission failure.
- On `404`, report the missing Structured Output, assistant, or call and identify the exact unresolved ID.
- On `409`, re-read current state before deciding whether the intended relationship or update already exists.
- On `429` or `5xx`, preserve the request context, report the service condition, and do not claim success.
- If a result is absent, distinguish processing delay, missing attachment, disabled artifact storage, insufficient call evidence, and extraction failure before recommending a change.

## API Implementation Examples

Read [API Examples](references/api-examples.md) when implementation code is needed. Use the official TypeScript or Python Server SDK only after confirming the generated method in its current official reference; use direct REST when SDK syntax is unavailable or unstable.

## Output Contract

Return only the sections relevant to the request:

- Mode: artifact-only, saved definition, relationship change, preview, or artifact-writing run
- Assumptions or blocking questions
- Final schema and Structured Output configuration
- Created or updated resource ID and verified fields, when mutated
- Attachment state and preserved relationships, when changed
- Preview or execution result, affected call IDs, and whether artifacts changed
- Retrieved result plus schema and evidence limitations
- Remaining configuration or validation work

## Public Sources

- [Structured Outputs quickstart](https://docs.vapi.ai/assistants/structured-outputs-quickstart/)
- [Create Structured Output API](https://docs.vapi.ai/api-reference/structured-outputs/structured-output-controller-create)
- [List Structured Outputs API](https://docs.vapi.ai/api-reference/structured-outputs/structured-output-controller-find-all)
- [Get Structured Output API](https://docs.vapi.ai/api-reference/structured-outputs/structured-output-controller-find-one)
- [Update Structured Output API](https://docs.vapi.ai/api-reference/structured-outputs/structured-output-controller-update)
- [Run Structured Output API](https://docs.vapi.ai/api-reference/structured-outputs/structured-output-controller-run)
- [Get Call API](https://docs.vapi.ai/api-reference/calls/get/)
- [Official TypeScript Server SDK reference](https://github.com/VapiAI/server-sdk-typescript/blob/main/reference.md)
- [Official Python Server SDK reference](https://github.com/VapiAI/server-sdk-python/blob/main/reference.md)

Referenced files: 2

create-tool7.3 KB

View saved version →

---
name: create-tool
description: Select, define, create, inspect, update, attach, detach, and verify reusable Vapi tools through the public API. Use for native call-control tools, supported provider integrations, API Request tools, custom function tools, MCP tools, tool messages, credentials, or configuration-preserving assistant attachment changes.
license: MIT
---

# Vapi Tool Management

Choose the documented tool type that directly provides the requested capability. Default to a payload or implementation plan unless the user explicitly requests a live Vapi mutation.

## Safety and Source Rules

- Verify the type and every field against the current [Create Tool API](https://docs.vapi.ai/api-reference/tools/create), public OpenAPI schema, or type-specific public guide before using it.
- Never imitate a documented Vapi capability with a custom function tool.
- Never invent an endpoint, request schema, destination, phone number, assistant ID, tool ID, integration connection, credential, or secret.
- Keep secrets in Vapi credentials or the user's backend. Treat an MCP server URL containing a token as a credential.
- Distinguish tool configuration, assistant attachment, provider connection, and external implementation. They are separate deliverables and success in one does not imply success in another.

## Select the Tool Family

| Need | Select |
|---|---|
| End calls, transfer calls, hand off between assistants, send DTMF or SMS, make a SIP request, or handle voicemail | The matching native Vapi tool |
| Use a publicly documented Google Calendar, Google Sheets, Slack, GoHighLevel, or other supported provider action | The exact integration tool after resolving its connection and required resource |
| Call a known HTTP endpoint with a declarative method, URL, headers, and body | `apiRequest` |
| Send a model-selected function call to custom backend logic that implements Vapi's callback contract | `function` |
| Discover and use tools from an existing MCP server | `mcp` with the default Streamable HTTP transport |

Do not choose `function` merely because the model invokes the capability. Native, integration, API Request, and MCP tools are also model-invoked.

Do not proactively recommend or create a Code Tool (`type: "code"`); it is not generally available on most accounts. Prefer `apiRequest` for a known HTTP endpoint or `function` with the user's `server.url` for user-hosted callback logic. Discuss a Code Tool only when the user explicitly asks about it, and do not present it as the recommended option.

Read [Tool Type Selection](references/tool-types.md) before building a payload. Read only the section for the selected family.

## Procedure

1. Determine the execution mode.
   - Return JSON, code, or a contract when the user asks for a draft or does not clearly authorize a live mutation.
   - Call the Vapi API only when the user explicitly asks to create, update, attach, or detach and `VAPI_API_KEY` is available.
   - If the key is unavailable, return ready artifacts and local commands without asking the user to paste it into chat.

2. Inspect before creating.
   - Use `GET /tool` and match any supplied name and capability to existing tools.
   - Reuse one suitable existing tool when the match is unambiguous and the user does not require a new resource.
   - If several tools plausibly match, ask the user to choose. Never guess an ID.
   - Use `GET /tool/{id}` before updating an existing tool.

3. Resolve the capability and dependencies.
   - Select the tool family using the table above and current public documentation.
   - Resolve every required endpoint, destination, provider connection, calendar, spreadsheet, channel, credential, or MCP server before a live create.
   - If one value blocks a valid tool, show the useful proposed contract first and ask only for that value.

4. Build the smallest valid payload.
   - Give the model a concise, specific description of when to invoke the tool.
   - For types with `function.name`, use 1–64 characters matching `^[a-zA-Z0-9_-]+$`. Generate a stable descriptive name when the user does not supply one.
   - For `apiRequest`, validate its top-level `name`, method, URL, headers, body schema, credentials, and timeout against the current public schema.
   - Define only parameters the model must supply. Keep trusted or secret values outside the model-visible schema.
   - Omit spoken `messages` unless progress feedback is useful. When included, use only types currently accepted by the selected tool schema, such as `request-start`, `request-response-delayed`, `request-complete`, and `request-failed`.

5. Create or update safely.
   - Before a production-affecting mutation, recap the type, capability, external dependencies, and target unless the user's current instruction already unambiguously authorizes that exact mutation.
   - Create with `POST /tool`. Validate the returned `id`, type, callable name where applicable, and requested configuration.
   - For an update, send the current `type` and only changed top-level fields to `PATCH /tool/{id}`. When changing a nested object, deep-merge the requested change into that object from the fetched tool and send the merged nested object so its omitted keys are not lost. Do not resend unchanged top-level fields or response-only fields.
   - Re-fetch the tool and verify the result. Creating or updating a tool does not attach it to an assistant.

6. Attach or detach without losing assistant configuration.
   - Read [Assistant Attachments](references/assistant-attachments.md) before changing an assistant.
   - `GET /assistant/{id}`, copy the complete current `model`, merge the tool ID into or remove it from `model.toolIds`, and preserve `model.tools` plus every unrelated model field.
   - Send the complete merged model to `PATCH /assistant/{id}`. Never patch a hand-written partial model.
   - Re-fetch the assistant and verify both the requested membership and the preserved model configuration.

7. Implement external behavior only when requested.
   - For `apiRequest`, Vapi executes the configured HTTP request; do not also build a function callback server.
   - For `mcp`, the MCP server supplies the callable tools; do not duplicate them as individual Vapi function tools.
   - For a custom `function` whose backend must be built, read [Function Tool Server](references/function-tool-server.md). Do not load that reference for other tool families.

8. Handle failures honestly.
   - On `400`, correct a documented shape or validation error before at most one justified retry.
   - On `401` or `403`, stop for authentication or permission issues. On `404`, report the missing tool, assistant, destination, or dependency. On `5xx`, report the service failure.
   - Never claim creation, update, attachment, detachment, provider connection, or backend implementation succeeded until the associated operation is verified.

## API Implementation Examples

Read [Tool API Examples](references/api-examples.md) when the user requests TypeScript, Python, or cURL implementation code. Read current tool and assistant state before update or attachment changes. Placeholders are acceptable in draft artifacts, never in live requests.

## Public Sources

- [Create Tool API](https://docs.vapi.ai/api-reference/tools/create)
- [Default tools](https://docs.vapi.ai/tools/default-tools)
- [Custom tools](https://docs.vapi.ai/tools/custom-tools)
- [MCP integration](https://docs.vapi.ai/tools/mcp)

Referenced files: 5

setup-api-key2.91 KB

View saved version →

---
name: setup-api-key
description: Guide users through obtaining and configuring a Vapi API key. Use when the user needs to set up Vapi, when API calls fail due to missing keys, or when the user mentions needing access to Vapi's voice AI platform.
license: MIT
---

# Vapi API Key Setup

Guide the user through obtaining and configuring a Vapi API key for the voice AI platform.

## Workflow

### Step 1: Request the API key

Tell the user:

> To set up Vapi, open the API keys page in the Vapi Dashboard: https://dashboard.vapi.ai/org/api-keys
>
> (Need an account? Create one at https://dashboard.vapi.ai/signup first)
>
> If you don't have an API key yet:
> 1. Click **"Create Key"**
> 2. Name your key (e.g., "development")
> 3. Copy the key immediately — it is only shown once
>
> Do not paste a private API key into this chat. Save it locally using the steps below, then tell me when the file is ready.

Then wait for the user to confirm that the local environment file is ready. Do not ask them to send or display the key.

### Step 2: Validate and configure

Once the user confirms the key is stored locally:

1. **Confirm the key is available without printing it.** Prefer an existing environment variable. Otherwise, ask the user to save it as `VAPI_API_KEY` in a local `.env.local` file using their editor. Never display the file contents.

2. **Validate the key** by making a request from the environment where it is loaded:
   ```bash
    curl -s -o /dev/null -w "%{http_code}" https://api.vapi.ai/assistant \
      -H "Authorization: Bearer $VAPI_API_KEY"
   ```

3. **If validation fails** (non-200 response):
   - Tell the user the API key appears to be invalid
   - Ask them to double-check and try again
   - Remind them of the URL: https://dashboard.vapi.ai/org/api-keys

4. **If validation succeeds**, confirm that the local environment file contains this variable without showing its value:
   ```
   VAPI_API_KEY=<the-api-key>
   ```

5. **Confirm success:**
   > Your Vapi API key is configured locally as `VAPI_API_KEY`.
   >
   > You can now use Vapi's API to create assistants, make calls, and build voice AI agents.
   >
   > Keep this key safe — do not commit it to version control.

### Step 3: Verify .gitignore

Check whether `.gitignore` protects local environment files. If not, add:
```
.env*
!.env.example
```

## Environment Variable

All Vapi skills expect the API key in the `VAPI_API_KEY` environment variable. The base URL for all API requests is:

```
https://api.vapi.ai
```

Authentication is via Bearer token:
```
Authorization: Bearer $VAPI_API_KEY
```

## Additional Resources

Vapi provides a **documentation MCP server** that gives compatible AI agents access to the Vapi knowledge base. Use its documentation search for advanced configuration, troubleshooting, SDK details, and anything beyond this skill.


See the [Vapi MCP integration guide](https://docs.vapi.ai/cli/mcp) for setup instructions across supported agents.

Referenced files: 1

setup-webhook8.06 KB

View saved version →

---
name: setup-webhook
description: Configure Vapi server URLs and webhooks to receive real-time call events, transcripts, tool calls, and end-of-call reports. Use when setting up webhook endpoints, building tool servers, or integrating Vapi events into your application.
license: MIT
---

# Vapi Webhook / Server URL Setup

Configure server URLs to receive real-time events from Vapi during calls — transcripts, tool calls, status changes, and end-of-call reports.

> **Setup:** Ensure `VAPI_API_KEY` is set. See the `setup-api-key` skill if needed.

## Overview

Vapi uses "Server URLs" (webhooks) to communicate with your application. Unlike traditional one-way webhooks, Vapi server URLs support bidirectional communication — your server can respond with data that affects the call.

## Where to Set Server URLs

### On an Assistant

```bash
curl -X PATCH https://api.vapi.ai/assistant/{id} \
  -H "Authorization: Bearer $VAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "server": {
      "url": "https://your-server.com/vapi/webhook",
      "credentialId": "cred_abc123"
    }
  }'
```

Create the optional `credentialId` in **Dashboard > Custom Credentials**. Omit it only for a deliberately public endpoint.

### On a Phone Number

Phone-number updates also use a `server` object with `url` and optional `credentialId`. When updating through the API, first retrieve the number and preserve its existing `provider` discriminator in the PATCH body. The dashboard is the safest choice when the provider is unknown.

### At the Organization Level

Set a default server URL in the Vapi Dashboard under **Settings > Server URL**.

Priority order: Tool server URL > Assistant server URL > Phone Number server URL > Organization server URL.

## Event Types

| Event | Description | Expects Response? |
|-------|-------------|-------------------|
| `assistant-request` | Request for dynamic assistant config | Yes — return assistant config |
| `tool-calls` | Assistant is calling a tool | Yes — return tool results |
| `status-update` | Call status changed | No |
| `transcript` | Real-time transcript update | No |
| `end-of-call-report` | Call completed with summary | No |
| `hang` | Assistant failed to respond | No |
| `speech-update` | Speech activity detected | No |

## Webhook Server Example (Express.js)

```typescript
import express from "express";
const app = express();
app.use(express.json());

app.post("/vapi/webhook", (req, res) => {
  const { message } = req.body;

  switch (message.type) {
    case "assistant-request":
      // Dynamically configure the assistant based on the caller
      res.json({
        assistant: {
          name: "Dynamic Assistant",
          firstMessage: `Hello ${message.call.customer?.name || "there"}!`,
          model: {
            provider: "openai",
            model: "gpt-4.1",
            messages: [
              { role: "system", content: "You are a helpful assistant." },
            ],
          },
          voice: { provider: "vapi", voiceId: "Elliot", version: 2 },
          transcriber: { provider: "deepgram", model: "nova-3", language: "en" },
        },
      });
      break;

    case "tool-calls":
      // Handle tool calls from the assistant
      const results = (message.toolCallList || []).map((toolCall: any) => ({
        toolCallId: toolCall.id,
        result: handleToolCall(
          toolCall.name,
          toolCall.parameters || toolCall.arguments
        ),
      }));
      res.json({ results });
      break;

    case "end-of-call-report":
      // Process the call report
      console.log("Call ended:", {
        callId: message.call.id,
        endedReason: message.endedReason,
        cost: message.cost,
        analysis: message.analysis,
        artifact: message.artifact,
      });
      res.json({});
      break;

    case "status-update":
      console.log("Call status:", message.status);
      res.json({});
      break;

    case "transcript":
      console.log(`[${message.role}]: ${message.transcript}`);
      res.json({});
      break;

    default:
      res.json({});
  }
});

function handleToolCall(name: string, args: any): string {
  // Implement your tool logic here
  return `Result for ${name}`;
}

app.listen(3000, () => console.log("Webhook server running on port 3000"));
```

## Webhook Server Example (Python / Flask)

```python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/vapi/webhook", methods=["POST"])
def vapi_webhook():
    data = request.json
    message = data.get("message", {})
    msg_type = message.get("type")

    if msg_type == "assistant-request":
        return jsonify({
            "assistant": {
                "name": "Dynamic Assistant",
                "firstMessage": "Hello! How can I help?",
                "model": {
                    "provider": "openai",
                    "model": "gpt-4.1",
                    "messages": [
                        {"role": "system", "content": "You are a helpful assistant."}
                    ],
                },
                "voice": {"provider": "vapi", "voiceId": "Elliot", "version": 2},
                "transcriber": {"provider": "deepgram", "model": "nova-3", "language": "en"},
            }
        })

    elif msg_type == "tool-calls":
        results = []
        for tool_call in message.get("toolCallList", []):
            results.append({
                "toolCallId": tool_call["id"],
                "result": f"Handled {tool_call['name']}",
            })
        return jsonify({"results": results})

    elif msg_type == "end-of-call-report":
        print(f"Call ended: {message['call']['id']}")
        print(f"Summary: {message.get('analysis', {}).get('summary')}")

    return jsonify({})

if __name__ == "__main__":
    app.run(port=3000)
```

## Webhook Authentication

Use a Vapi Custom Credential and place its ID in `server.credentialId`. Vapi supports Bearer Token, OAuth 2.0 client credentials, and HMAC credentials. Verify requests according to the credential you configured; HMAC header names, algorithms, timestamps, and payload formats are configurable, so do not assume a fixed `x-vapi-signature` format.

For a bearer credential, compare the incoming `Authorization: Bearer <token>` value with the token stored securely by your server. Never put the secret itself in an assistant or phone-number payload.

## Local Development

Use the Vapi CLI with a public tunnel. The CLI forwards from port 4242 to your app, but it does not create the public URL itself:

```bash
# Install the CLI
curl -sSL https://vapi.ai/install.sh | bash

# Terminal 1: expose the CLI listener
ngrok http 4242

# Terminal 2: forward events from the CLI to your app
vapi listen --forward-to localhost:3000/vapi/webhook
```

Set the Vapi server URL to the public ngrok URL. To skip the CLI and tunnel directly to the Express or Flask server instead:

```bash
ngrok http 3000
# Copy the ngrok URL and set it as your server URL
```

## End-of-Call Report Fields

The `end-of-call-report` event includes:

| Field | Description |
|-------|-------------|
| `call` | Full call object with metadata |
| `endedReason` | Why the call ended |
| `artifact` | Recording, transcript, messages, and other enabled artifacts |
| `analysis` | Configured summaries, structured data, and success evaluation |
| `cost` | Total call cost |
| `startedAt` / `endedAt` | Call timing, when included |

## References

- [Common Server URL Events](references/webhook-events.md) — Common event payloads and responses
- [Setting Server URLs](https://docs.vapi.ai/server-url/setting-server-urls) — Placement and priority
- [Server Authentication](https://docs.vapi.ai/server-url/server-authentication) — Custom Credentials
- [Local Development](https://docs.vapi.ai/server-url/developing-locally) — Testing webhooks locally

## Additional Resources

Vapi provides a **documentation MCP server** that gives compatible AI agents access to the Vapi knowledge base. Use its documentation search for advanced configuration, troubleshooting, SDK details, and anything beyond this skill.


See the [Vapi MCP integration guide](https://docs.vapi.ai/cli/mcp) for setup instructions across supported agents.

Referenced files: 2

simulations9.25 KB

View saved version →

---
name: simulations
description: Design, create, run, monitor, and maintain Vapi Simulations for assistants and squads. Use for simulation personalities, scenarios, structured-output success criteria, simulations, suites, chat or voice runs, tool mocks, target variables, lifecycle webhooks, regression coverage, CI quality gates, run-result analysis, and simulation API validation errors. Do not use for fixed-turn mock-conversation Evals unless the user is deciding between Evals and Simulations.
license: MIT
---

# Vapi Simulations

Build realistic conversation tests in five layers: a personality controls the AI tester, a scenario defines its intent and measurable outcomes, a simulation pairs them, a suite groups simulations, and a run executes them against an assistant or squad.

## Source and Safety Rules

- Verify live payloads against the current Vapi documentation MCP, API reference, or public OpenAPI before sending them. Simulations use the `/eval/simulation` API family.
- Never print, request in chat, or embed API keys, provider secrets, credential values, private webhook URLs, or real customer data.
- Treat running a simulation as an external action. It can consume credits, use concurrency, send webhooks, and call the target's real tools unless they are mocked.
- Do not run, cancel, update, or delete resources unless the user clearly requests that operation. Draft configurations when mutation is not requested.
- Resolve every assistant, squad, personality, scenario, simulation, suite, tool, structured-output, and credential ID from user input or the API. Never invent an ID.
- Do not create legacy Test Suites. Use Evals for deterministic turn-by-turn checks and Simulations for dynamic conversations over chat or voice.

## Procedure

1. Choose the test type and execution mode.
   - Use Simulations for multi-turn behavior, personality variation, squad handoffs, realistic tool paths, or audio behavior.
   - Use Evals instead when the requirement is an exact response, regex, fixed mock conversation, or precise tool-call argument check.
   - Return a test plan or payload when the user asks to design, draft, review, or explain. Perform live mutations only when explicitly requested and `VAPI_API_KEY` is available.

2. Inspect the target and existing test resources.
   - Fetch the assistant or squad and identify its core paths, guardrails, tools, variables, languages, and failure behavior.
   - List existing personalities, scenarios, simulations, suites, and reusable structured outputs before creating duplicates.
   - Reuse an existing resource only when its intent and configuration match unambiguously. Otherwise create a clearly named new resource or ask the user to choose among plausible matches.

3. Design coverage before payloads.
   - Start with one smoke simulation for the core path, one or two required Boolean outcomes, chat transport, and one iteration.
   - Add regression simulations for repaired defects. Add separate edge cases for ambiguity, interruption, refusal, unavailable dependencies, failed tools, escalation, and handoffs.
   - Keep scenario intent, personality behavior, and evaluation criteria independent so each can be reused.
   - Name resources by behavior and expected outcome, not implementation details.

4. Define the personality.
   - Prefer a suitable existing personality when available.
   - When creating one, provide a complete valid assistant configuration for the AI tester. Put stable temperament, speaking style, and caller behavior in its system prompt; put the situation-specific goal in the scenario.
   - Use the `create-assistant` skill to assemble or validate the personality's assistant configuration when available.
   - Configure voice and transcriber only when voice runs need them. Chat runs use the personality's model but skip its audio path.

5. Define the scenario and evaluations.
   - Write `instructions` as the AI tester's intent and facts. Describe the goal and constraints without scripting the target assistant's answer.
   - Make each evaluation measure one observable outcome. Prefer descriptive Boolean outputs for pass/fail facts and numeric outputs for thresholds.
   - Provide either `structuredOutputId` or inline `structuredOutput`, never both. Inline outputs require `name` and a JSON `schema`.
   - Match the expected `value` type to the evaluated primitive. Use `=` or `!=` for Boolean and string; numeric types also support `>`, `<`, `>=`, and `<=`.
   - Keep important criteria `required: true`. Use optional criteria only for diagnostics that must not fail the simulation.
   - Object structured outputs may be evaluated through a primitive leaf using `path`. Do not compare an object or array directly.

6. Isolate side effects and runtime context.
   - Inspect the target's configured tools before every run. Mock any tool whose real execution could write data, contact people, spend money, or make the test non-deterministic.
   - Match each `toolMocks[].toolName` exactly. The mock `result` is always a string; encode JSON as a string when the target expects JSON-shaped output.
   - Assume every unmocked tool remains live in both chat and voice simulations.
   - Put test values for `{{variables}}` in `targetOverrides.variableValues`. Use synthetic data and keep secrets in Vapi credentials.
   - Configure `simulation.run.started` or `simulation.run.ended` hooks only when requested. Prefer `server.credentialId` to inline authorization headers.

7. Create and verify reusable resources.
   - Create in dependency order: personality and scenario, then simulation, then optional suite.
   - Require `201` for create operations. Verify returned IDs and the fields that define the test.
   - For updates, fetch the current resource first. Omit unrelated scalar fields and send the complete intended value for any array being changed; suite `simulationIds` and `targetAssignments` replace their existing arrays.
   - Re-fetch after update. Deleting a suite or other simulation resource is permanent; verify the exact ID and dependency impact first.

8. Run deliberately.
   - Prefer `vapi.webchat` for fast prompt, tool, and conversation-logic iteration.
   - Use `vapi.websocket` for speech recognition, voice output, interruptions, recordings, or final end-to-end validation.
   - Start with one iteration. Increase iterations only to measure behavioral consistency after a single run is valid.
   - Before sending the run, recap the target, simulations or suite, transport, iterations, tool mocks, and any remaining live side effects.
   - Create the run with `POST /eval/simulation/run` and require `201`. Return the run ID and dashboard `url` when present.

9. Monitor and diagnose results.
   - Poll `GET /eval/simulation/run/{id}` until `status` is `ended`; do not treat `queued` or `running` as success.
   - Fetch `GET /eval/simulation/run/{id}/item` and inspect every item. A passing group has items to evaluate, zero failed or canceled items, and every required evaluation passes.
   - Report actual versus expected values, extraction errors, skipped evaluations, failure reasons, transcript evidence, transport, and iteration number.
   - Diagnose the failing layer before changing the assistant: target runtime failure, scenario ambiguity, personality behavior, tool mock mismatch, structured-output extraction, or genuine assistant behavior.
   - Keep the evaluation stable when fixing the assistant. Change expected criteria only when the business requirement changed.

10. Handle failures honestly.
   - On `400`, compare the request with the current schema and correct one unambiguous validation issue before at most one retry.
   - On `401` or `403`, stop for authentication or permission. On `404`, report the missing dependency. On `409` or concurrency errors, inspect `GET /eval/simulation/concurrency` and active runs. On `5xx`, report the service failure.
   - Cancel only queued or running groups or items. Never claim a run, cancellation, mutation, or pass succeeded until the corresponding API response is verified.

## API Implementation

Read [Simulation API Reference](references/api-reference.md) before producing REST code, making a live request, configuring hooks or mocks, or interpreting run results. Use direct REST unless the current official Vapi SDK documentation explicitly exposes the required simulation resource and method; never invent SDK method names.

## Output Contract

Return only the sections relevant to the request:

- Test strategy: target behavior, coverage, and why Simulation rather than Eval
- Resource plan: personality, scenario, evaluations, simulation, and suite
- Side-effect review: mocked tools, live tools, hooks, variables, transport, iterations, and expected cost/concurrency impact
- Save-ready JSON or implementation code
- Created resource IDs and verified fields, when mutations succeeded
- Run ID, dashboard URL, status, item counts, and per-evaluation evidence, when a run was requested
- Failure diagnosis and the smallest recommended next change

## Public Sources

- [Simulations overview](https://docs.vapi.ai/observability/simulations-overview)
- [Simulations quickstart](https://docs.vapi.ai/observability/simulations-quickstart)
- [Simulations advanced](https://docs.vapi.ai/observability/simulations-advanced)
- [Manage simulations](https://docs.vapi.ai/observability/simulations-manage)
- [Vapi API reference index and OpenAPI](https://docs.vapi.ai/llms.txt)

Referenced files: 2

vapi-prompt-builder10.6 KB

View saved version →

---
name: vapi-prompt-builder
description: Create, improve, or audit Vapi voice agent and Squad system prompts for production phone and web based voice agents. Use when the user wants help designing a Vapi assistant prompt, multi-assistant Squad prompt set, refining an existing prompt, creating prompt sections, building an intake or handoff workflow, improving tool-use instructions, adding guardrails, or optimizing voice-agent behavior for brevity, turn-taking, error handling, caller data collection, escalation, handoffs, and spoken formatting.
license: MIT
---

# Vapi Prompt Builder

## Core Workflow

Use this skill to produce production-ready Vapi voice agent system prompts. Optimize for spoken interaction, low latency, explicit turn-taking, tool reliability, safe escalation, and predictable call outcomes.

Start by classifying the request:

- Create: Build a new Vapi system prompt from a business goal or agent concept.
- Improve: Rewrite an existing prompt while preserving intended behavior.
- Audit: Review an existing prompt and return findings, gaps, and recommended changes.

Then resolve deployment shape:

- Single assistant: one Vapi assistant owns the call flow.
- Squad: multiple specialized assistants hand off between each other.

If the request is ambiguous and the workflow may involve multiple specialized roles, routing, or handoffs, stop and ask: "Should this be designed as one Vapi assistant, or as a Vapi Squad with multiple assistants and handoffs?" Do not draft until this is resolved.

Read `references/squad-prompting.md` when the user mentions squads, Handoff Tools, handoffs between assistants or squads, silent handoffs, dynamic routing, router/triage assistants, specialist assistants, or a workflow that is too broad for one reliable prompt.

Before writing or preserving workflow details, run a capability-grounding pass. Verify that every claimed input, artifact, tool action, side effect, and example is possible through the actual call channel, runtime context, visible Vapi tools, or explicitly described backend behavior. Read `references/capability-grounding.md` when the prompt mentions files, uploads, attachments, documents, screenshots, browser/web actions, async jobs, integrations, or any action the phone caller cannot perform directly during the call.

Read `references/voice-prompt-patterns.md` when creating or substantially rewriting a prompt, or when the request involves voice style, examples, tool behavior, information collection, or call endings.

Run an identifier-hygiene pass before finalizing. Read `references/identifier-hygiene.md` when the prompt uses tool names, resource IDs, snake_case identifiers, placeholder names, or generic values such as `the_tool_name`.

Run a Vapi trust-boundary pass when the prompt, tools, or configuration mention authentication, caller identity, account IDs, permissions, secrets, secure values, verified values, static parameters, `function.parameters`, dynamic variables, `variableExtractionPlan`, tool aliases, handoff arguments, or sensitive tool responses. Read `references/vapi-security-trust.md` before recommending where those values belong.

Run a Vapi readiness pass before presenting an artifact as ready to build or configure. Read `references/vapi-readiness.md` when the output includes tools, structured outputs, dynamic variables, Squads, handoffs, pronunciation guidance, testing/evals, or configuration notes. Separate confirmed Vapi configuration from assumptions and missing deployment inputs.

## Intake

Ask the fewest questions needed to make a useful first draft. Prefer a complete draft with clear assumptions over a long upfront questionnaire.

Always collect or infer:

- Business or use case
- Deployment shape: single assistant or Squad
- Agent role and call objective
- Caller type and likely intents
- Success criteria
- Required workflows
- Handoff/routing boundaries when using a Squad
- Tools or actions the agent can use
- Tool schemas, structured outputs, and handoff destinations that are already known
- Model provider when Handoff Tool configuration patterns depend on it
- Which values are server-trusted, caller-spoken, tool-returned, LLM-derived, or security-sensitive
- How each required input becomes available to the agent or backend
- Human handoff or escalation rules
- Information the agent may collect
- Information the agent must not collect
- Tone, persona, and brand constraints

Read `references/intake-question-bank.md` when the request is vague, high-risk, or missing several essentials.

If the user provides an existing prompt, inspect it before asking questions. Ask only about missing facts, contradictions, tool behavior, compliance constraints, or ambiguous handoff rules.

## Prompt Sections

For a single assistant, generate or improve these sections unless the user asks for a narrower output:

1. Identity and purpose
2. Personality and speaking style
3. Response guidelines
4. Guardrails and safety behavior
5. Context and dynamic variables
6. Workflow and intent routing
7. Tool-use rules
8. Error handling and recovery
9. Smart information collection
10. Escalation, transfer, and call ending
11. Few-shot examples

For a Squad, generate or improve:

1. Squad purpose and member map
2. Entry assistant behavior
3. One focused system prompt per assistant
4. Handoff decision rules
5. Context handoff requirements
6. Tool boundaries per assistant
7. Shared guardrails
8. Per-assistant examples, including handoff examples
9. External test scenarios for routing and context preservation

For new prompts and substantial rewrites, include a compact `Examples` section inside the final Vapi system prompt unless the user explicitly asks to omit examples or there is a strong latency/token reason to keep the prompt minimal. Do not substitute external test scenarios for in-prompt examples.

Keep the final system prompt lean. Do not include tutorial prose, rationale, or markdown intended for humans unless the user requests it. Use section headers only if they improve maintainability.

Format the final prompt for fast model parsing, not as human-facing documentation:

- Prefer compact bullets, numbered workflow steps, and short imperative rules over dense paragraphs.
- Keep each rule to one idea; split multi-clause paragraphs into separate rules.
- Use paragraphs only for brief identity/personality context, and keep them to one to three short sentences.
- Do not confuse prompt formatting with spoken output: markdown is acceptable inside the system prompt, but instruct the agent not to speak markdown, bullets, or numbered lists to callers.
- Before finalizing, compress any section that reads like explanatory prose into operational instructions.

## Example Design

Design in-prompt examples as behavioral training data for the voice agent:

- Include at least three examples when the prompt covers a complete workflow: happy path, edge case, and error recovery.
- Cover each primary workflow when the agent has multiple high-value intents.
- Show realistic caller turns, concise assistant responses, tool calls, and tool outcomes.
- Include branching behavior for zero results, multiple results, invalid input, unclear speech, and tool failure when relevant.
- Ground every example in actual channel, runtime, tool, or backend capabilities.
- Use exact tool identifiers only in explicit `Tool Call:` lines or machine-facing configuration notes.
- Keep examples short enough to justify their latency cost.
- Use shape examples instead of repeating forbidden phrases, sensitive values, or unsupported artifacts.

Keep external test scenarios separate from the final prompt. Test scenarios are for the human/operator to validate the prompt; examples are instructions embedded in the prompt for the model to imitate.

## Voice Optimization

Before returning the final prompt, run a voice-agent pass:

- Keep caller-facing turns short, usually one or two sentences.
- Ask one question at a time.
- Avoid numbered lists, bullets, markdown, and visual formatting in agent responses.
- Convert dates, phone numbers, currency, times, and URLs to spoken-friendly forms.
- Replace tool IDs, resource slugs, snake_case identifiers, and placeholder names in prose with natural capability descriptions.
- Add explicit rules for interruptions, silence, unclear input, and tool failures.
- Distinguish light banter from hard off-topic requests.
- Calibrate human-feel controls to the use case: all production agents need natural pacing, repair, and warmth; only add disfluency, banter, or personal rapport when they fit the persona and risk profile.
- Remove channel-impossible behaviors unless a tool or backend contract makes them real.
- Prefer deterministic Vapi configuration over prompt instructions when reliability or security matters.

## Tool and Configuration Notes

When tools are involved, review both prompt instructions and tool configuration. Flag items that should be configured outside the system prompt:

- Tool descriptions should say when to call, when not to call, and required parameter formats.
- Prompt prose should describe tools by capability. Exact tool names belong only in tool-call examples, schemas, configuration notes, or Query Tool instructions where Vapi needs the system prompt to name the search tool.
- Do not invent deployable tool schemas, structured output schemas, enum values, server URLs, or handoff destinations. Ask for them or mark them as configuration needed.
- Transfer and end-call tools need explicit descriptions.
- Slow tools should use request-start messages to fill dead air.
- Pronunciation issues should use pronunciation dictionaries when available.
- Values that must be secure, verified, or impossible for the LLM to fake should use Vapi's server-side/static-parameter patterns, not prompt text or LLM-filled schemas.
- Tool responses should be short, structured, and limited to fields the model needs.

## Output Modes

For a new prompt, return:

- Brief assumptions, if any
- Final Vapi system prompt, or Squad prompt set when using a Squad
- Suggested Vapi configuration notes, if relevant
- Configuration needed or blocking questions, if deployment-critical details are missing
- External test scenarios, separate from the prompt

For an improved prompt, return:

- Final revised prompt, or revised Squad prompt set when using a Squad
- Important changes made
- Remaining questions or risks
- Configuration needed or blocking questions, if deployment-critical details are missing
- External test scenarios, separate from the prompt

For an audit, return:

- Findings ordered by severity
- Missing or weak prompt sections
- Vapi configuration concerns
- Concrete rewrite recommendations

Read `references/review-checklist.md` before finalizing an audit or substantial rewrite.

Referenced files: 9

Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package license
MIT
Package author
Vapi
Keywords
vapi, voice-ai, agents, telephony

Declared capabilities

  • Interactive
  • Write

Package observed Oct 2, 2026.

Technical details
First seen
Sep 30, 2026 · 22:02 UTC
Last seen
Oct 2, 2026 · 18:00 UTC
Collection status
Collected

plugins_6a99b26dd5f08191ae2c40cf2f63d2b2

Download plugin data (JSON)