SaveMyCert
Log in
5 of 5 free questions left today·for 30 a day
Assembling and Deploying Applications

Databricks GenAI Engineer: Model Serving Access, Foundation Model APIs, ai_query() and Agent Memory

16 min readDatabricks GenAI · Assembling and Deploying ApplicationsUpdated

Model serving on Databricks is how an LLM application becomes a governed, callable endpoint: you control who can call it, how it authenticates to other resources, which Foundation Model API mode backs it, when to run it as batch inference with ai_query() instead, and where it keeps conversation memory. This lesson covers endpoint permissions, secret-backed credentials, manual agent authentication, AI Gateway rate limits, pay-per-token vs provisioned throughput and external models, the OpenAI-compatible client, serving a chain or agent, ai_query() arguments and compute, and persistent memory in Lakebase scoped to the authenticated user.

What you’ll learn
  • Assign CAN VIEW, CAN QUERY or CAN MANAGE on a serving endpoint by least privilege
  • Pass credentials to a served model with {{secrets/scope/key}} environment variables and know who needs READ
  • Choose manual authentication for a served agent and explain how it disables automatic passthrough
  • Configure AI Gateway rate limits per endpoint, user, service principal or group
  • Choose pay-per-token, provisioned throughput or an external model endpoint, and query them with the OpenAI client
  • Recognise batch workloads and apply ai_query() with the right arguments and compute
  • Store agent memory and structured state in the right datastore, scoped and granted correctly

Who can call a serving endpoint: CAN VIEW, CAN QUERY and CAN MANAGE

Access to a Model Serving endpoint is controlled by permissions on the endpoint itself, at three levels that each include the one below: CAN VIEW, CAN QUERY and CAN MANAGE. Least privilege means giving each identity the lowest level that still lets it do its job.

LevelAllowsGive it to
CAN VIEWGet and list the endpoint, see its state and configurationPeople who only need to see that the endpoint exists and is ready
CAN QUERYEverything in CAN VIEW, plus sending requests to the endpointCallers: analysts in notebooks, an app backend's service principal, the identity that runs an ai_query() job
CAN MANAGEEverything in CAN QUERY, plus updating the configuration (served model version, traffic split, scaling, environment variables), deleting the endpoint and changing its permissionsOwners and on-call operators who roll versions back or change traffic

Two points cause most mistakes. First, seeing an endpoint is not the same as querying it: CAN VIEW never permits sending a request, so every identity that submits requests needs CAN QUERY. Second, Unity Catalog privileges on the registered model do not decide who can call the endpoint. EXECUTE on the model or USE SCHEMA on its schema governs the model asset; the endpoint has its own access control list. Rolling back to an earlier version or changing a traffic split is a configuration update, so it needs CAN MANAGE, while an app that only sends questions needs CAN QUERY and nothing more.

Giving a served model credentials: secret-backed environment variables

A served chain gets credentials for outside systems through endpoint environment variables that reference Databricks secrets, written exactly as {{secrets/<scope>/<key>}}. When the endpoint is created or updated, Model Serving fetches the secret and exposes its value to the model as an environment variable, so the key never appears in plain text in the endpoint configuration, the model artifacts or the code.

  • The syntax is literal. A value such as secrets/translate/api_key without the double braces is just a plain-text string, not a secret reference.
  • The creator needs READ on the secret. The secret is fetched with the identity that creates or updates the endpoint, so that identity needs READ on the scope. If it lacks it, the create or update fails. WRITE or MANAGE on the scope is more than required.
  • Callers never touch the secret. People and apps that query the endpoint need CAN QUERY on the endpoint, not access to the scope.
  • Never package keys as artifacts or plain-text variables: both leave the key readable to anyone who can see the model or the configuration.

Inside the model, code reads the value like any other variable, for example os.environ["TRANSLATE_API_KEY"], typically in load_context when the client is created.

How a served agent authenticates to Databricks resources

A deployed agent reaches Databricks resources (LLM endpoints, Vector Search indexes, Genie spaces, tables, functions) in one of three ways: automatic authentication passthrough, on-behalf-of-user (OBO) authorization or manual authentication. Passthrough and OBO are taught in depth in the Agent Framework lesson; this section covers when you must fall back to manual authentication and what that changes.

MethodIdentity usedFits when
Automatic passthroughShort-lived credentials Databricks provisions for the resources declared when the agent was loggedEvery resource is a supported, declared type and the agent's own access is enough
On-behalf-of-userThe calling end user's identity, limited by the scopes you requestEach user must see only what they personally can access
Manual authenticationCredentials you supply in environment variablesA resource passthrough does not support, such as loading prompts from the MLflow Prompt Registry at runtime

For manual authentication Databricks recommends OAuth credentials of a service principal (machine-to-machine) for production, so access does not depend on a person's account; a personal access token is simpler but suited to development. Supply the values as secret references in the endpoint's environment variables (DATABRICKS_HOST, DATABRICKS_CLIENT_ID, DATABRICKS_CLIENT_SECRET), never as plain text. If the agent loads prompts from the Prompt Registry, the service principal also needs CREATE FUNCTION, EXECUTE and MANAGE on the schema that holds the prompts.

The trap: overriding these security environment variables turns off automatic passthrough for every other resource the agent uses. After the switch, the index search and the LLM call also run as the service principal, so that principal needs access to them too, or calls that worked before start failing with permission errors. Passthrough only ever covers the resource types it supports; anything else needs credentials you supply.

Capping consumption with AI Gateway rate limits

AI Gateway rate limits cap how much traffic a serving endpoint accepts, so one caller cannot exhaust a shared endpoint while everyone keeps access. Limits are set in the endpoint's AI Gateway settings, not in code, and can be expressed as queries per minute (QPM) or tokens per minute (TPM).

  • Endpoint limit: a ceiling on all traffic to the endpoint combined.
  • Default user limit: applies to each caller individually, which is the tool for stopping a single runaway notebook or script.
  • Custom limits for a specific user or service principal: override the default for that identity only. An app backend that calls as one service principal for hundreds of people counts as a single caller, so it needs its own higher limit rather than a looser default for everyone.
  • Group limits: shared by the members of a group.

TPM limits apply to endpoints that serve foundation or external models; custom model and agent endpoints accept QPM limits only. To cap the tokens an agent consumes, put the TPM limit on the model endpoint the agent calls. Rate limits are the control that caps how much an identity uses while leaving its access in place.

Foundation Model APIs: pay-per-token vs provisioned throughput

Foundation Model APIs serve Databricks-hosted foundation models on Model Serving in two modes: pay-per-token, ready-made endpoints you can call immediately, and provisioned throughput, endpoints you create with dedicated capacity.

Pay-per-tokenProvisioned throughput
SetupNone: endpoints already listed on the Serving pageYou create and size the endpoint
BillingPer tokenPer unit of provisioned capacity
ModelsA fixed set of Databricks-provided modelsSupported base models plus fine-tuned variants and custom weights registered in Unity Catalog
Best forPrototyping, experimentation, low or irregular trafficProduction workloads needing guaranteed throughput and predictable latency, and workloads that need compliance certifications such as HIPAA

A fine-tuned model registered in Unity Catalog cannot be called through the base model's pay-per-token endpoint; deploy the registered version to a provisioned throughput endpoint.

Databricks also offers a priority pay-per-token tier that it recommends for latency-sensitive production traffic. Provisioned throughput remains the recommended choice for production workloads that need high throughput, performance guarantees or fine-tuned models, and it is the mode documented for HIPAA compliance.

When the model belongs to a third-party provider (OpenAI, Anthropic and others), use an external model endpoint instead. It routes requests to the provider using the provider key stored in a Databricks secret, gives every team one governed entry point under endpoint permissions, and supports AI Gateway features such as rate limits and usage tracking. Calls are billed by the provider under your own contract, unlike Databricks-hosted models, which Databricks bills. The endpoint is the single governance point: the key lives in one secret, and every call passes through endpoint permissions and AI Gateway controls.

Querying Foundation Model API endpoints from code

Databricks serving endpoints for chat, completion and embedding models are OpenAI-compatible, so the OpenAI SDK works with three settings: set base_url to the workspace URL plus /serving-endpoints, authenticate with a Databricks token, and pass the serving endpoint name as model.

from openai import OpenAI

client = OpenAI(api_key=token,
    base_url=f"{host}/serving-endpoints")

reply = client.chat.completions.create(
    model="databricks-meta-llama-3-3-70b-instruct",
    messages=[{"role": "user", "content": q}])

vectors = client.embeddings.create(
    model="databricks-gte-large-en",
    input=chunks)
  • The model value is the endpoint name exactly as listed on the Serving page, not a Hugging Face identifier or a bare model name.
  • /api/2.0/serving-endpoints is the management REST API (create, update, list), not the OpenAI-compatible query path.
  • Use the API that matches the task: embeddings.create returns vectors; chat.completions.create and completions.create return generated text.

The same endpoints can also be called over REST, with the Databricks SDK or MLflow deployments client, and from SQL with ai_query().

Serving the LLM application itself

To serve an LLM application, register the logged chain or agent in Unity Catalog and deploy that version to a Model Serving endpoint. The endpoint exposes the chain over REST with autoscaling, and the chain, running on the endpoint, calls the Foundation Model API endpoint and any retrievers it uses. Deploying the whole chain keeps its retrieval and prompt logic on the server, behind one governed, real-time endpoint.

For agents, agents.deploy() from the databricks-agents package deploys a Unity Catalog model version in one call, for example agents.deploy("main.support.agent", 3). Beyond creating the endpoint, it provisions short-lived credentials for the resources declared at logging, sets up the Review App where subject-matter experts give feedback, and connects MLflow tracing. Creating the endpoint directly with the SDK gives you only the endpoint. Databricks documentation now also offers newer tooling for brand-new agents, but agents.deploy() remains the documented route for a registered version. Logging and registering the chain is covered in the pyfunc and Unity Catalog lesson.

Batch inference with ai_query()

ai_query() is a built-in SQL function that applies a serving endpoint's model to many rows in one query, which makes it the tool for batch inference: the inputs already sit in a table, the volume is large, and nobody waits on a single answer. Examples are nightly summaries of stored transcripts, labelling new tickets in a scheduled job and backfilling sentiment over years of reviews. When a person or a transaction waits for the reply (a chat assistant, a voice agent, a fraud check at checkout), use a real-time endpoint instead.

SELECT id,
  ai_query(
    'databricks-meta-llama-3-3-70b-instruct',
    CONCAT('Summarise: ', transcript),
    modelParameters => named_struct('max_tokens', 256),
    failOnError => false) AS result
FROM support.calls
ArgumentWhat it does
endpoint, requestThe serving endpoint name and the input expression for each row
responseFormatConstrains a chat foundation model's output to a structure, given as a DDL-style type string or a JSON schema, so downstream SQL can parse it reliably
returnTypeDeclares the SQL type of the value returned, mainly for custom model endpoints; it does not make an LLM produce structured text
modelParametersSampling settings such as max_tokens and temperature
failOnErrorDefaults to true: one endpoint error fails the whole query. Set to false and the function returns a struct with the response and an errorMessage; only failing rows lose their result, and you reprocess the rows whose errorMessage is not null

Databricks recommends submitting the full dataset in one query and letting the platform parallelise the requests, rather than looping over small batches.

Where it runs and who can run it. ai_query() is not available on Classic SQL warehouses; run it on a serverless or pro SQL warehouse, or on compute with Databricks Runtime 15.4 LTS or above (the current reference states the 15.4 LTS floor and the Classic exclusion; failOnError and responseFormat themselves need that runtime level). Because it is a built-in function of the runtime, the runtime version is the gate; libraries installed on the cluster do not change it. The identity running the query needs CAN QUERY on the endpoint, plus the usual SELECT on the input table.

Memory: why served models are stateless and where state belongs

A Model Serving endpoint is stateless across requests: it may run several replicas, any request can land on any of them, and replicas restart on scale-to-zero or redeploy. History kept in a Python attribute inside predict therefore lives in one process only, so state that appears to persist in a single development process does not survive a scaled deployment. Earlier turns must come from the request or from an external store.

RequirementWhere the state lives
Short conversations, never resumed, least infrastructureThe client resends prior turns in the chat request's messages list; the server stays stateless
Resume a conversation later or from another device, many concurrent users, millisecond reads and writes per turnLakebase, Databricks' managed Postgres, keyed by session or thread ID. Databricks' agent session and memory stores are built on it
Low-latency lookups of structured data whose source of truth is a Unity Catalog Delta tableA Lakebase synced table that replicates the Delta table into Postgres and keeps it updated
Analytics over conversations and logsDelta tables (for example inference tables), not the per-turn read/write path

The rule: per-turn agent state needs fast, transactional reads and writes by exact key. Stores built for analytics, similarity search or static files do not provide that, which is why Lakebase sits on the request path and Delta sits behind it for analysis.

Scoping long-term memory and granting the agent access to its store

Short-term memory belongs to one conversation and is keyed by its session ID; long-term memory (preferences, facts about the user) spans conversations and must be scoped by the person. Take that identity from the authenticated request context, never from a name the LLM extracts from the conversation or that the user types. Scoping by that user ID does two jobs at once: each person's memories are recalled in every conversation, and they never surface in anyone else's.

Access to the store follows the identity that runs the agent. In a notebook the agent uses the developer's own credentials, so reads and writes succeed; once deployed it typically runs as a service principal, and every store it reads or writes must grant that principal the matching access. Grants must name the identity the agent actually runs as, with each kind of access (read, write) it performs.

Tip. Expect scenario items that describe callers, an operator task, a failure or a requirement such as least privilege, least effort, latency, compliance or cost, and ask for the permission, configuration, serving mode, ai_query() argument, compute or datastore that satisfies it. Some show short Python (OpenAI client calls) or SQL (ai_query). Permission items turn on which level an action needs and on the difference between endpoint permissions and Unity Catalog privileges. Authentication items probe secret reference syntax, who needs READ on a scope, and the side effect of switching an agent to manual authentication. Serving items contrast pay-per-token, provisioned throughput and external model endpoints and how rate limits are scoped. Batch items ask you to recognise batch workloads and pick ai_query() arguments or compatible compute. Memory items present a forgetful or slow agent and ask where state should live, how to scope it and which identity needs access. A few items ask you to select two answers.

Key takeaways
  • Endpoint permissions are CAN VIEW < CAN QUERY < CAN MANAGE; callers need CAN QUERY, version rollbacks and traffic changes need CAN MANAGE, and UC privileges on the model do not open the endpoint.
  • Secrets reach a served model as environment variables written exactly {{secrets/scope/key}}; the endpoint creator needs READ on the scope, callers do not.
  • Prompt Registry access and other unsupported resources need manual authentication, preferably service principal OAuth in secret references; overriding those variables disables passthrough for every resource.
  • AI Gateway rate limits cap use without removing access: endpoint, default per-user, custom per user or service principal, and group limits; TPM limits are not available on custom model or agent endpoints.
  • Pay-per-token suits prototypes and irregular traffic (a priority tier serves latency-sensitive production); provisioned throughput suits high-throughput production, fine-tuned UC models and HIPAA; external model endpoints govern third-party providers with your own key.
  • The OpenAI client works with base_url = workspace + /serving-endpoints and model = the serving endpoint name.
  • Serve an application by registering the chain in Unity Catalog and deploying it to Model Serving; agents.deploy() also provisions resource credentials, the Review App and tracing.
  • ai_query() is for batch over tables: responseFormat structures chat output, failOnError => false isolates bad rows, submit the whole dataset in one query, and run on serverless/pro SQL or DBR 15.4 LTS+, not Classic SQL.
  • Served models are stateless across replicas: resend messages for short chats, use Lakebase for resumable sessions and synced tables for millisecond lookups of Delta data.
  • Scope long-term memory by the authenticated identity and grant the deployed agent's service principal the access it needs on the store.

Frequently asked questions

Which permission does someone need to query a Databricks Model Serving endpoint?

They need CAN QUERY on the serving endpoint. CAN VIEW only lets them see and list the endpoint, and CAN MANAGE adds configuration changes, deletion and permission management, which callers should not have. Unity Catalog privileges on the underlying registered model do not grant the right to call the endpoint.

How do I pass an API key to a model served on Databricks Model Serving?

Store the key in a Databricks secret scope and add an endpoint environment variable whose value is the reference {{secrets/scope/key}}. Model Serving fetches the secret when the endpoint is created or updated and exposes it to the model as an environment variable. The identity creating or updating the endpoint needs READ on the scope; users who query the endpoint do not.

When should a Databricks agent use manual authentication instead of automatic passthrough?

Use manual authentication when the agent must reach a resource that automatic passthrough does not support, such as loading prompts from the MLflow Prompt Registry at runtime. Databricks recommends a service principal's OAuth credentials supplied as secret references in environment variables. Setting those variables turns off passthrough for all of the agent's resources, so the service principal must also be granted access to them.

What is the difference between pay-per-token and provisioned throughput Foundation Model APIs?

Pay-per-token endpoints are ready-made in the workspace and charge per token, which suits prototyping and low or irregular traffic. Provisioned throughput endpoints are created with dedicated capacity for production workloads that need guaranteed throughput, they can serve fine-tuned or custom models registered in Unity Catalog, and they are the option offered with compliance certifications such as HIPAA.

When should I use ai_query() instead of a real-time serving endpoint?

Use ai_query() for batch inference: the inputs are already in a table, the volume is large and no user is waiting on an individual answer, such as nightly summarisation or backfilling labels. Use a real-time endpoint when a person or transaction waits for the reply, such as a chat assistant or a payment check.

Why does ai_query() fail on my SQL warehouse?

ai_query() is not available on Classic SQL warehouses. Run it on a serverless or pro SQL warehouse, or on a cluster with Databricks Runtime 15.4 LTS or above. The identity running the query also needs CAN QUERY on the serving endpoint it calls.

How do I stop one bad row from failing a whole ai_query() job?

Set failOnError => false. ai_query() then returns a struct containing the response and an errorMessage for each row, so only the failing rows lose their result and the rest of the query completes. You can then select the rows whose errorMessage is not null and reprocess them.

Where should a Databricks agent store conversation memory?

Not in the served model's process, because Model Serving runs stateless replicas that restart. For short, never-resumed chats the client can resend earlier messages each turn. For resumable sessions or long-term memory at low latency, use Lakebase, Databricks' managed Postgres, keyed by session for short-term memory and by the authenticated user for long-term memory, with the agent's service principal granted access.

Source

This lesson covers the "Assembling and Deploying Applications" domain of the official Databricks GenAI exam guide. Vendors revise their guides — check the source for the current version.

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.

Spotted a mistake in this lesson?