Skip to content

Commit 2011b05

Browse files
docs: restructure the README into a short landing page and topic guides (#70)
## Value **V.A.L.U.E. tier:** small — docs only. This restructures the README for readers arriving from the Vapi docs. Not micro: more than 200 lines and 8 files. - **Problem:** the README was 1,096 lines written for four audiences at once: newcomers, daily operators, promotion and CI admins, and coding agents. The first-run path was spread across three sections, some content appeared two or three times, and the `docs/learnings/` field guide was only mentioned in a file tree. - **Who it affects:** first-time visitors, who decide in seconds whether this is for them, and existing users looking for a specific topic. - **What changes:** - **A 275-line README**, covering: - what the repo does, and a diagram; - a five-step quick start: get a private copy, install, connect an org, deploy, test; - core concepts, including what's committed and what isn't; - a one-line command table and guide links; - the field guide, and staying up to date; - security, contributing and license. - **Getting a copy:** clone-and-repush keeps upstream history, so updates are an ordinary merge. "Use this template" (the repo is a template) needs `--allow-unrelated-histories` once. A public fork would publish the user's configuration. - **Long-form content moves verbatim** into `docs/guides/`: commands, workflows, file formats, PR checks, promotion, how it works, configuration, troubleshooting. Only heading levels and relative links change, so this PR reviews as a move; #71 edits the content. - **References** to old README sections (in `vapi-checks.yml`, `AGENTS.md`, `SECURITY.md`, `simulations.md` and the starter example) now point at the guides. ## Evidence of value - **Nothing lost:** of the old README's 795 content lines, 755 appear verbatim in the new README or a guide. The other 40 are the sections rewritten in the new README (intro, quick start, supported resources, API links) or retitled headings, and I checked each one by hand. - **Links:** all links and anchors across 45 markdown files resolve. - **Tests:** `npm test` passes, 496 tests, including the snippet test, which now reads the file formats guide. ## Testing plan - The link checker and the examples snippet test cover the moved content. - The Mermaid diagram renders on GitHub (checked on this branch's README). - **Not tested:** how the README renders on the Vapi docs site, if it's embedded there rather than linked. Stacked on #69. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
2 parents ca5d9ed + 453459c commit 2011b05

15 files changed

Lines changed: 1275 additions & 1113 deletions

File tree

‎.github/workflows/vapi-checks.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Vapi checks
33
# Runs the simulation checks in vapi-checks.yml against the PR branch's own
44
# files: each target is built inline and sent in one simulation run, so
55
# nothing is deployed. Opt in with the repository variable
6-
# VAPI_CHECKS_ENABLED=true; see "PR checks" in the README.
6+
# VAPI_CHECKS_ENABLED=true; see docs/guides/pr-checks.md.
77
#
88
# Never `pull_request_target`: the branch's code runs here, so it must only
99
# ever get this repository's secrets when the branch is this repository's.

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1032,4 +1032,4 @@ When transferring to human:
10321032
2. Create scenarios (what the simulated caller says + evaluation criteria)
10331033
3. Create simulations (pair personality + scenario)
10341034
4. Create suites (batch simulations together)
1035-
5. Run against the deployed resources with `npm run sim`, or against the local files (nothing deployed) with `npm run check` — see "PR Checks" in the README. The PR workflow runs `npm run check` on every affected PR when `VAPI_CHECKS_ENABLED=true`
1035+
5. Run against the deployed resources with `npm run sim`, or against the local files (nothing deployed) with `npm run check` — see [docs/guides/pr-checks.md](docs/guides/pr-checks.md). The PR workflow runs `npm run check` on every affected PR when `VAPI_CHECKS_ENABLED=true`

‎CONTRIBUTING.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Commit messages and PR titles follow [Conventional Commits](https://www.conventi
3737
| --- | --- |
3838
| A Vapi platform gotcha, recipe or troubleshooting guide | `docs/learnings/<topic>.md`, plus a row in [`docs/learnings/README.md`](docs/learnings/README.md) and the table in `AGENTS.md` for a new file |
3939
| A sync-engine pain point and its fix (pull, push, state, cleanup) | `improvements.md`, in its Problem → Current behavior → Risk → Current mitigation → Possible fix → Status format |
40-
| Setup or orientation for new users | `README.md` (keep it short; link to a guide for depth) |
40+
| Setup or orientation for new users | `README.md` (keep it short; put depth in `docs/guides/`) |
4141
| An example users can copy | `examples/`. Snippets in the docs that start with `# examples/<path>` must match the file exactly; `npm test` checks this. |
4242

4343
Don't edit `docs/changelog.md` here. It's a template for your own

‎README.md‎

Lines changed: 207 additions & 1106 deletions
Large diffs are not rendered by default.

‎SECURITY.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ acknowledge the report and keep you updated as we investigate.
2222
module, including in `validate`, `promote` plans and PR checks. Review them
2323
like code, and only run them from trusted branches.
2424
- **PR checks run with your key on same-repository branches.** Forked PRs get
25-
a dry run with no secrets. See "Cost and safety" in the README's
26-
PR Checks section for what a check still sends to real providers.
25+
a dry run with no secrets. See "Cost and safety" in
26+
[docs/guides/pr-checks.md](docs/guides/pr-checks.md#cost-and-safety) for
27+
what a check still sends to real providers.

‎docs/guides/commands.md‎

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Commands
2+
3+
Every command works in two modes:
4+
5+
- **Interactive** — run without arguments, get prompted for org and resources
6+
- **Direct** — pass an org slug and flags for scripting / CI
7+
8+
| Command | Interactive | Direct | One-liner |
9+
| --- | --- | --- | --- |
10+
| `npm run setup` | ✅ | — | First-time org wizard — creates `.env.<org>` and `resources/<org>/`. |
11+
| `npm run validate` | — | `npm run validate -- <org>` | Schema-check local YAML/MD with no network call. **Run before every `apply`.** |
12+
| `npm run audit` | — | `npm run audit -- <org> [--type <t>]` | Read-only drift detector — orphan local YAML, state ghosts, UUID collisions, content-identical clusters, sibling base-slug clusters, dashboard orphans, assistants with inline `model.tools`. Exit 1 on any finding; safe to wire into CI. |
13+
| `npm run promote` | — | `npm run promote -- --pipeline <name> --from <org> --to <org> [--apply]` | Plan or apply a forward-only, dependency-aware promotion defined by `promotion.yml`. |
14+
| `npm run apply` | ✅ | `npm run apply -- <org> [--force]` | **Default deploy verb.** Pull → merge → push in one safe pass; resilient against dashboard drift. |
15+
| `npm run pull` | ✅ | `npm run pull -- <org> [flags]` | Fetch remote state into local files / state file. Local-first by default — won't clobber local edits. |
16+
| `npm run push` | ✅ | `npm run push -- <org> [flags]` | Raw push without a pre-pull. Refuses by default when local YAML files lack state entries (orphan-YAML gate); pass `--allow-new-files` to bypass after confirming intent. **Skip unless you just ran `pull` and are certain state is fresh** — otherwise prefer `apply`. |
17+
| `npm run cleanup` | ✅ | `npm run cleanup -- <org> [--force --confirm <org>]` | Inspect (default) or delete orphaned remote resources. Destructive run requires `--confirm <org>`. |
18+
| `npm run rollback` | — | `npm run rollback -- <org> --list` or `--to <ISO>` | Restore from a snapshot in `.vapi-state.<org>.snapshots/` (one is written before every push/apply). |
19+
| `npm run call` | ✅ | `npm run call -- <org> -a <name>` or `-s <squad>` | Start an interactive WebSocket call against an assistant or squad. |
20+
| `npm run sim` | — | `npm run sim -- <org> --suite <name> --target <name> [--timeout <min>]` | Run a simulation suite (or specific simulations) against a deployed assistant/squad. Prints the run link; exits 0 passed, 1 failed, 3 incomplete (timeout, Ctrl-C, missing results). |
21+
| `npm run check` | — | `npm run check -- <check>\|--all [--dry-run] [--changed-since <ref>] [--budget-minutes <n>] [--json <path>]` | Run the `vapi-checks.yml` simulation checks against the files on disk: each target is built inline (tools, handoffs, judges, personalities; tools mocked fail-closed, servers dead-ended) and run in one simulation run per target, so nothing is deployed. Posts `Vapi Evals` commit statuses when run by the PR workflow. `--dry-run` builds the payloads offline (no key, nothing sent; `--print-payload` writes them). Exits 0 passed, 1 failed, 2 config or build error, 3 incomplete (timeout, interrupt, budget, billing). |
22+
| `npm run migrate` | — | `npm run migrate` | One-time, all orgs at once: slim legacy state files to pure `name → uuid` and seed the per-developer `.vapi-state-hash/` baseline store from the old hashes. Required once after upgrading to the hash-store engine — `pull`/`push`/`apply` refuse legacy-shaped state until it runs. Idempotent. |
23+
| `npm run build` | — | — | Type-check the codebase (`tsc --noEmit`). |
24+
| `npm test` | — | — | Run regression tests (`node:test`). |
25+
26+
## Interactive Mode
27+
28+
When you run a command without arguments, you get a fully interactive experience:
29+
30+
```bash
31+
npm run push
32+
# → Select org (if multiple configured)
33+
# → All resources / Let me pick…
34+
# → Searchable multi-select with git status indicators
35+
# → Confirm and execute
36+
37+
npm run pull
38+
# → Select org
39+
# → All resources / Let me pick…
40+
# → Shows which resources are already local (✔)
41+
# → "Overwrite locally modified files?" — defaults to NO (local-first)
42+
# → Confirm and execute
43+
44+
npm run cleanup
45+
# → Select org
46+
# → Dry-run preview of what would be deleted
47+
# → "Proceed with actual deletion?" — defaults to NO
48+
# → Destructive run is gated by both your confirm AND --confirm <org>
49+
```
50+
51+
Navigation:
52+
- **Type** to search/filter resources
53+
- **Space** to toggle the focused row (or toggle the whole group when the cursor is on a header)
54+
- **Ctrl+A** to select/deselect all currently-visible rows
55+
- **Ctrl+G** to toggle every item in the focused group
56+
- **→ / ←** (right / left arrow) to expand or collapse the focused group
57+
- **Enter** to confirm
58+
- **Esc** to clear the search; press again to step back to the previous prompt
59+
60+
## Direct Mode
61+
62+
Pass an org slug as the first argument to skip interactive prompts:
63+
64+
```bash
65+
# Pull everything for an org
66+
npm run pull -- my-org
67+
68+
# Force pull (overwrite local changes)
69+
npm run pull -- my-org --force
70+
71+
# Push only assistants
72+
npm run push -- my-org assistants
73+
74+
# Push a single file
75+
npm run push -- my-org resources/my-org/assistants/my-agent.md
76+
77+
# Pull with bootstrap (state only, no files written)
78+
npm run pull -- my-org --bootstrap
79+
80+
# Pull a single resource by UUID
81+
npm run pull -- my-org --type assistants --id <uuid>
82+
83+
# Call an assistant
84+
npm run call -- my-org -a my-assistant
85+
86+
# Call a squad
87+
npm run call -- my-org -s my-squad
88+
```

‎docs/guides/configuration.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Configuration
2+
3+
## Environment Variables
4+
5+
| Variable | Required | Description |
6+
| --------------- | -------- | ------------------------------------------------ |
7+
| `VAPI_PRIVATE_API_KEY` | ✅ | Vapi private API key from [Private API Keys](https://dashboard.vapi.ai/org/api-keys). The legacy name `VAPI_TOKEN` is still accepted. |
8+
| `VAPI_BASE_URL` | ❌ | API base URL (defaults to `https://api.vapi.ai`) |
9+
10+
These are stored in `.env.<org>` files, one per configured organization.

‎docs/guides/file-formats.md‎

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# File Formats
2+
3+
Every snippet below is a file from [`examples/starter/`](../../examples/starter/), a
4+
small dental-clinic front desk with two assistants, tools, a handoff and a
5+
simulation suite. CI checks that each snippet matches its file and that the
6+
example passes `validate`, so you can copy from here safely.
7+
8+
A resource's ID is its path under the type folder, without the extension
9+
(`tools/lookup-patient.yml` is `lookup-patient`). Reference other resources
10+
by that ID, never by UUID: the engine resolves IDs to UUIDs per org.
11+
12+
## Assistants (`.md` or `.yml`)
13+
14+
Markdown with YAML frontmatter: the frontmatter is the assistant config and the
15+
body is its system prompt.
16+
17+
```markdown
18+
<!-- examples/starter/resources/starter/assistants/receptionist.md -->
19+
---
20+
name: Receptionist
21+
firstMessage: Thanks for calling Bright Smile Dental. How can I help?
22+
model:
23+
provider: openai
24+
model: gpt-4.1
25+
temperature: 0.3
26+
toolIds:
27+
- lookup-patient
28+
- handoff-to-scheduler
29+
tools:
30+
- type: endCall
31+
voice:
32+
provider: 11labs
33+
voiceId: sarah
34+
artifactPlan:
35+
structuredOutputIds:
36+
- call-summary
37+
---
38+
39+
# Identity
40+
41+
You are the receptionist for Bright Smile Dental, 123 Main St. The clinic is
42+
open Monday to Friday, 8am to 5pm.
43+
44+
# Flow
45+
46+
1. Ask for the caller's phone number and call `lookup_patient` with it.
47+
2. If they want to book, change or check an appointment, hand off to the
48+
Scheduler with `handoff_to_scheduler`. Don't book anything yourself.
49+
3. Answer general questions (hours, address) briefly yourself.
50+
```
51+
52+
## Tools (`.yml`)
53+
54+
```yaml
55+
# examples/starter/resources/starter/tools/lookup-patient.yml
56+
type: function
57+
function:
58+
name: lookup_patient
59+
description: Look up the caller's patient record by phone number.
60+
parameters:
61+
type: object
62+
properties:
63+
phone:
64+
type: string
65+
description: The caller's phone number
66+
required:
67+
- phone
68+
server:
69+
url: https://example.com/vapi/lookup-patient
70+
```
71+
72+
Handoffs between assistants are tools too. Give each one an explicit
73+
`function.name` if your prompts mention it by name:
74+
75+
```yaml
76+
# examples/starter/resources/starter/tools/handoff-to-scheduler.yml
77+
type: handoff
78+
function:
79+
name: handoff_to_scheduler
80+
destinations:
81+
- type: assistant
82+
assistantId: scheduler
83+
description: Books, changes and checks appointments.
84+
```
85+
86+
## Structured Outputs (`.yml`)
87+
88+
```yaml
89+
# examples/starter/resources/starter/structuredOutputs/call-summary.yml
90+
name: call-summary
91+
type: ai
92+
description: Summarizes the call for the front-desk log.
93+
schema:
94+
type: object
95+
properties:
96+
summary:
97+
type: string
98+
booked:
99+
type: boolean
100+
```
101+
102+
## Squads (`.yml`)
103+
104+
```yaml
105+
# examples/starter/resources/starter/squads/front-desk.yml
106+
name: Front Desk
107+
members:
108+
- assistantId: receptionist
109+
- assistantId: scheduler
110+
```
111+
112+
Members hand off to each other through handoff tools on the assistants, as
113+
above. Prefer them over the legacy `assistantDestinations` field.
114+
115+
## Evals (`.yml`)
116+
117+
An eval file is the body of the [Evals API](https://docs.vapi.ai/api-reference/evals)
118+
create request, written as YAML.
119+
120+
## Simulations
121+
122+
**Personality** (`simulations/personalities/`): the simulated caller, as an
123+
assistant config.
124+
125+
```yaml
126+
# examples/starter/resources/starter/simulations/personalities/calm-caller.yml
127+
name: Calm caller
128+
assistant:
129+
model:
130+
provider: openai
131+
model: gpt-4.1-mini
132+
messages:
133+
- role: system
134+
content: >
135+
You are a patient calling a dental clinic. Follow your scenario,
136+
answer questions briefly, and don't invent details.
137+
```
138+
139+
**Scenario** (`simulations/scenarios/`): what the caller does, how the call is
140+
judged (at least one evaluation), and mock results for the tools it calls.
141+
142+
```yaml
143+
# examples/starter/resources/starter/simulations/scenarios/books-cleaning.yml
144+
name: Books a cleaning
145+
instructions: >
146+
You are Jordan Lee, phone 206-555-0142, an existing patient. Book a teeth
147+
cleaning for next Tuesday morning and accept the first slot offered. Once
148+
the booking is confirmed, say thanks and goodbye.
149+
evaluations:
150+
- structuredOutputId: booking-confirmed
151+
comparator: "="
152+
value: true
153+
required: true
154+
toolMocks:
155+
- toolName: lookup_patient
156+
result: '{"found": true, "patientId": "P-1001"}'
157+
- toolName: book_appointment
158+
result: '{"success": true, "date": "next Tuesday", "time": "09:00"}'
159+
```
160+
161+
**Simulation** (`simulations/tests/`): a personality paired with a scenario.
162+
163+
```yaml
164+
# examples/starter/resources/starter/simulations/tests/books-cleaning-calm.yml
165+
name: Books a cleaning (calm caller)
166+
personalityId: calm-caller
167+
scenarioId: books-cleaning
168+
```
169+
170+
**Simulation Suite** (`simulations/suites/`):
171+
172+
```yaml
173+
# examples/starter/resources/starter/simulations/suites/core.yml
174+
name: Core
175+
simulationIds:
176+
- books-cleaning-calm
177+
```
178+
179+
## TypeScript resources (`.ts`)
180+
181+
Any resource can also be a `.ts` file whose default export is the resource
182+
object, useful for generating config. It is executed when loaded, so treat
183+
`.ts` resources like code in review.

0 commit comments

Comments
 (0)