Skip to main content
The DLP agent is a thin enforcement point. Every meaningful decision is made centrally in your Blindsight workspace and pushed to the agent via /agent/policy. This page covers what that policy looks like and which backend endpoints the agent talks to.

What policy controls

All of these are managed centrally. The agent never makes a local policy decision; it fetches the latest version from the cloud.

Where to edit policy

Policy comes from two places, and the difference matters. Policies has its own page in the DLP menu. It used to sit inside Configurations alongside the settings; it is a thing you come to manage rather than a setting you adjust once, so it now stands on its own. The old link still works and lands on the new page. Thresholds, custom phrases, custom PII rules and tool policy are the same as SDK-mode Runtime Security and are edited on the App the agent is attributed to (see Apps).
The default policy is a floor, not the final answer. Policy resolution merges most-restrictively, so a named policy assigned to somebody can be stricter than the workspace default but never looser.Fail mode is where this is felt most often: if the default says Send anyway and an assigned policy says Stop, the people that policy reaches get Stop. The Fail mode row names any assigned policy that overrides it and links straight to it, so the screen cannot show one answer while a device enforces another.

AI host rules

The agent only intercepts traffic to hosts on the AI host list. Every other connection passes through untouched.

Built-in host pack

Blindsight maintains a default host pack covering every supported provider. DLP policy → Use default host pack toggles it on; you can layer your own overrides on top.

Rule actions

Beyond which App owns a host, every rule carries an action that decides how far the agent goes on that connection. The discovery catalog is merged in as observe rules, so anything AI that you have not onboarded still shows up as an inventory row without ever being decrypted. Overrides layer on top of the defaults and the catalog, and the most specific matching host wins. When two assignments disagree about a host, the strongest action wins, ranked block > inspect > protect > tunnel. protect sits below inspect because both decrypt and scan, but protect never blocks the person, so an assignment that says inspect must not be softened by one that says protect.

Verdict enforcement on the device

The agent runs the verdict logic locally for speed, but the same scoring path as the cloud. Each intercepted request:
  1. Is MITM’d locally with the org root CA.
  2. Goes to /agent/scan for a verdict.
  3. Is enforced according to the verdict:
    • allow, forwarded to the upstream provider untouched.
    • redact, PII spans replaced with category markers (<EMAIL>, <API_KEY>, …) before forwarding.
    • block, returned to the calling app as a provider‑shaped error so the source application surfaces a refusal.
Observe‑only mode (enforce=false) records every verdict but never blocks. Useful when piloting a tighter threshold on a new App.

Backend endpoints (agent ↔ cloud)

The agent uses a small, dedicated set of endpoints under /api/runtime-security/agent/. Same workspace, same scanners, same event store as in‑app Runtime Security. All of these authenticate with the per-device token, sent as X-Blindsight-Device-Token. They are not for dashboard clients. These endpoints share Apps, thresholds, and the event log with /scan/input, /scan/output, and the proxy routes. Dashboards do not distinguish DLP events from SDK events except via the source attribute on the event row.

Event source

Events from the DLP agent carry:
  • source = "agent".
  • device_id = "<uuid>" referencing the row in DLP → Endpoints.
  • user_id = "<directory_user>" once identity is bound.
  • host = "api.openai.com" (or whatever was intercepted).
  • The usual verdict, injection, pii, redacted_text, blocked_reason fields.
Filter on source=agent in Observability to slice DLP traffic separately.

Direction and attachment on the event row

Every event says which way it was going, and, when it was a file, what happened to that file.
The direction query parameter on GET /api/runtime-security/events accepts input, output, and tool_call only. mcp_verify rows are returned in unfiltered listings but cannot be selected with that filter.
The attachment object: handling is the field to read for “what happened to this file”:
This used to be invisible. The agent reported the outcome under a key the console never read, so an uploaded file’s fate simply did not appear on the event row. Agents older than 1.0.24 do not populate attachment.

Device-scoped rules

A person can carry detection rules that apply to their machine alone, added from the desktop app’s Rules tab. The workspace’s own rules are listed alongside them, read-only. Body for PUT:
A device may hold up to 50 rules. The 51st returns 422.

How device rules merge with the workspace’s

Workspace rules are laid down first, then the device’s rules are merged by name on top. A new name adds a rule for that machine only. An existing name replaces it, and enabled: false switches it off, on that machine only.
A personal rule cannot switch the company’s detection off by default. Before a device rule is allowed to shadow a workspace rule, or one of the agent’s built-in detectors, the server checks that the person holds dlp.rules.override_workspace. Without it the device rule is dropped and the workspace rule ships instead. Only admin holds that permission by default, and every use is audited.
The check is made from live state on every read, never from a flag stored when the rule was written, and it requires all of:
  • the device belongs to that workspace,
  • its identity is bound, which only the SSO device-code flow sets,
  • it is attached to a user, and that account is active,
  • that user currently holds dlp.rules.override_workspace.
The built-in detector names a device rule can collide with are email_address, ipv4_address, ipv6_address, us_ssn, phone_us, credit_card, iban, github_pat, aws_access_key, anthropic_key, openai_key, jwt_token, api_key_label, and password_assignment.
The collision check deliberately ignores enabled. A rule saved as enabled with a pattern that matches nothing removes a detector just as thoroughly as switching it off, so the gate is on the name, not the flag.
Admins can list device rules across the whole fleet with GET /api/custom-rules?scope=device (needs dlp.view or dlp.manage) and delete one with dlp.manage. Authoring a device rule from the console is not offered: they belong to the device.

Keeping prompts on the machine

Injection scoring is the one reason prompt text leaves a device at all. Personal data is matched and redacted on the endpoint, and only what is left is sent to be scored. A workspace that will not have prompts leave its people’s computers can switch that scoring off.
Response: {"injection_detection": false}. Sending no key at all is a no-op that returns the current state. This is a workspace floor no named policy can override, because the permission that authors policies is a different and wider one.
It buys privacy with detection. Those devices stop detecting injection and jailbreak attempts entirely. dlp.injection.configure is held by admin only, is never implied by an older umbrella permission, and every change is audited at high severity.
With it off:
  • Host rules are still enforced first, so a block destination is still refused. Banning a destination needs the hostname, never the prompt.
  • Everything else is recorded with scan_status = "local_only" and no text at all. The text is dropped on the server rather than trusted to be absent, so an older agent that still sends the words cannot cause them to be stored.
  • An unscored prompt is filed as not scanned, never as a clean pass, so the console cannot show a green result for something nobody looked at.
  • A device still running the older policy after you switch scoring back on is recorded the same way, rather than scanned as an empty string and filed as an inspected allow.

Editing policy safely

Policy changes propagate to every agent within ~30 seconds. To roll out a tightening change safely:
1

Note the current policy version

The DLP policy page shows the active version number. Bookmark it in case you need to roll back.
2

Apply the change to a pilot App

Clone the App, apply the change to the clone, point a pilot device group at the cloned App via DLP policy → App attribution.
3

Watch drift

Use drift on the cloned App to see what shifts. PSI > 0.25 on verdict mix is your canonical “something just changed” signal.
4

Promote to the full fleet

Apply the change to the production App and push policy from DLP → Endpoints for an immediate refresh, or wait the cache TTL.
A change reaches a browser or tool that is already open. Nothing has to be restarted for a new rule to take effect: the agent reloads its scope in place and closes the live connections the change affects, so the next request is decided by the new rule.The exception is a connection the agent cannot close, a flow held over IPv6, which has no close API, or one whose close the operating system refused. When that happens the app names the one program still holding it and offers to restart just that program. It is the residue, not the normal path.
Removing a hostname from ai_hosts stops the agent from MITMing it. Existing connections complete; new requests go straight to the upstream provider untouched. There’s no grace period, confirm you’ve moved that traffic to a different App or that you really want it unscanned.

Common workflows

  1. DLP policy → AI hosts → Add. Enter the provider’s API hostname.
  2. Pick which App owns the traffic.
  3. Toggle enforce=true once you’re confident.
  1. DLP policy → Exclude hosts → Add. Add the hostname.
  2. The agent passes through it without MITM. Useful for sites that pin certs or are otherwise sensitive to inspection.
  1. Clone the production App into staging_<original>.
  2. Flip every host rule to enforce=false on the clone.
  3. Move pilot devices to the clone for a week. The verdict log fills up without breaking anyone’s workflow.
  4. Review the verdict mix before flipping enforce=true on the production App.