Pull prompt from Supabase
When this applies
- User says "pull prompt for {client}", "get prompt for {client}", or similar.
- User wants to review, compare, or export a client's current AI assistant prompt and configuration.
- Called by the sync workflow or auto-sync rule to check if prompts need refreshing (see "Freshness check mode" below).
MCP server
- Supabase (
user-Supabase):execute_sqlwithproject_idfor the Avoca production database. - Discover
project_idvialist_projectsif unknown. The production project is named "avoca".
Inputs
| Input | Required | Source |
|---|---|---|
| Client name or team ID | Yes | User provides, or match from clients/ folder name |
| Prompt name | No | If multiple prompts exist for the team, ask which one |
Workflow
Step 1 — Resolve the client
Match the client to their clients/{Name}-{ID}/ folder. Extract the team ID (numeric suffix). If the user gave a name, glob clients/ for a match. If they gave an ID directly, use it.
Read avoca-client.json from the client folder if it exists — it may have avoca_client_id.
Step 2 — Query system prompts for the team
SELECT sp.id, sp.name, sp.status, sp.template_id, sp.current_version,
sp.updated_at, sp.variable_overrides,
spc.company_name
FROM system_prompts sp
JOIN system_prompt_configs spc ON sp.config_id = spc.id
WHERE sp.is_deleted = false
AND sp.team_id = {team_id}
ORDER BY sp.updated_at DESC;
If multiple prompts exist, list them and ask the user which one to pull (or pull all if they say so). If only one, proceed automatically.
Step 3 — Pull the full data
Run these three queries in parallel for the chosen prompt (by sp.id):
A) Sections (modules):
SELECT
s->>'name' AS module_name,
s->>'order' AS module_order,
s->>'enabled' AS enabled,
s->>'isCustom' AS is_custom,
s->>'isLocked' AS is_locked,
s->>'content' AS content,
s->>'originalContent' AS original_content
FROM system_prompts, jsonb_array_elements(sections) AS s
WHERE id = {prompt_id}
ORDER BY (s->>'order')::int;
Note: this may return a large result. If it times out or truncates, batch by pulling sections in groups (e.g., WHERE (s->>'order')::int BETWEEN 0 AND 19, then 20–39, then 40+).
B) Config (business variables):
SELECT spc.*
FROM system_prompt_configs spc
JOIN system_prompts sp ON sp.config_id = spc.id
WHERE sp.id = {prompt_id};
C) Template name:
SELECT name, version FROM system_prompt_templates
WHERE id = (SELECT template_id FROM system_prompts WHERE id = {prompt_id});
Step 4 — Build the markdown file
Save to: clients/{Name}-{ID}/prompts/{prompt-name-slug}.md
Slugify the prompt name (lowercase, hyphens, no special chars). If a file already exists, overwrite it (this is a fresh pull).
File structure
# {Prompt Name} — {Company Name}
**Team ID:** {team_id}
**Prompt ID:** {prompt_id}
**Template:** {template_name} (v{version})
**Status:** {status}
**Version:** {current_version}
**Last updated:** {updated_at}
**Pulled:** {today's date and time}
---
## Business config
| Field | Value |
|-------|-------|
| Company name | {company_name} |
| Assistant name | {assistant_name} |
| Location | {company_location} |
| Timezone | {timezone} |
| Trades | {trades_provided.text} |
| Service hours | {service_hours} |
| Live rep hours | {live_representative_hours} |
| Company phone | {company_phone_number} |
| Website | {website} |
| Fees name | {fees_name} |
| Intro line | {ai_intro_line} |
| Closing line | {offer_closing_line} |
| Country | {country} |
| Tech arrival notice | {technician_arrival_duration} |
| Emergency re-fetch | {emergency_re_fetch_mode} |
---
## Policy snapshot
Decode `agent_config_variables` into a human-readable table:
| Policy | Setting |
|--------|---------|
| Booking | {enabled/disabled} — {offer_availabilities.type} |
| Transferring | {enabled/disabled}{, time-based if applicable} |
| Commercial | {action} |
| Cancellation | {action} |
| Rescheduling | {action} |
| ETAs | {action} |
| New customers | {action} |
| Renters | {action} |
| Membership confirmation | {enabled/disabled} |
| Equipment age question | {enabled/disabled} |
| AI disclosure | {enabled/disabled} — {timing} |
---
## Module index
| # | Module | Enabled | Custom | Size |
|---|--------|---------|--------|------|
| 0 | MODULE: VARIABLES | ✅ | — | 4.6 KB |
| 1 | SYSTEM CAPABILITIES | ✅ | — | 1.4 KB |
| ... | ... | ... | ... | ... |
Use ✅ for enabled, ❌ for disabled. Use ✏️ for custom modules.
---
## Modules
For each module, output:
### {order}. {Module Name}
{If disabled: **⚠️ DISABLED**}
{If custom: **✏️ CUSTOM OVERRIDE** — content differs from template}
{content — the rendered module text, as-is}
---
## Services provided
{services_provided — full text}
## Services NOT provided
| Service | Description |
|---------|-------------|
| {service} | {description} |
## FAQ
{faq}
## Membership info
{membership_information}
Step 5 — Custom diff detection
For each module where isCustom is true OR where content differs from originalContent:
- Note it in the module index with ✏️
- In the module section, add a collapsed diff block:
<details>
<summary>Diff from template</summary>
**Original:**
{originalContent}
**Current:**
{content}
</details>
Step 6 — Variable overrides
If system_prompts.variable_overrides is non-null, add a section:
## Variable overrides
| Variable | Override value |
|----------|---------------|
| ... | ... |
Step 7 — Confirm
Tell the user:
- File path saved
- How many modules (total / enabled / disabled / custom)
- Any notable config (e.g., "transfers disabled", "booking type: specific_time")
Pulling multiple prompts
If the user says "pull all prompts" for a client with multiple prompts, loop through each and create separate files. Summarize all in one message.
Comparing prompts across clients
If the user says "compare prompts for {client A} and {client B}":
- Pull both using the workflow above (if not already saved locally).
- Produce a diff summary focusing on:
- Modules that differ in content
- Modules enabled in one but disabled in the other
- Config differences (services, hours, policies)
- Save as
clients/{Name-A}-{ID}/prompts/compare-vs-{Name-B}.mdor output in chat per user preference.
Step 8 — Update avoca-client.json
After writing the markdown file, update avoca-client.json in the client folder with prompt metadata so future syncs can check freshness.
Read the existing file, merge in the prompts key, and write it back:
{
"avoca_client_id": "2339",
"prompts": {
"457": {
"name": "John Goudie",
"version": 7,
"updated_at": "2026-04-02T02:52:32Z",
"pulled_at": "2026-04-05T22:00:00Z",
"file": "prompts/john-goudie.md"
}
}
}
Fields per prompt entry:
name— prompt name fromsystem_prompts.nameversion—current_versionfromsystem_promptsupdated_at—updated_atfromsystem_prompts(ISO 8601)pulled_at— current timestamp when the pull happened (ISO 8601)file— relative path to the markdown file within the client folder
If the client has multiple prompts, each gets its own key under prompts (keyed by prompt ID).
Freshness check mode
When called from the sync workflow or auto-sync rule (not a direct user request), use this lightweight mode instead of a full pull.
When to use
- The sync workflow reads
avoca-client.jsonand finds apromptssection. - It calls this skill in "check" mode for that client.
Procedure
Read
avoca-client.jsonfrom the client folder. If nopromptskey exists, skip entirely — the user hasn't opted in to prompt tracking for this client.Extract the team ID and the stored
updated_atfor each prompt.Run a single cheap query:
SELECT id, name, current_version, updated_at
FROM system_prompts
WHERE team_id = {team_id} AND is_deleted = false;
Compare each prompt's
updated_atfrom Supabase against the storedupdated_atinavoca-client.json.If unchanged: Do nothing. Optionally log "prompt is current" if reporting to the user.
If changed: Run the full pull workflow (Steps 2–8 above) for the changed prompt(s). This overwrites the markdown file and updates
avoca-client.jsonwith the new version/timestamp.If a new prompt appears (ID not in
avoca-client.json): Ignore it — don't auto-pull prompts the user hasn't explicitly pulled before.
Output in check mode
Keep it minimal. Examples:
- (nothing — prompt is current, no output needed during silent sync)
Prompt "John Goudie" updated (v7 → v8) — re-pulled to prompts/john-goudie.md
Safety
- Read-only: never write to Supabase.
- Large prompts may exceed query result limits — batch section pulls if needed.
- Don't dump the full
final_prompttext unless the user specifically asks for it; the module breakdown is the point.
Output
Keep chat output concise. Example:
Pulled "John Goudie" prompt to
clients/John Goudie-2339/prompts/john-goudie.md54 modules (53 enabled, 1 disabled) · Template: Modular v3.0.87 · Last updated 4/2/2026