Three ways to get an LLM answer into Salesforce. Picking the wrong one costs you either compliance, money or months. Part 1 of the External AI series.
Meridian Wealth is a mid-size wealth management firm. The advisory team wants AI-generated meeting prep notes on client accounts: portfolio changes, recent service cases, life events logged by advisors. Simple feature. Then legal joins the call.
Suddenly "call an LLM from Apex" has three very different answers. This post is the map. The rest of the series builds each path hands-on.
Path 1 — Native Models API. Salesforce hosts the model relationship. You call a Salesforce-managed model (OpenAI, Anthropic, Gemini and others) through the aiplatform Apex namespace or the REST endpoint. The Einstein Trust Layer sits in the path: data masking, toxicity scoring, audit trail, zero-retention agreements Salesforce has already negotiated. No endpoint, no key, no callout config. We covered this end-to-end in Call LLMs from Apex with the Models API — that post stays the reference for this path; we won't repeat it here.
Path 2 — Bring Your Own LLM (BYO LLM). You register an external foundation model — your Azure OpenAI deployment, an Amazon Bedrock or Google Vertex AI model, or an OpenAI account you contract directly — in Einstein Studio (Model Builder). Salesforce then treats it like any other model: it gets an API name, it's callable from the Models API, Prompt Builder and Agentforce, and requests still pass through the Einstein Trust Layer. Your contract, your model, Salesforce's governance. Part 2, Bring Your Own LLM: Register an External Model in Einstein Studio, builds this.
Path 3 — Direct external callout. Plain Apex HTTP callout to any model endpoint, authenticated with a Named Credential + External Credential. Maximum freedom: any provider, any parameter, any response shape, streaming, self-hosted models Salesforce has no connector for. Also maximum responsibility: no trust layer, no masking, no audit unless you build them. Part 3, Calling an External LLM from Apex, builds this — including when it's the wrong choice.
| Factor | Native Models API | BYO LLM (Einstein Studio) | Direct Apex callout |
|---|---|---|---|
| Model choice | Salesforce's supported model list only | Your deployment on supported providers (Azure OpenAI, Bedrock, Vertex AI, OpenAI) | Anything with an HTTP API — including self-hosted and fine-tuned models |
| Einstein Trust Layer | Yes — masking, toxicity scoring, audit built in | Yes — your model, Salesforce's trust layer in the path | No — you build masking, audit and safety yourself |
| Data retention terms | Salesforce's zero-retention agreements with providers | Whatever your contract with the provider says — you control it | Whatever your contract says — and nothing checks it for you |
| Data residency | Depends on Salesforce's model hosting | You pick the region when you deploy the model | You pick the region — full control |
| Cost model | Metered Salesforce AI credits/requests | Provider bill at your negotiated rates + Salesforce platform costs | Provider bill only — cheapest per token, but you build the controls |
| Latency | Trust layer adds a hop; fine for most UX | Trust layer hop + your provider's region | Shortest path — org to endpoint direct |
| Setup effort | Lowest — permissions and a few lines of Apex | Medium — provider setup + Model Builder registration | Highest — credentials, client class, retries, masking, audit, cost tracking |
| Governance burden | Mostly Salesforce's problem | Shared — contract yours, guardrails Salesforce's | Entirely yours |
Ignore the plumbing for a second — here is the shape of "summarize this text" on each path. The difference in what you own is visible in the code.
Path 1 and Path 2 look identical in Apex. That's the point of BYO LLM: once registered, your model is just another model name.
// Paths 1 & 2: Models API via the aiplatform namespace.
// Path 1 uses a Salesforce-managed model name; Path 2 uses the
// API name of the model you registered in Einstein Studio.
aiplatform.ModelsAPI.createGenerations_Request request =
new aiplatform.ModelsAPI.createGenerations_Request();
request.modelName = 'sfdc_ai__DefaultOpenAIGPT4OmniMini'; // or your BYO model's API name
aiplatform.ModelsAPI_GenerationRequest body =
new aiplatform.ModelsAPI_GenerationRequest();
body.prompt = 'Summarize in two sentences:\n' + inputText;
request.body = body;
aiplatform.ModelsAPI.createGenerations_Response res =
new aiplatform.ModelsAPI().createGenerations(request);
String answer = res.Code200.generation.generatedText;
// Path 3: direct callout through a Named Credential.
// No trust layer — masking, retries, audit are now YOUR code.
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:My_LLM/v1/chat/completions');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setTimeout(120000);
req.setBody(JSON.serialize(new Map<String, Object>{
'model' => 'my-fine-tuned-model',
'messages' => new List<Object>{
new Map<String, Object>{
'role' => 'user',
'content' => 'Summarize in two sentences:\n' + inputText
}
}
}));
HttpResponse resp = new Http().send(req);
Two snippets, one honest observation: the Path 3 version above is not production-ready — it has no retry, no error taxonomy, no PII masking, no cost log. The full production version is Part 3; the hardening is Part 5. That gap is the real price of Path 3.
Walk their four constraints through the table:
Every constraint lands on Path 2: BYO LLM through Einstein Studio. Their fine-tuned model, their contract, their region — with Salesforce's masking and audit still in the path. The only work is the registration, which is Part 2 of this series.
When would the other paths have won?
Sources: Supported Models — official docs · Access Models API with Apex · Einstein Generative AI developer guide