Skip to main content
Modal is a serverless GPU platform: you write a small Python app, run modal deploy, and Modal gives you a public HTTPS URL backed by GPUs. Unlike the other providers in this section, Modal has no model catalog and no shared endpoint. You run the inference server. Choose Modal when you want a fine-tuned checkpoint, a model no hosted API offers, a GPU region close to your callers, or full control over the serving engine. This guide deploys an OpenAI-compatible vLLM server on Modal and adds it to Bolna as a custom LLM.

What to enter in Bolna


What you need

  • A Modal account and the Modal CLI (pip install modal, then modal setup)
  • The Hugging Face model you want to serve
  • A Bolna account with access to Settings → Integrations

Deploy and connect

1

Deploy a vLLM server

Save this as bolna_llm.py and run modal deploy bolna_llm.py. It is a trimmed version of Modal’s vLLM inference example, with the settings a voice agent needs. Swap in your own model and the GPU it needs.
bolna_llm.py
modal deploy prints the server URL, for example https://your-workspace--bolna-llm-server.ap-south.modal.direct. The dialog’s placeholder shows the older *.modal.run shape that Modal web functions use; both work the same way. Paste the URL you were given and add /v1.
2

Create a proxy token

A Modal Server rejects requests without a proxy token by default, with a 401. Create one under Settings → Proxy Auth Tokens in Modal, or run modal workspace proxy-tokens create. Join the token ID and secret with a period, wk-<id>.ws-<secret>, and use that as the API key. Modal accepts it as a bearer token, which is what Bolna sends.If your workspace uses role-based access, scope the token to the environment the app is deployed in, or requests are denied with a 403.
3

Check the endpoint

The id in the response is the model name to register, llm in the example above. To also measure time to first token, run the streaming test.
4

Choose Modal in the Add custom model dialog

In Bolna, go to Settings → Integrations, filter by LLM, and click Add model on the Custom LLM card. You can also open the same dialog from an agent: on the Intelligence tab, open the LLM Provider dropdown and choose + Add custom LLM.Pick Modal as the provider. The endpoint field only shows the shape of a Modal URL as a placeholder, because your URL is unique to your workspace and app.
Bolna Add custom model dialog with Modal selected as provider and an empty endpoint URL field showing a Modal URL placeholder

Modal selected: the endpoint placeholder shows the URL shape, the hint says to use the URL from modal deploy

5

Register the model

Fill in the values from the table above and click Add model.
Add custom model dialog with Modal selected, a model name, a Modal endpoint URL, a masked API key and a family

A filled-in Modal registration

6

Use it on an agent

On the agent’s Intelligence tab, choose custom as the provider and select your model. If you added it from the agent’s dropdown, it is already selected. Save the agent and place a web call before you send live traffic to it.

Things to know

  • Keep a container warm. A Modal Server with no running container rejects requests with a 503 instead of queuing them, so a call that arrives after the app has scaled to zero gets no reply at all. Keep min_containers=1 for any agent that takes live calls. You pay for that GPU while it idles.
  • Region. routing_region sets where Modal’s proxy accepts requests: us-east (default), us-west, ca-central, eu-west, ap-south (Mumbai) or ap-southeast-2. To also keep the GPUs in that region, set compute_region, which adds a cost multiplier.
  • Model name. Bolna checks the model name against your server’s /v1/models when you add it. vLLM lists every value given to --served-model-name, so enter one of them exactly.
  • Tool calling. If your agent uses tools, vLLM needs --enable-auto-tool-choice and the parser for your model, for example gemma4 for Gemma 4, hermes for Qwen2.5 or llama3_json for Llama 3.1. See vLLM’s tool calling guide.
  • Thinking. Qwen3 models think before every reply by default, which the caller hears as silence. Turn it off per agent with the extra request params {"chat_template_kwargs": {"enable_thinking": false}}. Gemma 4 has thinking off by default.
  • Using vLLM’s own key instead. If you deploy with unauthenticated=True, Modal’s proxy lets every request through. In that case, protect the server with vLLM’s --api-key flag, read from a Modal Secret, and register that key in Bolna instead of a proxy token.

Tuning a Modal deployment for voice


Troubleshooting

The app scaled to zero, and Modal rejected the request with a 503. Registration still saves a model it can’t reach, so this first shows up on a call. Set min_containers=1 and redeploy.
Check that the key is the token ID and secret joined with a period, wk-<id>.ws-<secret>, with no spaces. A 403 means the token isn’t scoped to the app’s environment. If you use vLLM’s --api-key instead, make sure the Secret is attached and redeploy after changing it.
The model name must match a --served-model-name value exactly. Check GET /v1/models.
The URL is missing /v1, or it points at a different Modal app. Use the URL that modal deploy printed for the server, followed by /v1.