What is AI agent threat detection?
AI agent threat detection finds hostile input and risky behavior in the four places a threat reaches an agent: the content it reads, the hosts it connects to, the sequence of actions in its session, and the clients that call its endpoints. A detection that runs before a tool call executes can stop the action. One that runs afterward can only report it.
An AI agent is a program that uses a language model to choose actions and then takes them through tools: it reads files, fetches web pages, runs shell commands, queries databases, and calls other services. Each of those tools runs with real credentials. A threat to an agent rarely looks like malware on disk. It looks like a sentence in a support ticket that tells the agent to send a customer list somewhere, or a curl command to a host that has been serving malware for a week.
The term doesn't have a settled definition. Endpoint security vendors use it for behavioral detection on the machines where agents run, cloud providers use it for findings about agents deployed on their platforms, and sandbox vendors such as Blaxel use it for watching a workload while it runs and flagging behavior that signals compromise. This article uses the broader meaning and organizes it by where the threat shows up, because that decides which control can see it.
How is threat detection for AI agents different?
Traditional threat detection watches processes, files, and network flows for known-bad patterns. An agent's dangerous actions often look normal at that level: a signed binary makes an HTTPS request with a valid token. What makes the action hostile is why the agent took it, and that lives in text the agent read a few steps earlier.
Consider a coding agent asked to fix a failing test. It reads the repository's README, which an attacker edited to include an instruction to upload the .env file to a paste site "for debugging." The agent runs curl with the file attached. An endpoint sensor sees a developer tool making an outbound request, which developer machines do all day. The evidence that matters is the injected text and the destination, and the window in which you can act on them is before the command runs.
That's why agent threat detection works best at the agent's own decision points: the moment content enters its context, the moment it's about to call a tool, and the moment a request reaches its API. A detection at any of those points can feed a policy, which is a set of rules that allows or denies the action.
Where does a threat show up for an AI agent?
A threat reaches an agent through what it reads, where it connects, what its session does over time, or who calls its endpoints. Each surface needs a different detector, and a detector built for one surface is blind to the others. A prompt injection model can't tell you that a host is malicious, and threat intelligence can't read a README.
The following table maps each surface to the signal that detects it and the Arcjet control that applies:
| Surface | Example threat | Signal | Arcjet control |
|---|---|---|---|
| What the agent reads | Instructions hidden in a web page, document, or tool result | Prompt injection detection | Prompt injection detector in guard() or protect() |
| Where the agent connects | A fetch or curl to a host known for malware or scanning | IP threat intelligence on the destination host, plus an allowlist | IP threat detector on the tool call |
| What the session is doing | Credentials read, then an upload to an external host | Session flags such as credential_access and data_exfiltration | Session analysis on coding agents |
| Who calls the agent's endpoints | Scripted clients running up model costs on a chat route | Bot detection, IP reputation, and rate limits | protect() on the HTTP route |
Arcjet runs these checks in the path of the action. In your own agents, the JavaScript, Python, and Go SDKs call guard() before a tool runs and protect() on an HTTP route. In coding agents such as Claude Code, GitHub Copilot, Cursor, OpenAI Codex, and Muse Code, Arcjet decides each call from the agent's hooks. A hook is a request the agent sends to an outside service at fixed moments, such as before a tool call, and the answer can stop the call. One policy covers all five agents with no code change.
How do you detect threats in what an agent reads?
Screen text for prompt injection at the point it enters the agent's context: the user's message, a retrieved document, a fetched web page, or the result of a tool call. Prompt injection is text written to override the agent's instructions. When the payload arrives inside retrieved content rather than from the user, it's called indirect prompt injection.
Arcjet's prompt injection detector runs on Arcjet's own AI security models and returns a yes-or-no verdict. In an HTTP route, protect() checks the incoming prompt before your code calls the model provider. Inside an agent, guard() checks a string before you hand it back to the model, such as the readable text of a page your fetch tool retrieved. The text is sent to Arcjet for evaluation, and the check adds about 100 ms.
A detection is most useful as one fact in a policy rather than as a verdict on its own. Arcjet policies are written in Rego, a declarative policy language from the Open Policy Agent project, and a policy declares detectors, which are checks Arcjet runs on a named input before the rules evaluate. The following rule from the Arcjet policy examples denies a destructive tool only when the message behind it shows injection, so a flagged message can still reach a read-only tool:
deny contains "injection-on-destructive-tool" if { input.signals.prompt_injection.message_check.detected input.values.destructive}Coding agents are a harder case. A hook that reports a tool result fires after the tool ran, and Arcjet's hooks don't withhold that result from the model. Arcjet screens what the agent reads, such as tool results and fetched pages, as part of session analysis, which a later section covers. For the design of screening, provenance, and containment in your own pipelines, see defending against indirect prompt injection in agentic workflows.
How do you detect threats in where an agent connects?
Look up each host that a tool call is about to contact in threat intelligence, and deny the call when any host scores high or critical risk. The check belongs on the tool call, because that's the last point before the connection opens. Pair it with an allowlist, because threat intelligence has no record of a domain registered yesterday.
Arcjet's IP threat detector reads hosts from a SERVER input, which is a value your code sends to Arcjet for evaluation. It accepts absolute URLs, bare hostnames, and IP addresses, and ignores other text. It resolves each hostname, looks up each public address in Arcjet threat intelligence, and scores each host by its riskiest address. That's the same data that scores the caller of an inbound request in protect(), applied in the other direction. The rolled-up verdict reports the worst host, with per-host results in assessments.
The following policy denies a call when the detector with the ID dest scores any host high or critical:
package arcjet.guard
import rego.v1
deny contains "malicious-destination" if { input.signals.ip_threat.dest.risk_level in {"high", "critical"}}Name the set of risk levels. A string comparison such as >= "high" gives the wrong answer, because alphabetical order puts critical before high.
In a custom agent, call guard() inside the fetch tool before it opens a connection. The following example sends the URL as the destinations input to a policy published under the label web.fetched, which declares the dest detector over that input:
import { launchArcjet, policyInput } from "@arcjet/guard";
const arcjet = launchArcjet({ key: process.env.ARCJET_KEY! });
export async function fetchTool(url: string, userId: string) { const decision = await arcjet.guard({ label: "web.fetched", actor: userId, inputs: { destinations: policyInput.server.stringList([url]), }, });
// An unfinished check isn't a pass. Treat it as a denial. if (decision.conclusion === "DENY" || decision.hasFailedOpen()) { throw new Error("Destination blocked by policy"); }
// The policy scored this host only, so refuse redirects to another one. return fetch(url, { redirect: "error" });}The direct guard() client fails open when it can't complete an evaluation, for example on a timeout, so the check on hasFailedOpen() matters. The detector doesn't fetch URLs or follow redirects, so a fetch tool that follows a redirect can reach a host the policy never scored.
On coding agents, Arcjet fills destinations for you from each tool call: the URL arguments of web tools, and the absolute URLs and connection targets of curl, wget, ssh, dig, and git in shell commands. The coding-agent.destination-threat starter policy applies the same Rego on every tool call. For the full verdict fields and failure behavior, see how to stop AI agents contacting malicious URLs and domains. For the allowlist and how to combine it with scoring in one policy, see how to build an egress allowlist for AI agents. The same idea applies to Model Context Protocol (MCP) servers, which expose tools to an agent over a standard protocol. For more information, see what a rogue MCP server is and how to detect one.
How do you detect threats across a whole agent session?
Watch the session as a sequence, set a flag when the sequence looks like an attack, and refuse risky follow-up calls while the flag is set. Some threats are invisible in any single call. Reading ~/.aws/credentials is routine, and so is an HTTPS upload. The two together, in that order, in one session, are what credential theft looks like.
Arcjet session analysis does this for coding agents. It screens tool results, reviews the session's activity, some of it in the background, and sets named flags on the session. The agent can't set or clear them. The flags that matter most for threat detection are the following:
prompt_injection: a tool result tried to override the agent's instructions.credential_access: a tool call looks like it reads credentials.data_exfiltration: a tool call looks like it sends local data out.code_execution_risk: a tool call looks like it runs untrusted code.sensitive_data_exposure: a tool result contains an entity type that the policy's sensitive information detector denies.elevated_risk: the session as a whole looks like an attack.
The coding-agent.session-analysis starter policy reads the flags on every later tool call. After prompt_injection, data_exfiltration, code_execution_risk, or elevated_risk, it refuses shell commands, web requests, MCP calls, and file writes. After credential_access or sensitive_data_exposure, it refuses only web and MCP calls, the calls that could send data out, while local work continues. File reads stay allowed in both cases, so the agent can keep answering the developer.
A person clears a flag in the Arcjet Console, with a required reason that goes to the audit log. Flags also expire after a period with no new findings. Session analysis can't undo what happened before the flag was set. It contains the calls that follow, not the one that triggered it. For more on the model, see what session tainting is.
How do you detect threats against an agent's own endpoints?
Check the client on every request to the routes that reach your agent, before your code spends a model call on it. A public chat or agent endpoint draws the same automated traffic as any API, with a higher cost per request, because each one can trigger model calls and tool use that you pay for.
Arcjet protect() runs in your HTTP handler and decides each request with rules that you configure in code. Bot detection identifies automated clients and lets you allow verified ones, such as search engine crawlers. IP analysis labels the caller's network as VPN, proxy, Tor, or hosting, flags known abusers, and, when available, adds a threat assessment with a risk level, reputation, and observed activities. Rate limits cap requests per user or per IP. Shield, Arcjet's application-aware web application firewall, tracks probing for paths such as .env and admin panels across requests. You can add prompt injection detection on the same route to check the user's message.
Inbound checks cover requests to the agent. They don't see what the agent reads after it starts working, which is why the other three surfaces need their own detectors. For more information, see AI agent bot management.
How does detection and response compare with a decision before the tool call?
The two cover different failures, and most teams need both. A decision before the tool call can stop a known-bad action, but only for actions it can see and threats it can recognize. Detection and response after the fact sees more of the machine, correlates across hosts and identities, and catches what no rule anticipated, but the action has already happened by the time it reports.
Google's Agent Platform Threat Detection is an example of the after-the-fact model. It's a Security Command Center service, in Preview, that monitors agents deployed to Google's Agent Runtime for threats such as reverse shells, container escapes, and malicious scripts. Control-plane detectors also analyze audit logs and Agent Runtime logs. The documentation describes detection and findings, not blocking. It produces findings in Security Command Center in near-real time, with names such as "Exfiltration: AI Agent Initiated BigQuery Data Exfiltration to External Table." Details come from Google Cloud's public documentation, checked on November 6, 2026.
SentinelOne's Singularity Agentic Detection and Response (ADR), announced on October 21, 2026 in early access, combines both models. The announcement says it blocks prompt injection, jailbreaks, credential exfiltration, and tool poisoning before the action executes. The same behavioral detections that the Singularity Platform already runs on endpoints, cloud workloads, and identities judge agent activity there, and a security team can stop one agent mid-action without halting the rest of the workflow. It also covers platforms such as Salesforce Agentforce and Microsoft Copilot Studio. Details come from SentinelOne's launch announcement, checked on November 6, 2026. For a direct comparison, see SentinelOne vs. Arcjet.
Arcjet makes its decision before the call. It decides each prompt and tool call in your code or in the coding agent's hooks, and records the decision, which is evidence a responder can use later. It doesn't run on the network or as an endpoint sensor, so it doesn't see a process that opens a connection outside any tool call the agent reports. Endpoint and cloud detection cover that gap. In the other direction, an after-the-fact finding about a reverse shell can't give you back a secret that already left, and a policy on the tool call can stop the upload before it starts.
What are the limits of AI agent threat detection?
Every detector here misses something. Threat intelligence has no record of new domains, Arcjet's hooks don't withhold a tool result, background analysis can land after more calls, and a prompt injection model makes mistakes. Build each policy around what its detectors can and can't see. The following limits apply to Arcjet's detectors:
- A host that can't be looked up scores risk
none. If DNS resolution or the threat lookup fails, the host is treated as clean. A rule that must deny unverifiable hosts needs an allowlist as well. - Threat intelligence misses new and unlisted domains. A domain registered this morning, or a public file-sharing site with a clean reputation, doesn't score high or critical. An allowlist catches those, and threat scoring catches known-bad hosts you never thought to list.
- A call with more than 30 distinct public hosts fails a live rule closed with
AJP1009, rather than scoring part of the list. - Destination scoring isn't a defense against server-side request forgery (SSRF), where an attacker steers your code to an internal address. Private, loopback, link-local, CGNAT, multicast, and unspecified addresses aren't scored, so a call to an internal address passes.
- Some session analysis runs in the background, so the agent can make more calls before a flag lands. The calls in that window are decided without it.
- Arcjet doesn't block a coding agent's tool result. The hook fires after the tool ran, so screening can flag the session but doesn't withhold the text from the model.
- Prompt injection detection is a model, so it produces false positives and misses. On a coding agent, a detector over the developer's own prompt flags legitimate work that quotes injection text, which is why Arcjet doesn't offer it as a starter yet.
Arcjet starts every new rule in dry run, which records what the rule would deny without blocking anything. Publish the starters in dry run, read what they would have denied, and set them live once the results match what you expect. For the broader runtime picture, see AI agent runtime security, and for the platforms that cover parts of it, see AI agent security platforms compared.
Learn more: Threat detection · Session analysis · Coding agent policies · Remote policies
Frequently asked questions
What is AI agent threat detection?
It's the practice of finding hostile input and risky behavior where a threat reaches an AI agent: the content it reads, the hosts it connects to, the sequence of actions in its session, and the clients that call its endpoints. A detection that runs before a tool call executes can stop the action. One that runs afterward can only report it.
How does threat intelligence apply to AI agents?
An agent is an outbound client, so threat intelligence can score the hosts it's about to contact. Arcjet's IP threat detector resolves each host a tool call names, looks up its public addresses in Arcjet threat intelligence, and lets a policy deny the call when any host scores high or critical risk. Pair it with an allowlist, because a new or unlisted domain has no threat record and scores risk none.
Can you block a malicious tool result in a coding agent?
Not with Arcjet. The hook that reports a tool result fires after the tool ran, and Arcjet doesn't withhold the result from the model. Arcjet session analysis screens tool results and flags the session, for example with prompt_injection or data_exfiltration, and the session analysis starter policy then refuses risky follow-up calls such as shell commands, web requests, and MCP calls.
Is destination threat scoring a defense against SSRF?
No. Arcjet doesn't score private, loopback, link-local, CGNAT, multicast, or unspecified addresses, so a call to an internal address passes. Server-side request forgery needs its own checks. A host that can't be looked up also scores risk none.
Should I use agentic detection and response or a policy before the tool call?
Most teams need both. A policy before the tool call can stop a known-bad action, such as an upload to a high-risk host, before it runs. Detection and response products, such as endpoint or cloud platform tools, see activity outside the calls an agent reports and correlate across hosts, but a detection after the fact reports an action that has already happened.
AI runtime security in your code
Protect your AI agent workflows with Arcjet
Add a threat check to your agent's fetch tool with guard(), and publish the policy in dry run to see what it would deny before it blocks anything.