Claude Code CLI Proxy
Proxy Claude Code CLI traffic through agentgateway on Kubernetes to intercept, inspect, and secure agentic client requests before they reach Anthropic’s API.
What you’ll build
In this tutorial, you will:
- Set up a local Kubernetes cluster with agentgateway and an Anthropic backend
- Configure native Anthropic message routing (not OpenAI translation)
- Connect Claude Code CLI to route all traffic through the gateway
- Add prompt guards to block sensitive content in CLI prompts
- Understand model selection considerations for Claude Code
Before you begin
Make sure you have the following tools installed:
- Docker
- kubectl
- kind
- Helm
- Claude Code CLI (
npm install -g @anthropic-ai/claude-code) - An Anthropic API key (get one at console.anthropic.com)
For detailed tool installation instructions, see the LLM Gateway tutorial.
Why proxy agentic CLI traffic?
Architecture diagrams typically show agents running in production systems. But the majority of agentic traffic actually originates from developer laptops — tools like Claude Code CLI, Cursor, and Copilot. This traffic needs the same governance as production workloads.
By routing Claude Code CLI through agentgateway, you get:
- Visibility — See every prompt and response flowing through the gateway
- Security — Block sensitive data (PII, credentials) before it leaves the network
- Governance — Enforce organizational policies on developer AI usage
- Auditability — Log and trace all agentic interactions for compliance
┌──────────────────┐ ┌──────────────────────────────┐ ┌──────────────────┐
│ Claude Code │ │ agentgateway │ │ Anthropic API │
│ CLI │ ──── │ + route policies │ ──── │ (Claude models) │
│ (developer │ │ + prompt guards │ │ │
│ laptop) │ │ + observability │ │ │
└──────────────────┘ └──────────────────────────────┘ └──────────────────┘Step 1: Create a kind cluster
kind create cluster --name agentgatewayStep 2: Install agentgateway
# Gateway API CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml
# agentgateway CRDs
helm upgrade -i --create-namespace \
--namespace agentgateway-system \
--version v2.2.1 agentgateway-crds oci://ghcr.io/kgateway-dev/charts/agentgateway-crds
# Control plane
helm upgrade -i -n agentgateway-system agentgateway oci://ghcr.io/kgateway-dev/charts/agentgateway \
--version v2.2.1Verify the control plane is running:
kubectl get pods -n agentgateway-systemStep 3: Create a Gateway
kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: agentgateway-proxy
namespace: agentgateway-system
labels:
app: agentgateway
spec:
gatewayClassName: agentgateway
listeners:
- protocol: HTTP
port: 80
name: http
allowedRoutes:
namespaces:
from: All
EOFWait for the proxy:
kubectl get deployment agentgateway-proxy -n agentgateway-systemStep 4: Create the Anthropic secret
Export your Anthropic API key and create a Kubernetes secret:
export ANTHROPIC_API_KEY=<insert your Anthropic API key>
kubectl apply -f- <<EOF
apiVersion: v1
kind: Secret
metadata:
name: anthropic-secret
namespace: agentgateway-system
labels:
app: agentgateway
type: Opaque
stringData:
Authorization: $ANTHROPIC_API_KEY
EOFStep 5: Create the Anthropic backend
This is where the configuration differs from a standard LLM Gateway setup. Claude Code CLI sends requests to Anthropic’s native /v1/messages endpoint — not the OpenAI-compatible /v1/chat/completions endpoint. You must configure the backend with explicit route policies so agentgateway handles the Anthropic message format correctly.
claude-sonnet-4-5-20250929) but Claude Code CLI uses a different model, you may get a 400 error with a misleading message like “thinking mode isn’t enabled.” To avoid this, either match the model exactly or omit the model field to allow any model.This configuration allows Claude Code CLI to use any model. The anthropic: {} syntax means no model is pinned.
kubectl apply -f- <<EOF
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
name: anthropic
namespace: agentgateway-system
labels:
app: agentgateway
spec:
ai:
provider:
anthropic: {}
policies:
ai:
routes:
'/v1/messages': Messages
'*': Passthrough
auth:
secretRef:
name: anthropic-secret
EOFThis configuration pins the backend to a specific model. Make sure the model matches what Claude Code CLI is configured to use.
kubectl apply -f- <<EOF
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
name: anthropic
namespace: agentgateway-system
labels:
app: agentgateway
spec:
ai:
provider:
anthropic:
model: claude-sonnet-4-5-20250929
policies:
ai:
routes:
'/v1/messages': Messages
'*': Passthrough
auth:
secretRef:
name: anthropic-secret
EOF| Setting | Description |
|---|---|
anthropic: {} |
Allow any model — Claude Code CLI sends the model in each request |
anthropic.model |
Pin to a specific model — must match the CLI’s model selection |
routes['/v1/messages'] |
Process requests in Anthropic’s native message format (required for Claude Code) |
routes['*'] |
Pass through all other requests (e.g., /v1/models) without LLM processing |
Step 6: Create the HTTPRoute
Create an HTTPRoute that routes all traffic from the Gateway to the Anthropic backend:
kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: claude
namespace: agentgateway-system
labels:
app: agentgateway
spec:
parentRefs:
- name: agentgateway-proxy
namespace: agentgateway-system
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: anthropic
namespace: agentgateway-system
group: agentgateway.dev
kind: AgentgatewayBackend
EOFThis route uses a / path prefix match so that all requests — including /v1/messages, /v1/models, and any other Claude Code CLI endpoints — are forwarded to the Anthropic backend.
Step 7: Test with Claude Code CLI
Set up port-forwarding:
kubectl port-forward deployment/agentgateway-proxy -n agentgateway-system 8080:80 &Single prompt test
Send a quick test prompt through the gateway:
ANTHROPIC_BASE_URL="http://localhost:8080" claude -p "What is Kubernetes?"You should receive a normal response from Claude, confirming that traffic is flowing through agentgateway.
Interactive mode
You can also start Claude Code CLI in interactive mode with all traffic routed through the gateway:
ANTHROPIC_BASE_URL="http://localhost:8080" claudeThis opens the full Claude Code CLI experience. Every request — prompts, tool calls, file reads — flows through agentgateway where it can be inspected, logged, and secured.
Step 8: Add prompt guards
Now that connectivity is confirmed, add security by configuring prompt guards. This modifies the backend to reject requests containing specific patterns before they reach Anthropic.
kubectl apply -f- <<EOF
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
name: anthropic
namespace: agentgateway-system
labels:
app: agentgateway
spec:
ai:
provider:
anthropic: {}
policies:
ai:
routes:
'/v1/messages': Messages
'*': Passthrough
promptGuard:
request:
- response:
message: "Rejected due to inappropriate content"
regex:
action: Reject
matches:
- "credit card"
auth:
secretRef:
name: anthropic-secret
EOFkubectl apply -f- <<EOF
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
name: anthropic
namespace: agentgateway-system
labels:
app: agentgateway
spec:
ai:
provider:
anthropic:
model: claude-sonnet-4-5-20250929
policies:
ai:
routes:
'/v1/messages': Messages
'*': Passthrough
promptGuard:
request:
- response:
message: "Rejected due to inappropriate content"
regex:
action: Reject
matches:
- "credit card"
auth:
secretRef:
name: anthropic-secret
EOFThis configuration:
- Routes
/v1/messagesrequests through Anthropic’s native message processing - Passes through all other endpoints without LLM processing
- Rejects any prompt containing “credit card” with a custom message
Step 9: Test the prompt guard
Send the same prompt that was working before, but now with blocked content:
ANTHROPIC_BASE_URL="http://localhost:8080" claude -p "What is a credit card"The request is rejected before reaching Anthropic. You’ll see the custom rejection message instead of a response from Claude.
Now send a request without the blocked phrase:
ANTHROPIC_BASE_URL="http://localhost:8080" claude -p "What is Kubernetes?"This request goes through normally because it doesn’t match any prompt guard patterns.
Extending prompt guards
You can use built-in patterns and custom regex to enforce broader security policies:
promptGuard:
request:
- response:
message: "Request rejected: Contains sensitive information"
regex:
action: Reject
matches:
- "SSN"
- "Social Security"
- "delete all"
- "drop database"
- response:
message: "Request rejected: Contains email address"
regex:
action: Reject
builtins:
- Email
- CreditCard| Pattern | What it blocks |
|---|---|
Custom regex (matches) |
Any phrase you define — dangerous commands, sensitive terms |
Email (builtin) |
Email addresses in prompts |
CreditCard (builtin) |
Credit card numbers |
SSN (builtin) |
Social Security Numbers |
Real-world use cases
| Scenario | Prompt Guard | Effect |
|---|---|---|
| Prevent data exfiltration | Block SSN, credit card, email patterns | PII never leaves the network |
| Restrict dangerous operations | Block “delete”, “drop”, “destroy” patterns | Prevent destructive agent actions |
| Compliance enforcement | Block proprietary terms, internal project names | Keep confidential data out of LLM providers |
| Cost control | Block overly long prompts (custom regex on length) | Prevent excessive token usage |
Cleanup
kill %1 2>/dev/null
kind delete cluster --name agentgateway