Hand this to an AI agent pointed at your repository. It finds the provider calls, moves one environment onto Dome, and verifies nothing changed.
1
Check what Dome proxies
Confirm your API surface is supported before you start.
2
Mirror your model in Dome
Create a connection that matches what you call today.
3
Switch one environment
Change three values, keeping a one-variable rollback.
4
Verify parity
Compare the same request through both paths.
5
Add the governance
Apply the rule and the cap you moved for.
Prerequisites
For this tutorial, you will need:- An app that calls OpenAI or Anthropic through their official SDK or plain HTTP.
- The Dome CLI, installed and signed in.
- The provider API key your app uses today.
- A workspace you can experiment in. Provision a sandbox if you do not have one:
Adopting an existing app usually spans two roles. A developer changes the configuration, while the rule and the spend cap belong to security and finance. Both halves are shown here.
Check what Dome proxies
Establish this before you change anything, because it determines whether your app can move today.
If your app is built on the OpenAI Responses API, it cannot move yet. Find out now rather than midway through a migration:
Mirror your model in Dome
Create a connection that resolves to exactly what your app calls today. Name it after the model id your code already passes, and your application’s model string keeps working unchanged:- OpenAI
- Anthropic
Switch one environment
Three values change, and nothing else:
Naming the connection after the model handled the third. Wire the first two so that reverting is a single variable:
llm_client.py
DOME_GATEWAY_URL returns the app to the provider. That is the rollback, and it needs no deploy of new code.
Collect the endpoint values:
Anthropic clients set
base_url to the Gateway without the /v1 suffix, because their SDK appends /v1/messages itself. Anthropic routes also accept the credential in x-api-key when no Authorization header is present, so an app that only sets x-api-key works unchanged.Verify parity
Run the same prompt through both paths and compare. Use a deterministic request so the comparison means something:parity_check.py
llm.model_call.attempted and llm.model_call.completed attributed to checkout-service, with token usage. That record is the thing you did not have before.
Troubleshooting
Troubleshooting
These are remediation steps if you get stuck:
-
400withselect a gateway. The base URL is missing its/gateways/<id>segment. For OpenAI clients it must also end in/v1. -
404withno connection for requested model. The model string in your code does not match a connection name in this workspace. Compare them: -
403withmodel not available in this gateway. The connection is not attached to Default. Check membership withdome gateway get Default. -
403withagent is not granted access to this gateway. The agent has no admission grant. Note thatGET /v1/modelsskips this check, so a working smoke test does not prove the grant exists: -
401from the gateway. Your app is still sending the provider key. This endpoint authenticates the agent. -
429withllm: quota exceeded. A spend cap fired. The message names the subject that ran out. -
501on a request that worked before. You are calling a surface Dome does not proxy yet, such as Responses or Moderations. Keep those calls on the direct path until they are supported. -
Requests succeed but nothing appears in audit.
The app is still on the direct path. Confirm
DOME_GATEWAY_URLis set in the environment the process actually reads.
Add the governance
Parity holding is the midpoint, not the finish. Nothing is governed yet: the agent may call anything in the gateway and spend without limit. Deploy a rule naming what this app may invoke. Createcheckout-service.cedar:
checkout-service.cedar
Keep the fallback branch in the code if you want, but point it at nothing. A rollback path that silently restores ungoverned access is worse than no rollback path, because it works.
Verify the results
Four things should now be true, and each has a command that proves it:- The app reaches the provider only through Dome. Its environment no longer holds a provider key.
- Calls are attributed.
dome audit query --limit 10namescheckout-service. - Only the intended model is reachable. Simulating any other connection name returns
DENY. - Spend is capped.
dome model quota listshows the limit and what has been used against it.
Next steps
In this tutorial, you:- Confirmed your API surface was proxied before starting, rather than discovering a gap midway.
- Moved a provider credential into Dome and out of your app’s environment.
- Changed three configuration values and no application logic, keeping a one-variable rollback.
- Proved parity before adding constraints.
- Applied a rule and a quota sized from real usage.
Debug a tool call denial
Diagnose the first rejection your rollout produces.
Govern per end user
The agent inherits each user’s permissions — same agent, different tool access and answers per person.
Pools
Failover and routing across providers once you are behind the gateway.
LLM gateway
Endpoints, pipeline stages, and error shapes in full.