> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flintai.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Usage

> Wrap LLM clients and route traffic through guardrails

The Flint AI Python SDK provides two integration paths: `flintai.wrap()` for standard LLM clients, and framework-specific plugins for agent frameworks like Google ADK and LangChain.

## Basic wrapping

Call `flintai.wrap()` on your existing LLM client. The SDK auto-detects the provider, rewrites the client's base URL to route through the guardrails proxy, and injects authentication headers. The same client instance is returned — mutated in place.

```python theme={null}
import openai
import flintai

client = openai.OpenAI()
client = flintai.wrap(
    client,
    gateway_url="https://app.flintai.dev",
    api_key="your-flintai-api-key",
)

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)
```

<Tip>
  Set `FLINTAI_GATEWAY_URL` and `FLINTAI_API_KEY` as environment variables, then call `flintai.wrap(client)` without parameters. See [Configuration](/flintai/platform/python-sdk/configuration) for details.
</Tip>

## `wrap()` parameters

| Parameter            | Type   | Default | Description                                                                                       |
| -------------------- | ------ | ------- | ------------------------------------------------------------------------------------------------- |
| `client`             | any    | —       | The LLM client to wrap (positional, required)                                                     |
| `gateway_url`        | `str`  | `None`  | Guardrails proxy URL. Falls back to `FLINTAI_GATEWAY_URL`.                                        |
| `api_key`            | `str`  | `None`  | Flint AI API key. Falls back to `FLINTAI_API_KEY`.                                                |
| `llm_api_key`        | `str`  | `None`  | Upstream LLM provider API key, forwarded as `X-LLM-API-Key`. Falls back to `FLINTAI_LLM_API_KEY`. |
| `policy_id`          | `str`  | `None`  | Guardrails policy ID. Falls back to `FLINTAI_POLICY_ID`.                                          |
| `require_guardrails` | `bool` | `True`  | Raise `FlintAIGuardrailsError` if guardrails can't be applied.                                    |
| `forward_llm_key`    | `bool` | `False` | Auto-extract the provider key from `client.api_key` and forward it.                               |

## Explicit initialization

For more control, use `flintai.init()` to initialize the SDK separately from wrapping. This is useful when registering plugins or when you want to configure guardrails once and wrap multiple clients.

```python theme={null}
import flintai

flintai.init(
    gateway_url="https://app.flintai.dev",
    api_key="your-flintai-api-key",
)

# Wrap clients without repeating credentials
client1 = flintai.wrap(openai_client)
client2 = flintai.wrap(anthropic_client)
```

`init()` accepts the same guardrails parameters as `wrap()`, plus:

| Parameter  | Type  | Default | Description                                                                                    |
| ---------- | ----- | ------- | ---------------------------------------------------------------------------------------------- |
| `provider` | `str` | `None`  | Explicitly set the provider (`"openai"`, `"anthropic"`, `"google"`). Auto-detected if not set. |

### Shutdown

Call `flintai.shutdown()` to clean up resources and restore wrapped clients to their original configuration. The SDK registers an `atexit` handler automatically, so explicit shutdown is optional in most cases.

```python theme={null}
flintai.shutdown()
```

## Google ADK

ADK agents lazily create their GenAI client at runtime, so `flintai.wrap()` cannot be used. Use `ADKGuardrailsPlugin` instead:

```python theme={null}
from flintai.plugins.adk import ADKGuardrailsPlugin
from google.adk.agents import LlmAgent

plugin = ADKGuardrailsPlugin(
    gateway_url="https://app.flintai.dev",
    api_key="your-flintai-api-key",
    llm_api_key="your-gemini-api-key",
)

agent = LlmAgent(
    name="my_agent",
    model="gemini-2.5-flash",
    instruction="You are a helpful assistant.",
    tools=[...],
    generate_content_config=plugin.content_config,
    before_model_callback=plugin.before_model_callback,
    on_model_error_callback=plugin.on_model_error,
)
```

<Tip>
  Set `FLINTAI_GATEWAY_URL`, `FLINTAI_API_KEY`, and `FLINTAI_LLM_API_KEY` as environment variables (or in a `.env` file), then create the plugin with no arguments: `ADKGuardrailsPlugin()`.
</Tip>

The plugin provides three components to pass to the ADK `Agent`:

* **`content_config`** — Configures HTTP options to route requests through the guardrails proxy
* **`before_model_callback`** — Injects agent identity (`X-Agent-Id`, `X-Agent-Name` from the callback context or `AGENT_NAME` env var) and session ID (`X-Agent-Session-Id`) headers on each LLM call
* **`on_model_error`** — Converts guardrails blocks (detected via the `GUARDRAIL_BLOCKED` error code) into an `LlmResponse` so the agent can handle them gracefully instead of crashing

<Note>
  The `before_model_callback` fails closed by default. If guardrails routing was never applied (the request has no `http_options`), it raises `FlintAIGuardrailsError`. Pass `require_guardrails=False` to the plugin for best-effort behavior.
</Note>

## LangChain middleware

For LangChain agents, use `LangChainGuardrailsMiddleware` to intercept model calls and inject guardrails routing:

```python theme={null}
from flintai.plugins.langchain import LangChainGuardrailsMiddleware
from langchain.agents import create_agent

middleware = LangChainGuardrailsMiddleware(
    gateway_url="https://app.flintai.dev",
    api_key="your-flintai-api-key",
)

agent = create_agent(
    model="openai:gpt-4o",
    tools=[...],
    middleware=[middleware],
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "Hello!"}]},
    config={"configurable": {"thread_id": "session-456"}},
)
```

<Tip>
  Set `FLINTAI_GATEWAY_URL` and `FLINTAI_API_KEY` as environment variables, then create the middleware with no arguments: `LangChainGuardrailsMiddleware()`.
</Tip>

The middleware automatically:

* Detects the underlying SDK client (OpenAI, Anthropic, or Google GenAI) from the LangChain chat model
* Applies guardrails routing on the first model call
* Extracts `thread_id` from the LangChain runtime config and attaches it as `X-Agent-Session-Id`

## Error handling

The SDK raises `FlintAIGuardrailsError` when guardrails can't be applied and `require_guardrails` is `True` (the default). Common scenarios:

* Missing `gateway_url` or `api_key` (and no environment variables set)
* Unrecognized client type passed to `wrap()`
* Async client passed to `wrap()` (not supported)
* ADK agent passed to `wrap()` instead of using `ADKGuardrailsPlugin`

```python theme={null}
from flintai import FlintAIGuardrailsError

try:
    client = flintai.wrap(client)
except FlintAIGuardrailsError as e:
    print(f"Guardrails not applied: {e}")
```

## Thread safety

* **`flintai.init()`**, **`flintai.wrap()`**, and **`flintai.shutdown()`** are **not thread-safe**. Call them from the main thread during application startup.
* Once initialized, **wrapped clients are thread-safe** — the underlying SDK clients handle their own concurrency.
* Double-wrapping is safe — the SDK detects already-wrapped clients and skips them with a warning.

## Async clients

Async clients (`AsyncOpenAI`, `AsyncAnthropic`) are **not supported**. Use sync clients only. Passing an async client to `wrap()` raises a `TypeError`.

## Best practices

* **Use environment variables** for credentials instead of hardcoding them. See [Configuration](/flintai/platform/python-sdk/configuration).
* **Pin your provider SDK versions** to the tested ranges to avoid breakage from private API changes. See [Integrations](/flintai/platform/python-sdk/integrations) for version compatibility.
* **Wrap once per client** during startup. The SDK mutates the client in place, so wrapping the same client multiple times is a no-op (with a warning).
* **Use `require_guardrails=False`** only in development. In production, fail-closed behavior ensures traffic is never sent without guardrails.

## Next steps

<CardGroup cols={2}>
  <Card title="Integrations" icon="plug" href="/flintai/platform/python-sdk/integrations">
    Provider-specific setup and version compatibility
  </Card>

  <Card title="Configuration" icon="sliders" href="/flintai/platform/python-sdk/configuration">
    Environment variables, credentials, and gateway setup
  </Card>
</CardGroup>
