Avoca → VAPI call resolution
When this applies
- User mentions Avoca call ID, call_id from the Enterprise/API export, or uploads a CSV whose call identifier is the Avoca row id — and needs VAPI data (
get_call).
- The Avoca id (
calls.id, UUID string) is not the same as VAPI's call id (calls.vapi_call_id); the database links them.
MCP servers and tools
- Supabase (
user-Supabase): read the tool schema for execute_sql before calling. Requires project_id (discover via list_projects if unknown).
- VAPI API (
user-vapi-api): get_call with argument callId set to the VAPI id from Supabase — read that tool's schema before calling.
Resolution rules
| Input |
Meaning |
UUID matching calls.id |
Avoca call → look up vapi_call_id. |
String matching calls.vapi_call_id |
Already VAPI id → optional DB row for context; get_call uses this id. |
If unsure, one query can cover both:
SELECT id AS avoca_call_id, vapi_call_id, team_id, ai_or_human
FROM public.calls
WHERE id = '<candidate>'::uuid
OR vapi_call_id = '<candidate>';
Single Avoca ID
- Run
execute_sql with project_id and a query like above (or only WHERE id = ... if the user confirmed Avoca id).
- If
vapi_call_id is null (e.g. human-handled call), report that VAPI get_call does not apply; summarize what Supabase returned if useful.
- If
vapi_call_id is set, call get_call with that value.
CSV / many IDs
The Avoca dashboard has two CSV export formats:
| Export type |
ID column |
Other useful columns |
| AI Calls Export (has call IDs) |
Call ID (UUID) |
Date, Time, Duration, Status, Call Reason, Summary, Emergency, Caller ID, Job ID, Customer ID, Notes |
| Basic Call Export (no call IDs) |
none |
Call Result, Call Date, Call Duration, Customer Name, Customer Phone, Summary |
If the CSV has a Call ID column, use those UUIDs directly. If it doesn't, fall back to matching via Supabase using phone number + timestamp:
SELECT id AS avoca_call_id, vapi_call_id, team_id, ai_or_human, created_at
FROM public.calls
WHERE team_id = <team_id>
AND customer_phone = '<phone>'
AND created_at BETWEEN '<start>' AND '<end>';
For CSVs with Call IDs:
- Parse the
Call ID column — these are Avoca UUIDs (calls.id).
- Normalize to a list of UUID strings; drop blanks and duplicates.
- Batch-resolve in Supabase with one query (adjust batch size if the list is huge, e.g. 100–500 ids per round):
SELECT id AS avoca_call_id, vapi_call_id, team_id, ai_or_human
FROM public.calls
WHERE id = ANY (ARRAY[
'uuid-1',
'uuid-2'
]::uuid[]);
- For each row with a non-null
vapi_call_id, call get_call (parallelize when safe). For missing rows or null vapi_call_id, note them in a short summary table (Avoca id → status).
Client folder routing
The team_id from Supabase maps to the client folder convention clients/{Name}-{ID}/. Use it to automatically route logs to the right place.
- Identify the client folder. Match
team_id from the SQL results to the numeric suffix in clients/*/ folder names (e.g., team_id 2285 → clients/Sykes Services-2285/).
- If the user already said which client this is for, use that folder directly.
- If the CSV contains calls from multiple teams, group by
team_id and file separately.
- If no matching folder exists, ask the user before creating one.
- Read
context.md from the matched client folder before writing, so you have full context on the client.
Saving logs
When the user wants logs saved (default for CSV uploads; ask if unclear for single IDs):
- File location:
clients/{Name}-{ID}/logs/{date}-vapi-call-export.md where {date} is today's date (YYYY-MM-DD). If a file with that name already exists, append a short disambiguator (e.g., -2).
- File format: Markdown with a summary header and per-call sections. Structure:
# {Client Name} — VAPI call logs ({date})
**Source:** Avoca dashboard CSV export ({N} calls)
**Resolved:** {resolved_count} VAPI calls | {no_vapi_count} human/no-VAPI | {missing_count} not in DB
---
## Summary
| # | Avoca ID | VAPI ID | Direction | Duration | Caller | Status |
|---|----------|---------|-----------|----------|--------|--------|
| 1 | `abc...` | `xyz...` | inbound | 3m 42s | +1... | ended-reason |
| ... |
---
## Call details
### Call 1 — `{vapi_call_id_short}`
- **Avoca ID:** `{avoca_call_id}`
- **VAPI ID:** `{vapi_call_id}`
- **Time:** {started_at} → {ended_at}
- **Direction:** {direction}
- **Duration:** {duration}
- **Caller:** {caller_number}
- **End reason:** {ended_reason}
- **Cost:** ${cost}
#### Transcript
> {role}: {message}
> {role}: {message}
> ...
#### Tool calls
| Tool | Arguments (summary) | Result (summary) |
|------|---------------------|-------------------|
| ... | ... | ... |
---
What to include from get_call: Extract and format these fields per call:
id, type, status, endedReason
startedAt, endedAt, duration (compute from timestamps)
direction (inbound/outbound)
- Customer phone number (from
customer.number or phoneNumber)
transcript — format as a readable dialogue with speaker labels
messages — tool-call entries (tool name, arguments summary, result summary)
cost and costBreakdown (if present)
analysis.summary and analysis.successEvaluation (if present)
Large batches: If more than ~20 calls, split into multiple files (-part1, -part2, etc.) to keep each file scannable.
Tell the user the file path after writing so they can find it.
Safety
- Only interpolate IDs that match UUID format; do not pass arbitrary CSV text into SQL.
- If schema differs in another environment, use Supabase
list_tables / inspect types before assuming column names.
Output
For in-chat output, prefer a compact summary: how many calls resolved, how many saved, file path(s). Don't dump full transcripts in chat when saving to disk — just confirm and link to the file.
1---2name: avoca-vapi-call-resolve3description: Resolves Avoca (internal) call IDs to VAPI call IDs using Supabase public.calls, then loads full call payloads via the VAPI API MCP get_call tool. Use when the user gives Avoca call IDs, Enterprise/API call_id values, or a CSV of Avoca calls and wants VAPI call details, transcripts, or provider metadata that only exist on VAPI. Supports saving results to the matching client's logs/ folder.4---56# Avoca → VAPI call resolution78## When this applies910- User mentions **Avoca call ID**, **call_id** from the Enterprise/API export, or uploads a **CSV** whose call identifier is the Avoca row id — and needs **VAPI** data (`get_call`).11- The Avoca id (`calls.id`, UUID string) is **not** the same as VAPI's call id (`calls.vapi_call_id`); the database links them.1213## MCP servers and tools14151. **Supabase** (`user-Supabase`): read the tool schema for `execute_sql` before calling. Requires `project_id` (discover via `list_projects` if unknown).162. **VAPI API** (`user-vapi-api`): `get_call` with argument `callId` set to the **VAPI** id from Supabase — read that tool's schema before calling.1718## Resolution rules1920| Input | Meaning |21|--------|--------|22| UUID matching `calls.id` | Avoca call → look up `vapi_call_id`. |23| String matching `calls.vapi_call_id` | Already VAPI id → optional DB row for context; `get_call` uses this id. |2425If unsure, one query can cover both:2627```sql28SELECT id AS avoca_call_id, vapi_call_id, team_id, ai_or_human29FROM public.calls30WHERE id = '<candidate>'::uuid31 OR vapi_call_id = '<candidate>';32```3334## Single Avoca ID35361. Run `execute_sql` with `project_id` and a query like above (or only `WHERE id = ...` if the user confirmed Avoca id).372. If `vapi_call_id` is null (e.g. human-handled call), report that VAPI `get_call` does not apply; summarize what Supabase returned if useful.383. If `vapi_call_id` is set, call `get_call` with that value.3940## CSV / many IDs4142The Avoca dashboard has **two CSV export formats:**4344| Export type | ID column | Other useful columns |45|-------------|-----------|---------------------|46| **AI Calls Export** (has call IDs) | `Call ID` (UUID) | Date, Time, Duration, Status, Call Reason, Summary, Emergency, Caller ID, Job ID, Customer ID, Notes |47| **Basic Call Export** (no call IDs) | *none* | Call Result, Call Date, Call Duration, Customer Name, Customer Phone, Summary |4849If the CSV has a `Call ID` column, use those UUIDs directly. If it doesn't, fall back to matching via Supabase using phone number + timestamp:5051```sql52SELECT id AS avoca_call_id, vapi_call_id, team_id, ai_or_human, created_at53FROM public.calls54WHERE team_id = <team_id>55 AND customer_phone = '<phone>'56 AND created_at BETWEEN '<start>' AND '<end>';57```5859**For CSVs with Call IDs:**60611. Parse the `Call ID` column — these are Avoca UUIDs (`calls.id`).622. Normalize to a list of UUID strings; drop blanks and duplicates.633. Batch-resolve in Supabase with one query (adjust batch size if the list is huge, e.g. 100–500 ids per round):6465```sql66SELECT id AS avoca_call_id, vapi_call_id, team_id, ai_or_human67FROM public.calls68WHERE id = ANY (ARRAY[69 'uuid-1',70 'uuid-2'71]::uuid[]);72```73744. For each row with a non-null `vapi_call_id`, call `get_call` (parallelize when safe). For missing rows or null `vapi_call_id`, note them in a short summary table (Avoca id → status).7576## Client folder routing7778The `team_id` from Supabase maps to the client folder convention `clients/{Name}-{ID}/`. Use it to automatically route logs to the right place.79801. **Identify the client folder.** Match `team_id` from the SQL results to the numeric suffix in `clients/*/` folder names (e.g., team_id `2285` → `clients/Sykes Services-2285/`).81 - If the user already said which client this is for, use that folder directly.82 - If the CSV contains calls from multiple teams, group by `team_id` and file separately.83 - If no matching folder exists, ask the user before creating one.842. **Read `context.md`** from the matched client folder before writing, so you have full context on the client.8586## Saving logs8788When the user wants logs saved (default for CSV uploads; ask if unclear for single IDs):89901. **File location:** `clients/{Name}-{ID}/logs/{date}-vapi-call-export.md` where `{date}` is today's date (`YYYY-MM-DD`). If a file with that name already exists, append a short disambiguator (e.g., `-2`).912. **File format:** Markdown with a summary header and per-call sections. Structure:9293```markdown94# {Client Name} — VAPI call logs ({date})9596**Source:** Avoca dashboard CSV export ({N} calls)97**Resolved:** {resolved_count} VAPI calls | {no_vapi_count} human/no-VAPI | {missing_count} not in DB9899---100101## Summary102103| # | Avoca ID | VAPI ID | Direction | Duration | Caller | Status |104|---|----------|---------|-----------|----------|--------|--------|105| 1 | `abc...` | `xyz...` | inbound | 3m 42s | +1... | ended-reason |106| ... |107108---109110## Call details111112### Call 1 — `{vapi_call_id_short}`113114- **Avoca ID:** `{avoca_call_id}`115- **VAPI ID:** `{vapi_call_id}`116- **Time:** {started_at} → {ended_at}117- **Direction:** {direction}118- **Duration:** {duration}119- **Caller:** {caller_number}120- **End reason:** {ended_reason}121- **Cost:** ${cost}122123#### Transcript124125> {role}: {message}126> {role}: {message}127> ...128129#### Tool calls130131| Tool | Arguments (summary) | Result (summary) |132|------|---------------------|-------------------|133| ... | ... | ... |134135---136```1371383. **What to include from `get_call`:** Extract and format these fields per call:139 - `id`, `type`, `status`, `endedReason`140 - `startedAt`, `endedAt`, duration (compute from timestamps)141 - `direction` (inbound/outbound)142 - Customer phone number (from `customer.number` or `phoneNumber`)143 - `transcript` — format as a readable dialogue with speaker labels144 - `messages` — tool-call entries (tool name, arguments summary, result summary)145 - `cost` and `costBreakdown` (if present)146 - `analysis.summary` and `analysis.successEvaluation` (if present)1471484. **Large batches:** If more than ~20 calls, split into multiple files (`-part1`, `-part2`, etc.) to keep each file scannable.1491505. **Tell the user** the file path after writing so they can find it.151152## Safety153154- Only interpolate IDs that match UUID format; do not pass arbitrary CSV text into SQL.155- If schema differs in another environment, use Supabase `list_tables` / inspect types before assuming column names.156157## Output158159For in-chat output, prefer a compact summary: how many calls resolved, how many saved, file path(s). Don't dump full transcripts in chat when saving to disk — just confirm and link to the file.