Tag policies
Tag policies are operator-defined rules that apply to agents based on the labels they wear. They let you treat a CI runner differently from a production server, or a privileged admin workstation differently from a developer laptop — without changing how you query the fleet.
Why it exists
A fleet is not homogeneous. A production database server should probably have shorter pathfinder explorations and stricter path restrictions than a dev laptop. An ephemeral CI runner should never be the source of hive mind leads — its test fixtures would generate noise. A contractor endpoint might need findings routed to a different webhook subscription than internal hosts.
Without tag policies, every agent behaves identically. That works at small scale, but once you have more than a handful of machines with meaningfully different roles, you need a way to express those differences without hard-coding them per-agent.
Tag policies are that mechanism. You define a policy per label, agents wear labels at install time via --tags, and the brain merges every applicable policy for an agent whenever it does something involving that agent.
How it works
Labels and install: When you install the agent, you pass one or more labels with --tags prod,linux-server. Those labels are sent to the brain on every heartbeat. The brain’s heartbeat handler records them. If you update the --tags flag and restart the agent, the labels update on the next heartbeat — console edits are overwritten.
Policy merge: The brain resolves all tag policies that apply to an agent — one per label — and merges them into an EffectivePolicy. Conflict resolution rules:
- Boolean denials win. If any policy sets
disable_outbound_leads: true, it’s true for the agent regardless of other policies. - Allowlists accumulate. Commands in
extra_allowedfrom any policy are granted. - Numeric floors take the max. If two policies set
severity_floor, the higher severity wins. - Numeric caps take the min.
max_pathfinder_turnsacross multiple policies uses the smallest value. - Severity floors take the highest severity. The most restrictive floor wins.
- System prompt fragments concatenate in tag-name order, deduplicated.
- Single-value fields (
force_depth,force_mode) take the first non-null value in tag-name order. A conflict is logged.
Enforcement: The effective policy is applied at multiple points in the pipeline — wherever the agent is involved. See the internal enforcement points reference for the full list.
Category overview:
| Category | Fields | What it controls |
|---|---|---|
| Lifecycle | auto_expire_after_idle_hours, auto_expire_after_N_runs, pin | When agents self-expire |
| Effort | force_depth, max_pathfinder_turns, force_mode | Investigation depth and pathfinder budget |
| Catalog | extra_allowed, extra_denied | Per-agent command allowlist overrides |
| Reasoning | extra_system_prompt | Context injected into the pathfinder prompt |
| Severity bias | severity_floor, severity_bump | Floor and bump for findings from this agent |
| Privacy | skip_paths, redact_user_paths | Paths to avoid and user-path redaction |
| Lead control | disable_outbound_leads | Whether this agent can source hive mind leads |
| Budget | max_investigations_per_day, maintenance_window | Rate limits and scheduling windows |
| Output routing | route_findings_to_webhook, tag_findings_with, default_environment_class | Finding metadata and webhook routing |
When you’d touch it
You set up tag policies in Console → Settings under the Tag policies section. The typical setup flow is:
- Decide which labels your fleet will use (
prod,ci-runner,dev,cloud-agent, etc.). - Create a tag policy for each label with the appropriate restrictions.
- Reinstall or update agents with
--tagsto carry the right labels.
If you’re scaling beyond 50 agents, set up tag policies before you do. The complexity of managing per-agent rules grows quadratically; label-based policies are the right abstraction once you have meaningful host segmentation.
Every policy field
| Field | Type | Optional | Description |
|---|---|---|---|
description | string | yes | Human-readable; rendered in the Settings editor. |
auto_expire_after_idle_hours | number | yes | Idle agents wearing this tag get auto-expired after this many hours. |
auto_expire_after_N_runs | number | yes | Agents wearing this tag get auto-expired after participating in N runs. |
pin | boolean | yes | When true, this agent is exempt from auto-expire regardless of other tags. |
force_depth | "quick" | "standard" | "deep" | yes | Override the request's depth for any investigation involving this agent. |
max_pathfinder_turns | number | yes | Cap pathfinder iterations on this agent. |
force_mode | "auto" | "cached" | "live" | yes | Override the request's mode (always-live skips cached). |
extra_allowed | string[] | yes | Commands appended to the agent's effective allowlist for any plan. |
extra_denied | string[] | yes | Commands appended to the deny list — wins over allow. |
extra_system_prompt | string | yes | Appended to the pathfinder system prompt as host-context. |
severity_floor | Severity | yes | Findings on this agent are bumped to at least this level. |
severity_bump | number | yes | Findings on this agent are bumped up by N levels (clamped to critical). |
skip_paths | string[] | yes | Path globs the plan compiler will refuse to walk on this agent. |
redact_user_paths | boolean | yes | Replace user-home paths in stdout with `~` before any LLM sees them. |
disable_outbound_leads | boolean | yes | Findings from this agent never propagate to the rest of the fleet. |
max_investigations_per_day | number | yes | Decline new investigations on this agent past this daily count. |
maintenance_window | string | yes | Cron expression — investigations on this agent are queued outside the window. |
route_findings_to_webhook | string | yes | Findings on this agent are routed to a specific webhook subscription regardless of severity filter. |
tag_findings_with | Record<string, string> | yes | Free-form metadata stamped onto every finding from this agent. |
default_environment_class | string | yes | environment_class to apply if not already tagged via the kv table. |