Available on the Enterprise plan.
Supported providers
Configuration
Step 1: Add a model
Before assigning a BYOM model to an agent, you need to register it in the admin panel:- Navigate to Admin > Models
- Click Add Model
- Provide a name for the model
- Select the model type (LLM or Embedding)
- Choose a provider and model
- Enter the required credentials for the provider
Step 2: Assign the model to an agent
Once a model is registered, reference it in the agents YAML configuration by name or ID:Network configuration
For every provider except LLM Gateway, Cube connects to your model provider from its control plane. If your provider requires IP allowlisting, ensure the Cube outbound IP addresses are added to your allowlist. For agents running in dedicated regions, additional per-region IP addresses may also need to be allowlisted. The LLM Gateway provider works the other way around: the request is made by your own deployment, so nothing needs to be reachable from Cube and there is no allowlist to maintain. See LLM Gateway below.Billing
When using a BYOM model, Cube AI tokens are not consumed. You are billed directly by your model provider based on their pricing. This means:- No Cube token quota is deducted for BYOM chat requests
- No token usage is tracked in the AI Tokens Usage dashboard for BYOM requests
- Per-seat token grants and token packages do not apply
Provider-specific notes
Anthropic
Supports extended thinking mode for compatible models. Configure this in the model settings when creating the model.AWS Bedrock
- Credentials are optional — if left empty, the default AWS credential chain is used (e.g., workload identity)
- Supports assume-role configuration for cross-account access
- Supports inference profiles
GCP Vertex AI
Requires a service account JSON key for authentication.Databricks
Requires a workspace URL and access token.Snowflake Cortex
Supports two authentication methods:- JWT authentication
- Key-pair authentication (requires an encrypted PKCS#8 PEM private key)
LLM Gateway
Use this provider to route agent traffic through your own LLM gateway or proxy — including one that is only reachable from inside your own network. Unlike every other provider, Cube holds no credentials and never calls your model. Your deployment does: Cube sends the conversation to your deployment’s runtime, which invokes achatCompletion hook you write in your configuration
file — cube.js, cube.ts, or cube.py under its snake_case name
chat_completion. The gateway endpoint, its API key and all LLM egress stay
inside your network.
Because the request originates from your own deployment, a gateway with no
public ingress — for example one reachable only within your VPC — works with
no peering, allowlisting or inbound access from Cube.
Writing the hook
The hook may return a LangChain chat model, which is the shortest path if your gateway already has a LangChain integration:ChatAnthropic,
ChatBedrockConverse, ChatVertexAI, or your own subclass. Add the
integration package to your project’s package.json; Cube does not need to
know which one you use.
The model must support tool calling. Cube agents call tools on every turn, so
a model without it cannot serve an agent.
To choose the model per request — to route by user, or to act on the model
name configured in Admin > Models — export a function instead. It is
called once per turn:
If you do not use LangChain, return an async iterable of chunks instead:
Chunk format
A LangChain model produces these for you. You only need this section if your hook builds chunks by hand — an async iterable incube.js, or either of the
cube.py forms below.
Each entry in
tool_call_chunks carries an index, and the args of entries
sharing an index are concatenated as a JSON string — that is how a streamed
tool call arrives one fragment at a time. Send the id and name on the first
fragment of each call:
args is the complete JSON string.
Writing the hook in Python
cube.py supports the same hook under its snake_case name, chat_completion,
but what it can return is narrower. Values crossing between Python and
JavaScript are limited to strings, numbers, booleans, lists, dicts and plain
functions, so a Python hook cannot return a model object or an async
generator. Return a list of chunks instead:
next function that yields one chunk per call and None
when the response is complete. A closure crosses the bridge, so it can hold
whatever iterator your gateway call produced:
content, tool_call_chunks, usage_metadata.
Three further differences from the JavaScript form:
- The request is a dict with the same keys, but without
signal— cancellation cannot be delivered across the bridge, so a Python hook is not told when the user cancels a turn. Enforce your own timeout if that matters - The hook must be a plain
deforasync def. A bound method, afunctools.partialor a callable class instance will not be picked up - There is no LangChain shortcut, so a Python hook always builds
tool_call_chunksby hand. If your gateway speaks the OpenAI API, acube.jshook withChatOpenAIis considerably less work
cube.js rather than cube.py — a deployment uses one
configuration file, and cube.py takes precedence when both are present.
Configuring the model in Cube
- Add a model in Admin > Models and choose the LLM Gateway provider
- Leave Model Name blank if your hook always serves one model, or set it to a name your hook routes on
- Optionally set Small Model Name for the lighter follow-up calls agents make; it defaults to the main model name
Troubleshooting
Rate limit errors
If you see rate limit errors, the limits are enforced by your model provider, not by Cube. Check your provider’s rate limits and usage quotas.Authentication errors
Verify that the API key or credentials configured for the model are valid and have the necessary permissions.LLM Gateway errors
Errors mentioning the LLM Gateway come from your own deployment, not from Cube’s control plane:- No
chatCompletionhook is configured — the model is assigned to an agent but the deployment’s configuration file does not export the hook, or the deployment has not restarted since it was added - Does not support tool calling — the chat model the hook returned has no
bindTools. Cube agents require a tool-calling model - Must return a LangChain chat model, a list of chunks, … — a
cube.jshook returned something with no stream in it - Unable to represent PyObject in JS — a
cube.pyhook returned a value with no bridge representation, most often a model object or an async generator. This is raised by the bridge itself, before Cube sees the return value, which is why it reads nothing like the message above. Use one of the two Python forms above - Stream ended before the response was complete — the connection to your gateway dropped mid-answer. Check your gateway’s timeouts and any proxy between it and the deployment