Integrations

Integrations

Route any agent framework through Sentisec with a base-URL change — and what your agent loop actually does when a tool call is blocked.

Sentisec speaks the Anthropic Messages API and the OpenAI Chat Completions API. Any SDK or framework built against either shape routes through it by changing one argument — the base URL. Your prompts, your tools, and your agent loop stay exactly as they are.

This section has a recipe per framework, a per-transport capability map, and the one thing most integration docs skip: what your agent actually experiences when Sentisec stops a tool call.

Pick your integration

The pattern

Every integration on this site is the same two lines of change:

  1. Point the client's base URL at your workspace.
  2. Use your Sentisec API key in place of the provider key. Sentisec holds the upstream credential, so your provider key never ships in your application config.

Everything downstream of that — tool schemas, streaming, retries, structured outputs — is unchanged. Frameworks that wrap a provider client inherit the change without knowing Sentisec exists.

If you would rather instrument in-process than swap a URL, the Python SDK ships wrap_anthropic and wrap_openai helpers; see the Python SDK quickstart.

Base URLs

https://api.sentisec.ch/ws/<your-workspace-id>        # the official Anthropic SDKs, Claude Code
https://api.sentisec.ch/ws/<your-workspace-id>/v1     # OpenAI-shaped clients, the Vercel AI SDK, Mastra

Your workspace id is on the dashboard next to your API key.

Whether the URL ends in /v1 depends on the client, not on the API it speaks. Use the same shape as the client's own default vendor URL:

  • No /v1 for the official Anthropic SDKs and Claude Code. Their default is https://api.anthropic.com and they append /v1/messages themselves, so adding /v1 produces /v1/v1/messages and a 404.
  • Ends in /v1 for the OpenAI SDKs and the Vercel AI SDK's @ai-sdk/openai and @ai-sdk/anthropic providers. Their default already ends in /v1 (https://api.openai.com/v1, https://api.anthropic.com/v1) and they append only the route: /messages, /chat/completions or /responses.

Vercel AI SDK and Mastra

The AI SDK's Anthropic provider is not the official Anthropic SDK: its base URL ends in /v1. Mastra agents take an AI SDK model, so the same URL applies to them.

import { createAnthropic } from "@ai-sdk/anthropic";

const anthropic = createAnthropic({
  baseURL: "https://api.sentisec.ch/ws/<your-workspace-id>/v1", // ends in /v1
  apiKey: process.env.SENTISEC_API_KEY, // your Sentisec key
});

Pass anthropic("<model id>") as the model of an AI SDK call or a Mastra Agent. createOpenAI from @ai-sdk/openai takes the same baseURL. The AI SDK's Amazon Bedrock provider is different: it speaks Converse and is configured as in Bedrock → Native Converse.

Use the workspace-scoped form. It is the one shape that guarantees your workspace's own policy travels with every request, on every transport. The recipes on this site all use it, and so should your production config.

What happens when a tool call is blocked

This is the part worth reading before you wire anything, because it decides how your agent behaves on the day a block actually fires.

A block never fails your request. It returns 200, with no exception and no error status, in the provider's own format.

The default: withhold

Sentisec removes the blocked call from the answer and puts an explanation in its place, as ordinary assistant text:

[Sentisec blocked tool_use: Sentisec policy blocked this tool call. …]

The shape is the same on Messages, Chat Completions, Responses and Bedrock Converse, streamed or not. Other calls in the same answer that only read keep their own decision. A call that changes something is not sent when another call in the same answer is held or refused (see calls proposed together). The turn ends with a standard value, tool_use or tool_calls while an allowed call remains, end_turn or stop otherwise. There is no Sentisec-specific stop reason.

With no allowed call left, your agent loop ends the run as it would on any final answer, and the explanation is that answer. It reaches the person or code that called the agent, not the model. You need no special case in your code, and the blocked call never runs.

Calls proposed together

A model often proposes several calls in one answer, for example a refund and a reply that confirms it. Sentisec reads such an answer as one plan. When one of its calls is held for approval or refused, the other calls in that answer that change something are not sent either. A reply cannot tell a customer about a refund that is still waiting for a person.

  • Calls that only read still run. A call only reads when its tool's class in protection setup says so. A tool with no class counts as one that changes something.
  • A call that needs approval itself is held with its own review. If two calls in one answer each need approval, such as two refunds, each is held and an admin approves each one. The agent still waits once. A call refused on its own is refused with its own explanation.
  • The agent is told why. A call that was not sent comes back the way a blocked call does. In place of a rule, it carries a fixed explanation: it was proposed together with a call that is waiting for approval, or with a call that was refused, so it has not run. It names no rule and no value.
  • The agent proposes it again. After an approval, the agent's retry of the held call is released once, and each call it proposes alongside is judged on its own. After a refusal, the agent proposes a call again on its own if it still needs it.
  • On a stream, the frames of a call that changes something arrive once every call in the answer has been decided, and so does everything after them. Text before them streams as the model writes it.
  • On shadow and observe nothing is held back. The calls run, and the session records that they would have been held back.

This applies to the API endpoints. In subscription mode, Claude Code and Codex are checked one call at a time.

Opt in: rename

If you would rather the model re-plans in the same run, a workspace admin can choose rename in the dashboard, on Protection → Enforce under More settings → When a call is blocked, or with PUT /v1/workspaces/{workspace_id}/recovery.

The blocked call then keeps its id and its place in the answer, but comes back named sentisec_tool_call_blocked, with these arguments:

{ "error": "tool_call_blocked", "reason": "<why the call was stopped>" }

A call held for approval also carries offers, which tell your application where to wait for the decision; see calls waiting for approval.

Your framework answers it the way it answers any tool it does not have. Sentisec replaces that answer with its own ruling before the model reads it, so the model learns why and can take another route. A third mode, notice, does the same under a notice tool your agent declares itself.

Rename needs a client whose tool loop answers an unknown tool. These are the clients and versions it works with:

ClientDefault (withhold)With rename
anthropic 0.120.2, tool runnerThe run ends with the explanationThe model gets the ruling and re-plans
langchain 1.3.14, create_agentThe run ends with the explanationThe model gets the ruling and re-plans
langgraph 1.2.9, create_react_agentThe run ends with the explanationThe model gets the ruling and re-plans
pydantic-ai 2.20.0The run ends with the explanationThe model gets the ruling and re-plans
llama-index-core 0.14.23, FunctionAgentThe run ends with the explanationThe model gets the ruling and re-plans
crewai 1.15.8The run ends with the explanationRe-plans, except on streamed Responses
openai 2.50.0The run ends with the explanationNo tool loop: the renamed call reaches your own dispatch code
openai-agents 0.23.1, RunnerThe run ends with the explanationOn Responses without streaming, the model gets the ruling and re-plans when you set RunConfig(tool_not_found_behavior="return_error_to_model"). Without it, the SDK raises an error on the unknown tool and the run ends. Chat Completions and streamed runs are not covered yet. See the recipe
@mastra/core 1.75.0, Agent on @ai-sdk/anthropic 4.0.78The run ends with the explanationOn Messages, streamed or not, the model gets the ruling and re-plans

The same list, with the API each client was checked on, is in the qualification field of GET /v1/workspaces/{workspace_id}/recovery.

Rename applies to the API endpoints only. The subscription lanes for Claude Code and Codex never use it.

Which to choose

The mode decides who learns about a block: the model, inside the run, or your code, after it.

  • withhold. When nothing else in the answer runs, the run ends, and its final answer is Sentisec's explanation. That text is written for your code, not for your customer, and the model does not get to act on it, so the agent cannot tell the customer anything about the block. If your application shows the agent's final answer to a customer, recognise the explanation and show your own message instead.
  • rename. The model reads the ruling in the same run. It can take another route, or tell the customer in its own words what happened, for example that a person has to approve a refund before it goes through.

Use rename when your client is on the list above for the API you call. Keep withhold otherwise: a client that is not on the list can raise an error on the renamed call, or hand it to your own dispatch code. In both modes the blocked call never runs, and a call held for approval can still go through once a person approves it; see calls waiting for approval.

A refused destination the agent can fix

Sometimes a recipient, an address or an account is refused because its value came from content outsiders wrote, such as an inbound email, and not from your organisation's own records or the user's request. The explanation then names the argument and says where its value must come from: your organisation's own records or the user's request. It invites the agent to take the value from there and propose the call again. It never shows the value. The new call is checked again from scratch, so a destination an outsider chose is still refused.

The agent can act on this only when it reads the explanation inside its run, which takes a recovery opt-in such as rename. Under the default, withhold, the run ends and the explanation reaches the person or code that called the agent. withhold stays the default.

When the agent does fix it, for example by looking the recipient up in your records, and its new call goes through, the session reads Blocked, agent recovered. Nobody needs to act on it. The refusal stays on the record and its review stays open, so you can still look at what the agent was asked to do. See session findings.

The other cases

  • Monitor-only (shadow). Every call passes untouched, including calls Sentisec would hold, the calls proposed together with them, and calls it could not read. The verdict still records what enforcing would have done. New workspaces start here.
  • A call held for approval. The explanation says the call awaits approval, and carries an offer with the address where your application reads the decision. After an admin approves it once, the agent's retry of the same request is released once, with the arguments the admin approved. An application that opens a new job, event or conversation for each attempt sends a new request, and a reworded retry there asks again: re-send the original instead. How to wait and re-send is in calls waiting for approval.
  • A tool call written as text. If a model prints a tool call as text instead of making one, the whole answer is withheld and the turn ends.
  • Sentisec cannot evaluate a call. The answer is still 200; the call is withheld behind a fixed explanation that carries a reference id.

Each framework page below shows what that framework does with a block.

Frameworks not listed here

If your framework targets Anthropic Messages or OpenAI Chat Completions — directly or through a provider abstraction — the base-URL swap works the same way. The recipes here are the ones we maintain and re-check; a framework's absence is not a limitation, just a gap in this list. If you want yours covered, tell us.

The recipes are Python. The TypeScript agent ecosystem (Vercel AI SDK, Mastra, OpenAI Agents SDK for Node) is not covered by a recipe on this site yet, though the official OpenAI and Anthropic Node clients are — see their pages above. For the AI SDK and Mastra base URL, see Vercel AI SDK and Mastra. A Mastra agent that waits for an approval and re-sends is in calls waiting for approval.

Automation platforms

The n8n-nodes-sentisec community node is in private preview and not ready for production workflows. If gating an n8n workflow is on your roadmap, talk to us — the Gmail triage recipe shows the workflow shape it targets.

Protected docs