Skip to content

Choosing a client setup

Which request surface each AI client speaks, whether `vulnetix ai-firewall install` can wire it, and which of its traffic never reaches the gateway.

Updated 02 Nov 2026Checked against ai-firewall@339de55, cli@4c8c3b7, website@ad775f3

Every client is wired the same way: its base URL points at the gateway, and its API key is your Vulnetix API key, not a provider key. The provider key stays in the vault and the gateway adds it on the way upstream. See Keys and base URLs for the two keys and the URL shapes.

A client is only wired when both halves are right. A base URL that points at the gateway with a provider key in the key field fails with 401 invalid_api_key. A Vulnetix key with the provider’s own base URL sends your Vulnetix key to the provider.

Clients

Client Surface install id What install writes Traffic that skips the gateway
Claude Code messages claude-code env in .claude/settings.json None once wired
Claude Desktop messages none Nothing. Set in the app. A user who signs in to Anthropic instead
Codex CLI responses codex [model_providers.vulnetix-openai] in ~/.codex/config.toml None once wired
Continue chat continue A models entry in ~/.continue/config.yaml, and ~/.continue/.env Roles the entry does not cover, such as autocomplete
aider chat aider openai-api-base and model in .aider.conf.yml None once wired
Cursor chat cursor (prints steps) Nothing. Set in the app. Tab completions, Auto mode
Windsurf chat windsurf (prints steps) Nothing. Set in the app. The editor’s built-in models
Belai and Kiro any, plus kiro none Nothing. Set in Belai. Decision models, Copilot
Any SDK or script chat, responses, messages shell, env Base-URL and key variables SDKs that ignore the variables
Other clients chat none Nothing Depends on the client

The SDK pages: curl, Python, JavaScript and TypeScript, Java, Kotlin and Spring AI, Go, Rust, .NET, Ruby, PHP, Elixir, Swift and Dart. Unattended agents: CI/CD.

Surfaces

The route decides the surface. A provider serves only the surfaces listed for it in the provider catalogue; a request on any other surface is refused with 404 unsupported_api, and the message names the route to use instead.

Surface Route under https://guardrails.vulnetix.com/{provider}/{uuid} Spoken by Served by
chat POST /v1/chat/completions OpenAI SDKs, LangChain, LlamaIndex, Continue, aider, Cursor, curl Every provider except anthropic and kiro
responses POST /v1/responses Codex CLI openai
messages POST /v1/messages, POST /v1/messages/count_tokens Anthropic SDKs, Claude Code, Claude Desktop anthropic
kiro POST /v1/generateAssistantResponse, GET /v1/ListAvailableModels Belai’s kiro provider kiro

GET /v1/models on any provider lists the models your policy lets you call. See The models endpoint.

Base URL shape

Client family Base URL
OpenAI-shaped (OpenAI SDKs, Codex, Continue, aider, Cursor, Windsurf, LangChain, LlamaIndex) https://guardrails.vulnetix.com/{provider}/{uuid}/v1
Anthropic-shaped (Anthropic SDKs, Claude Code, Claude Desktop) https://guardrails.vulnetix.com/anthropic/{uuid}, no /v1
Spring AI https://guardrails.vulnetix.com/{provider}/{uuid}, no /v1 (Spring AI appends /v1/chat/completions)

{uuid} is the UUID your Vulnetix API key belongs to: your own principal UUID, or the organisation UUID for a single-user organisation. Policy always comes from the organisation. vulnetix ai-firewall status prints it as the gateway org.

Environment variables the CLI sets

vulnetix ai-firewall install shell writes a managed block, fenced by # Vulnetix AI Firewall and # End Vulnetix AI Firewall, into your shell rc (or the Windows user environment). install env writes the same variables into an existing .env, .envrc or Makefile at the git root. Only providers with a stored key, and not denied by policy, are written.

Provider Base-URL variables Key variable Value of the key variable
openai OPENAI_BASE_URL, OPENAI_API_BASE OPENAI_API_KEY $VULNETIX_API_KEY
anthropic ANTHROPIC_BASE_URL ANTHROPIC_AUTH_TOKEN $VULNETIX_API_KEY
groq GROQ_BASE_URL GROQ_API_KEY $VULNETIX_API_KEY
mistral, deepseek, xai, openrouter, together, fireworks none none none

OPENAI_BASE_URL is read by openai-python 1.x and openai-node; OPENAI_API_BASE by langchain-openai and LlamaIndex. No SDK reads a base-URL variable for the providers in the last row, so the CLI writes only an informational VULNETIX_AIFW_<PROVIDER>_BASE_URL (for example VULNETIX_AIFW_MISTRAL_BASE_URL). Nothing reads it: set base_url in code for those providers.

Install and uninstall

vulnetix ai-firewall install                      # every client detected on this machine
vulnetix ai-firewall install claude-code codex    # only these
vulnetix ai-firewall install aider --dry-run      # print the plan, write nothing
vulnetix ai-firewall uninstall --all --except codex

Client ids: aider, claude-code, codex, continue, cursor, env, shell, windsurf. The flags (--provider, --model, --scope, --embed-key, --create-env, --dry-run, --gateway-url) are in Wiring clients.

Before writing, install:

  • skips a provider with no stored key, or one denied by policy, and says which;
  • skips a client whose surface the gateway does not serve for its provider (wire_unsupported), rather than writing a config that would 404;
  • refuses a --model the policy would refuse at request time;
  • refuses --embed-key when the target file is inside a git repository and not git-ignored.

Checking a machine

vulnetix ai-firewall status reports each client as one of:

State Meaning
wired The configured base URL is on the gateway host
points elsewhere A base URL is configured and it is not the gateway. Raises bypasses_firewall.
not wired Installed, with no base URL configured
manual Cursor or Windsurf: the setting lives in application state, which the CLI cannot read
not installed No config directory or binary found

manual does not mean wired. Claude Desktop, Belai and SDK code in your own programs are not in the CLI’s client list at all, so status says nothing about them. For those, the proof is a request: send one that a guardrail blocks and look for the 403, or read the X-Vulnetix-Firewall-Decision response header (allow, redact, flag or block).

What the gateway sees from an agent

Guardrails run over every text segment of the request on every surface, including tool results: a file an agent read or the output of a command it ran is screened on the next turn. The arguments a model writes for a tool call are opaque tool input and are not scanned. A tool runs on the developer’s machine before its result reaches the gateway, so a tool rule stops the tool being offered again; it cannot undo a command.

The gateway names the client from its request headers (claude-code, claude-desktop, codex-cli, cursor, kiro, copilot, continue, aider, anthropic-sdk, openai-sdk, langchain, curl, or unknown). Any caller can set those headers, so the name is attribution, not authentication. See Client identity.

Edit this pageSources: cli/pkg/aifirewall/clients.go, cli/pkg/aifirewall/provider.go, cli/pkg/aifirewall/config.go, cli/pkg/aifirewall/detect.go, cli/cmd/ai_firewall.go, ai-firewall/internal/api/server.go, ai-firewall/internal/api/handlers.go, ai-firewall/internal/client/client.go, ai-firewall/internal/wire/wire.go, website/src/components/ai-firewall/setup-guide-content.ts
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.