Skip to content

Configuration and transport

Use keyword arguments directly or pass a ShieldConfig:

from deepintshield import DeepintShield, ShieldConfig
config = ShieldConfig(
virtual_key="sk-ds-your-virtual-key",
base_url="https://gateway.example.com/",
timeout=20.0,
app_name="support-copilot",
agent_name="refund-agent",
requester="alice@example.com",
requester_role="support",
persist=True,
default_headers={"x-request-source": "web"},
)
shield = DeepintShield.from_config(config)
SettingDefaultMeaning
virtual_keyemptyWorkspace virtual key. Key-dependent helpers raise if it is missing.
base_urlhttps://app.deepintshield.comHosted or self-managed gateway root. Whitespace and trailing / are removed.
timeout30.0 secondsTimeout for the SDK-owned synchronous httpx.Client; also the default in native OpenAI constructor options.
default_headersemptyHeaders merged into SDK and provider requests.
app_namedeepintshieldApplication attribution.
agent_nameemptyStable Agentic Registry lookup key. Required for Agentic governance - there is no default.
requestersdk-userDefault acting user/service identifier.
requester_rolememberDefault role sent to guardrail/RAG evaluation.
persistTrueDefault evidence-persistence flag on explicit evaluations.

ShieldConfig.metadata is available as a configuration data field, but SDK 2.8.3 does not automatically attach it in DeepintShield.from_config(). Pass metadata= to each guardrail or RAG evaluation that needs it.

from deepintshield import DeepintShield
shield = DeepintShield.from_env()
VariableDefault
DEEPINTSHIELD_VIRTUAL_KEYempty
DEEPINTSHIELD_BASE_URLhttps://app.deepintshield.com
DEEPINTSHIELD_GATEWAY_URLlegacy fallback when DEEPINTSHIELD_BASE_URL is unset
DEEPINTSHIELD_TIMEOUT30
DEEPINTSHIELD_APP_NAMEdeepintshield
DEEPINTSHIELD_AGENT_NAMEempty
DEEPINTSHIELD_REQUESTERsdk-user
DEEPINTSHIELD_REQUESTER_ROLEmember
DEEPINTSHIELD_PERSISTtrue; 0, false, and no disable it

An invalid DEEPINTSHIELD_TIMEOUT value fails during configuration parsing. Environment values do not validate the key against the gateway until a request is made.

endpoint(provider) appends a gateway-mounted provider name without adding API version segments:

shield.endpoint("openai") # https://app.deepintshield.com/openai
shield.openai_base_url() # same
shield.anthropic_base_url() # .../anthropic
shield.bedrock_endpoint_url() # .../bedrock
shield.genai_base_url() # .../genai

The dedicated compatibility helpers also expose /langchain, /litellm, and /pydanticai. Passthrough helpers use these exact roots:

HelperPath
openai_passthrough_base_url()/openai_passthrough/v1
anthropic_passthrough_base_url()/anthropic_passthrough
genai_passthrough_base_url()/genai_passthrough

shield.headers() is the minimal SDK header set: content-type, configured defaults, and x-deepintshield-vk when a key is present.

shield.create_headers() adds transport attribution:

  • x-deepintshield-app
  • x-deepintshield-agent - omitted entirely when agent_name is unset, rather than sent empty
  • x-deepintshield-requester
  • x-deepintshield-requester-role
  • optionally X-Agent-Token with identity=True
from openai import OpenAI
client = OpenAI(
base_url=shield.endpoint("openai"),
api_key=shield.api_key(),
default_headers=shield.create_headers(),
)

Explicit extra values take precedence over generated headers. Treat an X-Agent-Token as a credential and never log the returned header dictionary. identity=True can perform lazy Agentic discovery/token acquisition; it is off by default so ordinary transport construction does not wait for identity.

For native OpenAI clients, use the shared public constructor options:

from openai import OpenAI
with OpenAI(**shield.openai_config(max_retries=2)) as client:
response = client.chat.completions.create(
model="anthropic/claude-sonnet-4-5",
messages=[{"role": "user", "content": "Hello"}],
)

openai_config() returns a fresh dictionary containing base_url, api_key, timeout, and merged default_headers, plus your native constructor options. It performs no model discovery or inference request; identity=True can trigger identity lookup. It preserves callable API keys and caller-supplied transports. The same options work with AsyncOpenAI. The request’s model ID selects the provider; there is no per-provider OpenAI client configuration to maintain.

Use shield.openai() / shield.async_openai() when you also want the SDK’s transport hooks for prompt caching and per-request agent-selector header normalization. openai_config() supplies constructor settings only.

The installed OpenAI SDK chooses its compatible HTTP transport: supported OpenAI 2.x uses httpx, while 3.x uses httpx2. A custom http_client must be accepted by the installed native SDK. Do not pass shield.http_client() to a library that requires a different transport implementation.

For other libraries accepting a URL/header pair or an httpx.Client:

base_url, headers = shield.connection(provider="openai")
with shield.http_client(provider="openai") as http:
response = http.post(
"/v1/chat/completions",
json={"model": "gpt-4o-mini", "messages": []},
)

http_client() returns a new httpx.Client; close it separately. A supplied base_url= overrides the provider-derived URL. This helper is useful only for libraries that accept an httpx.Client; prefer the typed provider builders when available.

payload = shield.request(
"POST",
"/api/guardrails/evaluate",
json_body={
"stage": "input",
"actor_type": "sdk_user",
"actor_id": "alice@example.com",
"input": "text to inspect",
},
)

request() joins base_url and path, sends JSON through the SDK-owned client, returns the decoded JSON value, and raises DeepintShieldError for HTTP status 400 or higher. For a non-JSON success response it returns {"raw": response.text}. It does not implement retries, pagination, file upload, incremental streaming, or an asynchronous transport. Incremental chat is provided separately by shield.chat(stream=True) and ChatCompletionStream.

Connection and timeout failures preserve their httpx.HTTPError or httpx.TimeoutException type and receive SDK error metadata. Catch those separately from DeepintShieldError, or read their annotation with get_exception_error_code() as described in Error codes.

Prefer a context manager or call close() during application shutdown:

with DeepintShield.from_env() as shield:
result = shield.guard(stage="input", input="hello")

close() is idempotent, unregisters the client from Agentic framework resolution, and closes its connection pool. Do not use a closed instance for new requests. If several live clients share a process, scope Agentic execution with with shield.agentic.run(...): so automatic framework enforcement can select the correct workspace and key.

Close native clients and framework-owned resources using their own lifecycle:

async def answer():
with DeepintShield.from_env() as shield:
async with shield.async_openai() as client:
response = await client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
return response.choices[0].message.content

Closing shield does not close a separately created OpenAI, AsyncOpenAI, or framework model client. Reuse those native clients within the application’s lifetime and close any partial streams before shutdown.

See Error codes for the complete structured transport-error contract.