Pydantic AI agents validate every field at runtime, but their LLM calls, tool requests, and Logfire telemetry leave from whatever IP your platform assigns. Pin all of it to two fixed static EU IPs.
# .env
HTTPS_PROXY=https://user:pass@eu-01.outboundgateway.com:8443
from pydantic_ai import Agent
agent = Agent('openai:gpt-4o')
# provider SDKs ride httpx, so
# every call follows the proxy
result = agent.run_sync(
'Look up order 4242')
A Pydantic AI agent checks every field of every request at runtime. The one thing it never validates is the address those requests leave from.
Your agent validates every field of every request at runtime, yet the server it runs on hands it a different outbound IP on every deploy or scale-out. To a partner API with an IP-restricted key, a perfectly formed request and a broken network identity look identical: a 403.
Enterprises increasingly restrict OpenAI, Anthropic, or Azure credentials to a list of approved source addresses. A Pydantic AI agent on serverless or containers has no fixed address to register, so the key that powers every model call is the first thing that breaks.
Tools in Pydantic AI are plain Python functions decorated with @agent.tool and wired to your dependency graph. Each one opens its own HTTP calls to CRMs, databases, and partner APIs, and every one of them fails the same way the moment the platform rotates the egress address.
Logfire captures every LLM call, request, and query from inside the agent and ships it to your Logfire region, EU or US. In locked-down environments, that exporter is also outbound traffic, and security teams want to know exactly which address it leaves from.
Pydantic AI agent
LLM, tools, telemetry
HTTPS Proxy
(Two static EU IPs)
LLMs + tool APIs
+ Logfire EU region
Pydantic AI rides the official provider SDKs, which ride httpx, so a single HTTPS_PROXY environment variable carries model calls, tool requests, and Logfire telemetry out through the same two EU addresses. Validate the inputs, pin the origin.
HTTPS_PROXY from the environment by default, and teams that prefer it explicit can inject a custom client.
Shipping Pydantic AI agents whose tool calls hit IP-restricted partner APIs, and who need the whitelist to survive every redeploy.
Running agents on serverless or containers where a NAT gateway is overkill or outright impossible, and needing one env var instead of a networking project.
Approving which addresses may use restricted LLM credentials and partner keys, and preferring a two-address allowlist over cloud-sized CIDR blocks.
Documenting where prompts, agent payloads, and observability telemetry originate, under GDPR and the EU AI Act's record-keeping expectations.
Set HTTPS_PROXY once; the agent, its tools, and telemetry follow.
Pydantic AI calls models through the official provider SDKs, which are httpx-based. httpx honours HTTPS_PROXY by default, so model calls and tool functions route through the proxy with no code changes.
# .env
HTTPS_PROXY=https://user:pass@eu-01.outboundgateway.com:8443
OPENAI_API_KEY=sk-...
PARTNER_API_TOKEN=...
import os
import httpx
from dataclasses import dataclass
from pydantic_ai import Agent, RunContext
# Tool: plain function; its httpx calls honour HTTPS_PROXY
@dataclass
class Deps:
partner_token: str
agent = Agent('openai:gpt-4o', deps_type=Deps)
@agent.tool
async def lookup_order(ctx: RunContext[Deps], order_id: str) -> str:
async with httpx.AsyncClient() as client:
r = await client.get(
f"https://api.partner.eu/orders/{order_id}",
headers={"Authorization":
f"Bearer {ctx.deps.partner_token}"})
return r.text
result = agent.run_sync('Look up order 4242',
deps=Deps(partner_token=os.environ["PARTNER_API_TOKEN"]))
Prefer it visible in code rather than ambient in the environment? Pass a proxied client to the provider explicitly.
import os, httpx
from openai import AsyncOpenAI
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel, OpenAIProvider
client = httpx.AsyncClient(
proxy=os.environ["HTTPS_PROXY"])
model = OpenAIModel(
'gpt-4o',
provider=OpenAIProvider(
openai_client=AsyncOpenAI(http_client=client)),
)
agent = Agent(model)
Logfire's OpenTelemetry-based exporter also honours the standard proxy environment variables, so traces of every LLM call leave through your fixed EU addresses on their way to the Logfire EU region.
import logfire
# HTTPS_PROXY is already set; telemetry follows it
# EU region: logfire-eu.pydantic.dev
logfire.configure()
with logfire.span('agent run'):
result = agent.run_sync('Look up order 4242')
Set it wherever the agent runs. Keep the proxy URL in a secret, never in the image.
# Docker Compose
services:
agent:
env_file: .env
# Kubernetes: Secret
env:
- name: HTTPS_PROXY
valueFrom:
secretKeyRef:
name: outboundgateway-proxy
key: proxy-url
Whitelist both IPs, everywhere
Your account comes with two static IP addresses and traffic uses either one, per connection. Register both on your LLM provider keys, partner APIs, and egress firewalls. If one proxy node is briefly down, the other keeps the agent running.
📖 Complete Documentation: For detailed examples, error handling, and other Python libraries, see the Python SSL Proxy Guide, Node.js Guide, and all other language guides.
Agent traffic is sensitive by construction: prompts, tool payloads, retrieved documents, telemetry. EU teams generally want that path on European infrastructure.
The proxy runs in EU data centres, so model calls, tool requests, and telemetry leave from European addresses, a residency detail that counts when payloads carry personal data.
TLS passes through untouched, so the proxy cannot read prompts, tool arguments, or trace payloads. It forwards encrypted bytes and nothing else.
Agent traffic doesn't bounce through US infrastructure on its way to model providers or Logfire's EU region, which removes a recurring question from GDPR transfer reviews.
When an auditor asks where your AI system's traffic originates, the answer is two named EU addresses, the same two you whitelisted on your provider keys. One story, no gaps.
Two addresses to whitelist on provider keys and partner APIs, with automatic failover between them.
httpx reads the proxy env var on its own. Your agent definition, tools, and dependency graph stay untouched.
European data centres and a GDPR-conscious setup, giving your agent's traffic a predictable European origin.
Model calls, every tool function, and Logfire telemetry: one env var covers all outbound traffic the agent generates.
TLS passthrough means the proxy can't read your traffic. Prompts, tool payloads, and traces stay private the whole way.
Starting from €19/month. Flexible plans for every scale. Cancel anytime.
Your agent validates every field. Give its network identity the same predictability: two fixed EU IPs, one env var, zero code changes.
€19/month starter plan • 7-day refund policy • Direct founder support
No, and that's worth being precise about. BaseModel validation is pure Python with no network calls. The outbound surface is Pydantic AI agents, whose model requests go through the provider SDKs and whose tools make HTTP calls, plus the Logfire SDK's telemetry. If you only use pydantic for data validation inside a service that makes no outbound calls, you don't need this.
Yes. Pydantic AI calls models through the official provider SDKs such as openai, which are built on httpx, and httpx reads HTTPS_PROXY from the environment unless configured otherwise. Tool functions using httpx or requests get the same treatment. If your platform disables environment awareness, you can pass a proxied httpx.AsyncClient to the provider explicitly.
Yes. Logfire's OpenTelemetry-based exporter honours the standard proxy environment variables, so traces of your agent runs travel through the same two EU IPs on their way to your Logfire region. Pairing Logfire's EU region with an EU egress keeps the observability path European end to end.
Happy to talk through how a two-IP EU egress fits your Pydantic AI setup, from a single-tool agent to a fleet of graph runs behind restricted provider keys.
Contact Our Founders →