Use CRM custom values in your prompts
Last updated: September 25, 2026
Your CRM's custom values — the per-sub-account constants like business name,
address or offer details — are available inside every agent prompt as {{cv_*}}
variables. You write the prompt once; each call fills in the values of the client
it is actually calling for.
This is what makes one agent template serve many clients: a "physiotherapy niche"
agent can open with {{cv_business_name}} and quote {{cv_offer_details}}
without a separate prompt per client.
How values resolve at call time
Every call — outbound and inbound — resolves {{cv_*}} tokens from the
sub-account of that call: the client the lead belongs to. Client A's calls get
client A's values, client B's calls get client B's.
The reference sub-account you pick in the editor plays no part in this. It is a design-time helper only: it populates the variable palette so you can see which variables exist and insert them with a click. Changing the reference never changes what a live call says.
Two practical notes:
- Values are read from your CRM and cached briefly, so an edit to a custom value in the CRM can take up to an hour to reach live calls.
- The lookup is fail-open: if your CRM is unreachable at dispatch time, the call still goes out and the unresolved variables render empty.
Insert variables from the editor
- Open the agent (Agents → agent → Prompt tab). On a desktop the panel sits in a column next to the prompt and follows you as you scroll; the same panel is on the New agent form, so you can build the prompt around variables from day one.
- In the GHL variables panel, pick a reference sub-account — the picker is searchable. Sub-accounts built from the same snapshot share the same variables, so any client from the snapshot works as a reference.
- Once the variables load, the palette shows a search box and a count of
what is available. A snapshot easily carries dozens of variables, so nothing
is listed until you type: search by name or by key (for example
budgetorcv_business) and the matching variables appear as chips, in two groups:- Custom values — the sub-account's custom values, resolved automatically on every call.
- Custom contact fields — per-lead tokens, populated by the workflow that triggers the call.
- Click a chip to insert the variable at the cursor position. It goes into the field you clicked in last — the prompt, or the fixed opening phrase of the Call opening card — and the top of the panel says which one. If the search matches more than 30 per group, refine it to see the rest.
The contact's standard fields need no mapping
Name, email and phone are not custom values, and you do not have to route them
through the CRM: Standard contact fields sits at the top of the same panel
and is always available — no reference sub-account, no search. Its five chips
insert {{lead_first_name}}, {{lead_last_name}}, {{lead_full_name}},
{{lead_email}} and {{lead_phone}}, which GodSetter fills on every call from
the lead's own record — outbound, inbound and browser test alike. A value it
does not have renders as an empty string, never as raw text, and the full name
is split for you: first word = first name, the rest = last name. Only what goes
beyond these five needs the cv_* route below.
Naming: cv_ plus the normalized key
Every token is {{cv_<key>}}, where <key> is the CRM field key normalized:
lowercase, any run of characters that isn't a letter or digit collapsed into a
single underscore, and the custom_values. prefix dropped.
| CRM key | Prompt token |
|---|---|
custom_values.business_name | {{cv_business_name}} |
custom_values.Offer-Price | {{cv_offer_price}} |
contact.budget (custom contact field) | {{cv_contact_budget}} |
You never need to build these by hand — the palette inserts the exact token.
Trigger-supplied values win
The workflow webhook that triggers a call can send its own customValues map
(see Wire your CRM workflow to an agent).
Those values are exposed as cv_* variables too, and on a name collision the
trigger's value wins over the sub-account's custom value. This is also how
per-lead custom contact fields (GHL custom fields) reach the prompt on the
generic webhook: the workflow maps them into customValues (e.g.
"contact_budget": "{{contact.budget}}").
With the "Start call cycle" marketplace action there is nothing to map: the
contact's own custom fields are fetched automatically and exposed under the same
palette tokens (e.g. {{cv_contact_budget}}), then persisted on the contact like
any other trigger value.
Trigger values persist on the contact
The customValues a trigger sends are saved on the lead, not just used for
that one call. They resolve as the same cv_* variables on every later touch:
- automatic redials (retry cadence or a scheduled callback) ride with the full set the trigger supplied;
- inbound callbacks — when the lead calls back, the answering agent gets the
same per-contact
cv_*context it dialed with; - a later trigger for the same contact updates the keys it sends and keeps the others (partial updates never wipe earlier values).
So every contact field you put in the agent's prompt as a cv_* token stays
available for that contact across the whole call cycle, in both directions.
One template per niche
The typical setup: one agent per niche, wired to a snapshot workflow. Every client built from that snapshot shares the same custom-value keys but fills its own values — so onboarding a new client means importing the sub-account and filling in its custom values in the CRM. No prompt edits, no new agent.
