Skip to main content
Xenovia is an OpenAI-compatible endpoint, so ChatOpenAI is the client for every Xenovia agent, whichever provider the agent routes to. The provider and model are configured on the agent and resolved server-side; the model argument in your code is a placeholder that the runtime replaces with the agent’s configured model.

Setup

The Python examples are checked with Python 3.12, langchain / langchain-openai 1.0.0 and langchain 1.4.0 / langchain-openai 1.6.1 using simulated HTTP responses. Validate your agent’s policies, guardrails, and provider configuration separately.

One client for every provider

Use ChatOpenAI no matter which provider is attached to the agent: Provider-native classes such as ChatGroq, ChatAnthropic, ChatBedrock, or ChatGoogleGenerativeAI use their own API paths and auth headers, so they cannot be pointed at the agent endpoint; a request from them returns 404. Pointed at the provider directly, they bypass Xenovia entirely, so those calls are neither traced nor policy-checked. The model argument is a placeholder. The runtime replaces it with the model configured on the agent, and the model field in the response reports the model that actually served the request. To change models, update the agent’s provider configuration rather than your code.

Chains

Use the configured llm in any LangChain chain. Every LLM call in the chain routes through Xenovia individually — each call gets its own trace.

Agents with tools

The Python example uses LangChain 1.x create_agent. Older examples using create_tool_calling_agent and AgentExecutor from langchain.agents do not work on 1.x. Tool definitions are passed to the upstream LLM through Xenovia. The request-stage Rego policy evaluates input.tool_names before the call reaches the model — a blocked tool returns 403 before the LLM is called. This checks the tools offered to the model, separately from authorizing a local action using model-generated arguments.

RAG pipeline

The generation step routes through Xenovia. The runtime does not expose /v1/embeddings yet, so point the embeddings client directly at your provider — an embeddings call sent to the agent endpoint returns 404.

Session tracking

The Python setup sets X-Xenovia-Session-Id on the client before constructing chains or agents, so all their LLM calls stay grouped in Sessions. Reuse it for the conversation, and create a new client and session ID for a separate conversation. Reassigning llm after creating a chain or agent does not update the client it already holds.

Forwarding the simulation session

Simulation sends your agent an X-Xenovia-Session-Id header with every turn. Pass it, unchanged, on each LLM call made for that turn:
Here llm is a ChatOpenAI built as in Setup but without default_headers. A session fixed on the client can’t follow Simulation, which runs several conversations at once, each with its own value. On the Xenovia cloud runtime the value is signed (xsim1.…) and a changed one is rejected with 400; on any runtime, a changed or dropped value means Simulation can’t grade a scenario’s tool and instruction-leak checks.

Handling policy blocks

LangChain propagates the upstream 403 as an openai.PermissionDeniedError. Catch it in your chain’s error handler.
Embedding calls are not governed by Xenovia today because the runtime does not expose /v1/embeddings. Keep OpenAIEmbeddings pointed at your provider and route only the chat model through the agent endpoint.