Examples

Wrap a LangChain agent

A LangChain agent becomes a monitored agent by setting one base URL on its model. No agent-side code changes.

LangChain agents reach their model through ChatOpenAI, ChatAnthropic, or a sibling class. Each of those takes a base_url. Point it at Sentisec and every step the agent takes is scored — the agent code itself does not change.

You need: a Sentisec workspace and API key, and an OpenAI key stored under Settings → Providers, in Provider keys.

An OpenAI-backed agent

pip install langchain langchain-openai
import os
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain_core.tools import tool

llm = ChatOpenAI(
    model="gpt-5.6-terra",
    base_url="https://api.sentisec.ch/ws/<your-workspace-id>/v1",
    api_key=os.environ["SENTISEC_API_KEY"],
)

@tool
def get_weather(city: str) -> str:
    """Return the weather for a city."""
    return f"Sunny in {city}, 21°C"

agent = create_agent(llm, [get_weather])

result = agent.invoke({"messages": [("user", "What's the weather in Lausanne?")]})
print(result["messages"][-1].content)

Your OpenAI key stays in your workspace; the key in this process is the Sentisec one.

Info
LangChain 1.x moved AgentExecutor

On LangChain 1.x, from langchain.agents import AgentExecutor raises an ImportError — AgentExecutor now lives in the langchain-classic package. langchain.agents exports create_agent, which builds a LangGraph loop and is what the sample above uses. If you are still on a legacy AgentExecutor loop, install langchain-classic and keep your existing code; the base-URL change is the same.

An Anthropic-backed agent

pip install langchain langchain-anthropic
import os
from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(
    model="claude-sonnet-4",
    base_url="https://api.sentisec.ch/ws/<your-workspace-id>",
    api_key=os.environ["SENTISEC_API_KEY"],
)

Note the missing /v1 — the Anthropic transport appends its own, the OpenAI one does not.

What the agent sees when a call is stopped

Sentisec does not error out the request. When it stops a tool call, the call is withheld and an explanation takes its place in the model's message. With no call left, the agent finishes and that explanation is its last message. You write nothing, and the tool never runs.

To let the agent re-plan instead, a workspace admin can opt in to rename; create_agent then hands the model Sentisec's reason and the loop keeps going. See LangChain.

What you will see

  • The agent's planning step, no tool use yet → NOMINAL
  • The agent invokes get_weather → NOMINAL
  • The agent reads a tool result carrying planted instructions → ELEVATED
  • The agent acts on those instructions, outside its declared task → SUSPICIOUS or HIJACK

Each of those is a step of the run under your workspace's Sessions.

Why this works with no integration

LangChain agents have no special surface in Sentisec — they are ordinary OpenAI and Anthropic clients. Sentisec sees the tool-call shape on the wire and evaluates it against your workspace's policy, whatever produced it. The same one-line change works for LangGraph, PydanticAI, LlamaIndex, and CrewAI.

Next

Protected docs