A tool call you have denied never reaches your runtime.
Intercis is a proxy outside your agent process. Turn enforcement on and we take the call out of the model's response, so your runtime is handed nothing to execute.
- The model asked for
tool_use: bash rm -rf /var/app/releases- Your runtime received
- Text only, and an audit row naming the rule that matched.
When we are down
We are in the path. While we are unreachable your agents' calls to us fail, and we publish no uptime figure and no latency figure.
- What it governs
- Tool calls that cross the Anthropic and OpenAI API wire.
- Who holds the switch
- You do. An owner or admin on your side moves the tenant between observe and enforce, and the next call runs under it. The three ways to stop it
- Where it runs
- Our hosted proxy. No self-hosted build today.
- Who you work with
- The founder. Intercis is one person today.
Start a 90-day pilot
Five fields, and anything longer goes to sales@intercis.io. We do not touch your agents until you point one at us.
Sent. The sales team reads it, at sales@intercis.io. Your tenant starts in observe mode, so nothing changes in your agents until you switch it to enforce. In week one you point one agent at the proxy with its base URL and 2 headers, and each governed call is recorded as observe instead of deny.
What 90 days costs
Month to month on the Team tier, cancel any time, including during the 90 days. There is no separate pilot rate: this is the price afterwards too.
Team
Book a call for pricing Per registered agent
A design partner gets a reduced rate, quoted on the call too. We have not written down what we ask in return.
Month one stops nothing. Your tenant starts in observe mode, so the log is what you are buying, and enforcement is a setting you turn on in week 5.
The only fleet we have measured is our own: one agent, 10 days, in observe mode. Yours would be the first that is not.
- The hosted proxy on the routes we govern today.
- The dashboard: the event log with filters on verdict, provider and time window, a single-policy view, agent-ID search, and CSV export of the rows in hand.
- Time-boxed exclusions when a rule is wrong for your work.
Enterprise
Custom Quoted per fleet
- More than 20 agents, which we quote per fleet instead.
- There is no MSA. A pilot agreement and a data-processing addendum exist as drafts that no lawyer has yet reviewed, and this page plus the security page are our answer to a security questionnaire.
What a denied call looks like on the wire
Other tools return a verdict about an action. Intercis takes the action out: the model's
tool_use block is replaced with a plain text block, so the agent runtime
never receives a tool call to run.
The request path, in words. Your agent runtime sends its request to the Intercis proxy, which forwards it unchanged to Anthropic or OpenAI under your own provider key. The response comes back still carrying its tool_use block; the proxy judges that block, deletes it, and hands your runtime text only. A second path leaves the proxy: on a deny-rule miss it asks a classifier, and that call goes to Anthropic or OpenAI on an Intercis credential rather than yours, carrying the tool name and the full tool input.
What the model returned
{ "role": "assistant",
"content": [
{ "type": "text",
"text": "Clearing old releases." },
{ "type": "tool_use",
"name": "bash",
"input": { "command":
"rm -rf /var/app/releases" } }
] }
The agent runtime would have executed this block.
What your agent runtime received
{ "role": "assistant",
"content": [
{ "type": "text",
"text":
"Intercis blocked this action.
Policy: <policy>" } ],
"stop_reason": "end_turn" }
No tool call is left to run. The denial is logged with the rule that matched.
What your agent does next
The response carries stop_reason: end_turn, so the model's turn is over. We
hand your runtime no error and nothing is retried, so a loop part way through a job stops
there. On our own coding agent, 516 of 4,764 governed calls in ten
days were ones enforce mode would have removed. How many turns that would have ended we
do not know: the window ran in observe mode, where nothing was stopped.
These are shapes, not transcripts. The text block we substitute names the policy and says the event was logged.
How you stop it
Three levers. Two are in your dashboard; the third is the setting that put us in the path.
| Lever | Who | When it takes effect | What it leaves behind |
|---|---|---|---|
| Move the tenant back to observe | An owner or admin, in the dashboard | The next call | An audit row naming the account, the old setting and the new one. Logging carries on and no call is deleted. |
| Deactivate one agent | An owner or admin, in the dashboard | The next call | A deny in your event log under agent-identity-unknown for every call that agent then makes. No admin audit row. |
| Point the base URL back at the provider | Whoever can change that agent's configuration | The next call that agent starts | Nothing of ours. The traffic runs ungoverned and we see none of it. |
Enforcement is one setting on your tenant, read when we check your key on every call. If the audit row for that change cannot be written, the change is refused rather than made quietly. A deactivated agent's calls are refused with a 403 rather than falling through to the provider.
Who can do any of it: sign-in is an email and a password, or a link to that address, with no SSO and no MFA today. Of the four roles, owner, admin, member and viewer, only owner and admin can change enforcement, deactivate an agent or issue a key.
What it stops today
A governed call is a tool call that crosses the Anthropic or OpenAI API wire and that your runtime would run.
-
Two layers judge the call
Credential theft, secret-vault access, destructive shell, log tampering, encoded execution, container escape, privilege escalation and data exfiltration are stopped by pattern, before any model is asked. 112 deny rules, counted in the repository on 6 October 2026, at commit
7024101. They sit under 18 policy-name prefixes and 17 threat-category headings in the file, a count read on 12 September 2026. They are regular expressions, so the same call gets the same verdict every time and you can work out why.When no rule matches, an intent classifier reads the call's content and answers in one word. It is asked only about tools that can act: execution tools, file-writing tools, and any
mcp__tool your runtime executes. A missing or malformed tool name goes to the classifier rather than past it, and read-only tools are outside that gate on purpose. -
Floors an operator cannot waive
Four families cannot be released at any scope by anyone holding an account: credential access, secret-vault access, log tampering and encoded execution, with their Windows equivalents, such as LSASS dumps, registry hive saves and encoded PowerShell. An exclusion against one of those is refused whatever scope it names.
Everything else can be excluded when a rule is wrong for your work, and no exclusion becomes a permanent hole: an end date is required. A policy-wide waiver is refused for the classifier rule and the tool-scope rule, so an exclusion there names a command fingerprint, a target substring or a path. If the exclusion store is unreachable, no exclusion applies and the rules stand.
A call we cannot read in full is stopped, not passed. Past 65,536 bytes the scan stops, the call is denied structurally, the classifier is not asked, and that deny skips the exclusion check.
-
One row per governed tool call, hash-chained, and what that log can lose
Each governed tool call writes a row while the database is up, and the shape of one is at the end of this page. Of 4,764 governed calls on our own agent, 516 were ones enforce mode would have removed; the rest are rows saying a call was allowed, the same fields with allow in the verdict column. The tool input is stored with the row, known credential patterns masked first. Every row carries a SHA-256 over its own fields plus the previous row's hash, one chain per tenant, computed by a database trigger before the insert. On a row recorded from 2026-09-20 that covers every column of the event except the tool input, which a nightly job empties at 90 days; rows recorded earlier are hashed over ten named fields and are never re-hashed.
Whether the row proves who called depends on the key. Bound to one agent, possession of the key is the identity and a call under another agent's name is refused. Unbound, which is what a key is until someone binds it, the agent name is whatever the caller puts in the header, so any holder can write rows as any registered agent of your tenant.
There is no self-serve export of the chain today: the dashboard exports eight columns and neither hash is among them. No client role holds UPDATE or DELETE on the table, so neither your users nor a compromised agent can touch a logged verdict. We hold the service role and it bypasses that, so the chain is tamper-evident, not tamper-proof: somebody with our database credentials could rewrite a tail and recompute the hashes, and only a hash recorded outside our database would catch it. Nothing we ship puts one there.
When the database is unreachable, only deny rows are held back and re-inserted later; an allow or an observe row that fails to insert is lost. Our code says it plainly: those rows are telemetry and the deny rows are the product. In observe mode every row is an observe row, so the log for month one is best-effort throughout. Blocking never waits on the audit write, which is why the write may fail at all. The held-back denies go to a 5 MB file on the proxy's own disk, oldest lines dropped once it is full and not on a volume.
A missing row leaves no gap in the chain: the next row's
prev_event_hashstill points at the last row written. The chain catches a rewrite that left the hashes after it alone, not omission, and omission is what happens when the database blinks. -
What it costs when we are right, and when we are wrong
Our pattern layer catches 40 of the 47 payloads in our own agentic-threat corpus, 85.1%, with 7 documented bypasses. Measured 12 September 2026. We wrote the corpus, so it measures regression stability, not an attacker.
It holds no safe payloads, so it says nothing about how often we would stop work that was fine. We measured that separately, on our own coding agent: 737 of 4,764 governed tool calls, 15.47%, are calls today's rules flag on traffic we labelled benign, with a 95% interval of 14.47% to 16.52%. One agent, 10 days of traffic ending 4 September 2026, in observe mode, with 31 August taken out because a four-hour classifier outage voided it. 516 of the 737 are calls enforce mode would have removed and 221 are injection-scan rows, which never block. The working is on the benign-corpus report.
The seven we miss are worth more to you than the 85.1%. Five are obfuscations of one destructive command, each rewriting it so the rule's word never appears as typed. Two of the five do not run as written. The other two are tool poisoning, where the command we can see is harmless and the instruction sits in the file it reads. We do not publish the techniques. Underneath us there is the classifier and your own egress rules.
-
What Anthropic and OpenAI give you themselves
Both sell an export of what happened: Anthropic's Compliance API and OpenAI's Compliance Logs Platform return conversations and coding-agent transcripts minutes after the fact, for Enterprise plans. Anthropic also runs an inline hook that can refuse a prompt before the model sees it; it fires on the prompt, so a tool call reaches it only after it ran on the machine. OpenAI has no server-side hook: its Codex controls run on the device and apply to Codex only, and its remote hooks cover MCP tools alone and, by OpenAI's own words, a hook error or timeout does not block the tool. Neither compliance export covers an agent running on a plain API key, which is the agent you built and the one that routes through us. Intercis judges the tool call on the wire, before your runtime can run it, on either provider. Verified against both vendors' documentation on 1 October 2026.
The 90 days
Nothing is blocked until you turn it on.
-
Week 1
Point one agent at the proxy, in observe mode
The whole integration is a base URL and 2 headers, 1 of them required, and none of it is a code change:
the base URL your client already reads ANTHROPIC_BASE_URL=https://api.intercis.io the key we issue you, required on every call x-intercis-key: ik_live_... the agent's name; a key bound to one agent does not need it x-agent-id: your-agent-idThe key is
ik_live_and 64 hex characters. We store an HMAC-SHA256 of it, never the key, and show the plaintext once. Bind it to one agent: unbound is the default, and it lets any holder claim any registered agent of your tenant.Your tenant starts in observe mode: the verdict is computed for every governed call and recorded as observe instead of deny. Those rows are best-effort, which is the gap in the log above.
From you: one agent whose failure you can absorb, someone who can change its base URL, and your security review in the first two weeks.
-
Weeks 2 to 4
Read the log
By week 4 the log tells you what your agents asked for and which of those calls we would have stopped. Exclude a stop you disagree with: an owner or admin writes the exclusion in the dashboard, with a reason of at least twenty characters and an end date it cannot be without. When it lapses the rule applies again, and nothing tells you it has. The pilot creates a standing job: somebody reads those stops, writes the exclusions, and writes them again when they expire.
From you: a named person who reads the event log each week, writes the exclusions and re-reads them as they lapse.
-
Week 5
Turn enforcement on, and off again
Your owner or admin moves the tenant from observe to enforce in the dashboard, and back the same way. It takes effect on the next call and covers that tenant's agents together.
From you: the decision to switch it on, once the log has given you a reason, and an owner or admin account to make it.
-
Weeks 6 to 13
Widen it, and see what you are holding
Add the rest of the agents, one at a time or together. Each is the same two settings and its own key. At day 90 you hold one row for every governed call your agents made, in our database, each naming the rule that matched and hash-chained to the row before it. Then you keep going month to month or you cancel. There is nothing underneath the subscription to cancel.
From you: the rest of the agents, once the first has satisfied you.
What this does not cover
Five costs, three gaps and one limit on the audit chain, under the same headings as what Intercis does not cover, with what we are doing about each. What it costs when we are wrong is measured above.
-
Being in-path is a setting, not a law
Your agent routes through Intercis because its base URL says so, and a compromised process can point that URL somewhere else and go straight to the provider. Pair us with an egress rule blocking direct calls to
api.anthropic.comandapi.openai.com. Without one we are a control a compromised process can walk around.What we are doing about it: By design. Being in the path resists tampering only alongside an egress rule on your own network, and that rule is yours to set.
-
Only the provider API wire is visible
Tools the provider runs on its own servers have already run by the time the response reaches us: hosted MCP calls, web search, file search, code interpreter and image generation. Each writes an audit row with the verdict observe, naming the tool; none is judged, and none can be stopped. If your agents use hosted MCP servers, you can see that traffic and we cannot govern it.
What we are doing about it: Nothing is scheduled. A hosted tool call is observed, not governed: it writes one observe row and is never judged or blocked, and no governance of hosted tool calls is planned.
-
Streaming is buffered before anything is judged
To judge a tool call we have to see all of it, so the proxy collects the whole stream, reassembles the tool calls, judges them, then replays it. That adds latency equal to the full stream duration before your agent sees any output, and if your product streams tokens to a human you will feel it.
What we are doing about it: By design. The wait is the price of judging a call before it is delivered rather than after.
-
We are a new place your prompts pass through
Your prompts and tool inputs pass through our proxy in plaintext. We store the tool input rather than the conversation, plus the first 200 characters of any user message the injection scanner matches. Relayed traffic runs on your provider key, which we do not store; the classifier call runs on our credential, so the tool name and input reach Anthropic or OpenAI under an Intercis account rather than your agreement with them. There is no self-hosted build today.
What we are doing about it: Undecided. How a self-hosted build would be licensed has not been decided, and nothing is scheduled.
-
The provider routes are ours to maintain
The routes we govern today are Anthropic's messages route and OpenAI's responses and chat completions routes. A new provider, or a new route shape at an old one, is work we have to do first, and until we have that traffic is not governed.
What we are doing about it: By design. It is the standing cost of sitting outside your agent process, and it is ours for as long as the product exists.
-
If we are unreachable, your agents stop
We are in the path, so while we are unreachable your agents' calls to us fail. There is no SLA, no uptime number and no latency number: we publish none of them today, and we will not quote a number we have not measured. A co-located latency benchmark is an open item on our roadmap, and the pilot is where you measure it in your own environment. The proxy is one hosted service behind a health check on
/health. It restarts on failure, and on a deploy the old instance drains for 30 seconds while the new one overlaps it for 60. It will take 300 requests a minute from your tenant by default, counted in memory on the instance, so that is a per-instance limit rather than a distributed guarantee.Nothing queues and nothing routes around us; the break-glass is the third lever above. One engineer, no on-call rota, and the alarms go to our error tracker, where you do not see them. A first engineering hire is on our roadmap, gated on revenue rather than on intent.
What we are doing about it: By design. We sit in the path so that a denied action cannot reach your agent, and a control in the path that let traffic through while it was down would be a way around itself.
-
The classifier fails open
When the intent classifier cannot answer, the call is allowed on the default setting and stopped on fail closed. The deny rules still enforce underneath it, the row records that the classifier was unavailable and why, and the proxy raises an alarm once a rolling window of 200 consultations shows an unavailable share above 5%.
The prompt-injection scanner is separate and softer: 13 fixed patterns in four families, instruction override, prompt extraction, role hijack and delimiter escape. A hit is recorded and flagged, and nothing is stopped.
What we are doing about it: Built: a per-tenant setting to fail closed, so a call the classifier cannot answer is stopped and recorded as denied. The default stays fail open, no tenant has switched, and switching is a request to us until the dashboard carries the toggle.
-
The audit log can have holes
When the database is unreachable, only deny rows are held back and re-inserted later; an allow or observe row that fails to insert is lost, and a missing row leaves no break in the chain. In observe mode every row is an observe row, so the log for month one is best-effort throughout. The detail is with the log, above.
What we are doing about it: No change is scheduled. Blocking never waits on the audit write, and that is why a write can fail.
-
The audit chain has no anchor outside our database
Nothing outside our database records any row's hash, and the dashboard export carries neither hash column. Somebody with our database credentials could rewrite a tail and recompute the hashes, and the chain would still verify.
What we are doing about it: Planned, not built: signed, hash-chained receipts and a verify route that answers, so a hash can be checked outside our database. There is no date.
For the reviewer you forward this to
- The security page The controls, the auth model, the failure modes, and the sentence saying Intercis is not SOC 2 certified.
- The privacy page What is stored, for how long, and who processes it.
- The validation report The detection figures with their labels, and how to re-run them.
One audit row, in the shape it is stored:
id 0f9b2c31-6c4e-4d21-9a77-2b0d5f8e1a44
tenant_id 7c1a4d90-5f33-4e0a-8b62-1d9e77c0b512
created_at 2026-09-12T14:22:07Z
agent_id build-agent-3
action bash
target terraform destroy -auto-approve
verdict deny
policy infra-terraform-destroy
injected false
source anthropic-messages
classifier_status not_run
event_hash 9f2c...
prev_event_hash 4a71...
target is a readable excerpt of the command, path or query. It is hashed
in both chain formats and it is kept for the life of the tenant. The full tool input
sits in a separate column that a nightly job nulls at 90 days, deliberately outside the
hash.
On a row recorded from 2026-09-20, event_hash is a SHA-256 over every line
above except the two hash columns, plus prev_event_hash and the row's
remaining columns, the tool input excepted. On a row recorded earlier it covers ten
named fields, and classifier_status is not one of them.
What a reviewer asks
How do we turn it off in a hurry?
Move the tenant back to observe, deactivate the agent, or point its base URL back at the provider. The first two are in your dashboard and take effect on the next call; How you stop it has who can pull each and what it leaves behind.
Can we verify the chain ourselves?
Our published sample chain, yes, today and in about a minute: the verifier, the sample chain and the trigger that writes the hash are public, and How it works walks through the check. Your own rows, not today. The verifier reads a JSON export of the whole row minus the tool input, both hash columns included; the only export you have is the eight-column CSV, and no endpoint returns the head hash. For the whole 90 days the chain over your rows is ours to check and not yours. A self-serve export carrying the hashed fields, and a verify route that answers, are open items on our roadmap with no date.
Do you store our prompts?
One piece, yes: when the injection scanner fires it keeps the first 200 characters of
the matching user message. Otherwise we store the tool input and not the conversation,
and a nightly job nulls that input at 90 days. The audit row stays for the life of the
tenant, target included.
Do you have a SOC 2 report?
No. Intercis is not SOC 2 certified and no audit is underway. What a reviewer gets instead is the security page and the list of what we do not cover on this one.
What happens if the company stops?
Being in path is a setting, not an installation, so your agents run as they did before as soon as the base URL changes. Your event rows live in our database, and what you can take with you is the eight-column CSV.