The AI has no access to Salesforce of its own. It sees only what AI Engine puts into the prompt. A data source is a saved query that runs every time a user clicks the template, and its rows go into the prompt. This is how a Global template such as "My weekly pipeline" gets real numbers, and how a Record template can include data the record context does not cover.
Before you start#
- Every object the query reads must be enabled in Agent Objects. Task, Event and User are always allowed.
- Open the template in Ai Agent Admin Setup → Prompt Templates. See Create prompt templates.
Add a data source#
- Below the prompt, click + Add data source.
- Name (placeholder key): a short name such as
pipeline_by_stage. Use lowercase letters, digits and underscores, up to 40 characters, unique within the template. - Question (plain language): describe the data, for example "my open opportunities by stage with total amount".
- Click ✨ Generate. AI Engine writes the query into the SOQL field. You can also type or edit the query yourself.
- Set Row limit: 1 to 200, default 50.
- Click ▶ Preview and check the result (see below).
- Click Insert {data:name} to add the placeholder to the prompt, then move it under a heading of your own in the prompt body.
- Click ✓ Save at the top of the template.
For Record templates, a Sample record Id for Generate / Preview field appears. Paste the Id of a real record, so that Generate can see an example and Preview can run against it.
Limits#
| Limit | Value |
|---|---|
| Data sources per template | Up to 5 |
| Rows per data source | 1 to 200 (Row limit), default 50 |
| Total size of all data sources in one prompt | 40,000 characters by default |
| Name | Lowercase letters, digits and _, up to 40 characters |
| Question | Up to 255 characters |
Row limit is the limit that applies. Preview and Save rewrite the LIMIT in the query to that number, and add one if the query has none. Queries that return a single total row, such as COUNT() or SUM(...) without GROUP BY, run without a row limit. Preview shows the effective limit.
The character budget covers all data sources of one prompt together. Sources run in list order. When the budget runs out, the remaining rows are cut and the prompt notes how many rows were shown. Put the most important source first. The budget is stored in the Max Context Chars (Data Sources) field of the active AI Engine Profile record. The admin panel does not show it, so to change it, update that field with a data tool such as Data Loader. Values below 1,000 are ignored and the default of 40,000 applies.
Binds: one template for every user#
Never write a fixed record Id or user Id into a query. Use these binds instead:
| Bind | Means | Available in |
|---|---|---|
:currentUserId |
The user who clicks the template | Record and Global templates |
:recordId |
The record the template runs on | Record templates only |
Example: SELECT StageName, SUM(Amount) total FROM Opportunity WHERE OwnerId = :currentUserId AND IsClosed = false GROUP BY StageName. Every rep who runs the template sees their own pipeline. If you write "my", "mine" or "this record" in the question, Generate is instructed to use the matching bind. Check the generated query before you save it. In Preview, :currentUserId is your own user.
Use relative date literals such as TODAY, LAST_N_DAYS:30 or NEXT_N_DAYS:14. If Generate writes a fixed date, replace it, otherwise the template goes out of date.
What a query may contain#
A data source query must be a single SELECT. The following are rejected at Preview, at Save and again when the template runs:
- objects that are not enabled in Agent Objects
- DML keywords and semicolons (a single semicolon at the end is simply removed)
FOR UPDATE,FOR VIEWandFOR REFERENCE- any bind other than
:recordIdand:currentUserId, and:recordIdin a Global template
WITH SECURITY_ENFORCED, WITH USER_MODE and WITH SYSTEM_MODE are removed from the query automatically. AI Engine sets the access mode itself.
Preview#
▶ Preview runs the query the same way it will run for a user, with the same checks, row limit and PII masking, but with your own access. It shows the number of rows and columns, roughly how many characters it adds to the prompt, the first 10 rows and the effective row limit. Preview also puts the final query, with the row limit applied, back into the SOQL field. That is the query that will be saved.
How the data reaches the prompt#
- Each
{data:name}placeholder is replaced with that source's rows. - If the template has data sources but no
{data:...}placeholder, all sources are added at the end of the prompt under the headingCRM DATA:. This works, but your own headings help the AI understand what each block is. - A placeholder whose source does not exist is replaced with a note that the source is not configured.
- When a prompt contains data, AI Engine adds an instruction to use only the data provided, to say so when data is missing, and not to invent numbers.
- Each data source has an Active switch. Inactive sources are kept but skipped. ✕ Remove deletes a source when you next save the template.
Security#
Queries run with the permissions of the user who clicks the template, not the admin who wrote them. Sharing rules and field-level security apply, and PII masking applies as in the chat. A rep running a team-wide query gets only the records they are allowed to see in Salesforce.
If a query selects a field the running user cannot read, that data source fails for that user. The prompt then contains a short note that the source failed, and the other sources still run. Keep data source fields to ones every intended user can read.
Troubleshooting#
- Generate says the question cannot be answered with a single query. Rephrase it as a data question: which records, which fields, which period.
- "object is not enabled in Agent Objects". Enable the object, or change the query.
- "this source needs a record (:recordId) but none was given" in Preview. Enter a Sample record Id for Generate / Preview.
- The answer says the data is empty. Run Preview with a realistic sample record, and check the row limit and date filters.
- Headline numbers look too low. A list capped at 50 rows that returns 50 rows makes the AI report 50. Add a separate data source that returns the totals with
COUNT()orSUM().