Red lines (prohibitions)¶
A Charter rule decides an action in its context: it can allow, hold for a person or refuse, and what it decides can be escalated, lifted by a break-glass override, widened by an authority request or narrowed by a mission. A red line is different in kind. It names something that is never on the table for an agent, whatever the context, whoever asks, and whatever else the agent has been granted.
"Never search the web." "Never touch the customer database." "Never send anything to a personal mailbox." "Never move secret data." Written once, in plain words, and enforced three layers deep.
What a red line covers¶
| Kind | Pattern | Example |
|---|---|---|
capability |
an action family or glob | web_search, transfer_*, delete_* |
resource |
a resource class glob | db:customers, tool:crm*, bucket:exports |
destination |
external, model, or a domain glob |
external, *.gmail.com |
data_class |
a classification; that class and above | SECRET |
A capability pattern is read generously: web_search covers web_search_news and web_search.images, and a bare family such as search covers search_web. Over-prohibiting is the safe side of a red line.
A red line applies to the whole organisation, to one department (department:<id>) or to one agent (agent:<agent_id>). An agent is bound by all three layers that name it.
Writing one in plain words¶
In the Red lines view you type what never happens, in your own words: "never search the web", "the procurement agents never touch the customer database", "nothing secret leaves the organisation". The model reads the sentence against the workspace's own vocabulary (observed action types, registered tools, MCP servers, labelled sources, departments and agents) and proposes one or more red lines, each with its kind, its pattern and a short restatement. Every proposal goes through the same checks a hand-written line does, so an invalid one is set aside and said so. You review the proposals, adjust a pattern if you want, untick any you do not mean, and sign. Nothing exists until you sign. The pattern fields are still there for anyone who prefers to write them directly, and they are what the form falls back to when no model can be reached.
client.compile_red_line("never search the web")["lines"]
# [{"kind": "capability", "pattern": "web_search", "text": "Never search the web", "scope": "organisation", "rationale": "…"}]
How it is enforced¶
- The tool disappears. A prohibited tool is removed from what the agent is offered: the SDK filters a framework's tool list, the MCP gateway strips it from
tools/list, and the agent's public Agent Card does not advertise it. The agent cannot try what it cannot see. - The choke point refuses, unconditionally. At the enforcement point the red line is checked before sessions, boundaries, rules, the mission and break-glass, and the refusal is returned at once with
decision_path: prohibited. No escalation is created, so no person is asked. The break-glass override acts later in the pipeline and therefore never reaches a prohibited action. An authority request, a mission, a warrant or a negotiation cannot include it. Pre-flight refuses the step the same way, so an agent that plans properly never reaches the attempt. - It is subtracted from every authority in the model. When the Authority Slice is resolved, every authority the agent holds has the prohibited families removed and the patterns attached as
never. A warrant is issued without the family and carriesneverin its signed body, so the offline check refuses the action as well. A negotiation's intersection excludes both parties' red lines. The passport and the Agent Card say what the agent can never do.
The SDK's AgentSide also refuses locally, before any network call, and its system_prompt_fragment() adds the red lines to the agent's own instructions as "You can never: …", so the model is told, the tool list is told, and the enforcement point is told. Three different mechanisms have to fail at once for a red line to be crossed.
Governance of the list¶
Adding a red line is one person's act. It is signed, sealed in the Provenance Vault and included in the Charter hash, so every receipt proves which prohibitions were in force when a decision was taken. The signed Charter diff records it as a tightening.
Removing one is the dangerous act, so it takes two people and time:
- A first person requests the removal. The line keeps applying.
- A cooling period runs (
XYBERN_REDLINE_COOLING_HOURS, one hour by default). - A different person confirms. The same person cannot ask and confirm. Only then is the line removed, sealed and the Charter re-sealed; the diff records a loosening.
A pending request can be cancelled by anyone with admin rights, and the line was in force throughout.
Proving it holds¶
Attack My System probes every red line against every agent it applies to through pre-flight and reports a critical finding if one would not be refused. The Red lines view has the same self-test ("Prove they hold") and a dry-run tester: pick an agent, type an action and optionally a resource or destination, and see whether it crosses a line. Nothing is executed and nothing is recorded.
Where it shows¶
- Red lines view under Authority: the list, the plain-language add form, the two-person removal flow, the tester and the self-test.
- Passports: a "never N" pill on each agent's posture, and the
red_lineslist in the signed passport body. - Agent Cards:
xybern.neverand a skills list without the prohibited families. - Decision records: a Red line row on any decision refused with
decision_path: prohibited. - Authority language (XAL): a
red_linessection. A document adds red lines; it never removes one, because removal is two people and a cooling period.
red_lines:
- {key: no_money_movement, kind: capability, pattern: "transfer_*", text: Never move money}
- {key: no_customer_db, kind: resource, pattern: "db:customers", text: Never touch the customer database, scope: "department:Procurement"}
API¶
GET /v1/enforce/red-lines the list; ?agent_id= gives what applies to one agent (verify)
POST /v1/enforce/red-lines {kind, pattern, text, scope?, reason?} (approvals)
POST /v1/enforce/red-lines/<id>/remove first person asks; {reason?} (approvals)
POST /v1/enforce/red-lines/<id>/confirm-removal second person, a different key, after cooling (approvals)
POST /v1/enforce/red-lines/<id>/cancel-removal (approvals)
GET /v1/enforce/red-lines/check?agent_id=&action_type=&resource=&to= dry run, records nothing (verify)
POST /v1/enforce/red-lines/self-test {agent_ids?} (verify)
A refused decision carries:
{"decision": "block", "decision_path": "prohibited",
"policies_triggered": [{"policy_id": "__red_line", "name": "Red line: Never search the web", "decision": "block",
"red_line": {"line_id": "rl_…", "kind": "capability", "pattern": "web_search", "text": "Never search the web",
"scope": "organisation", "detail": "'web_search_news' is covered by the red line 'web_search'"}}],
"reasoning": "Prohibited by a red line (Never search the web): … A red line is never escalated and no override lifts it."}
SDK (2.26.1)¶
from xybern import XybernClient
from xybern.agentside import AgentSide, ActionRefused
client = XybernClient(api_key="…")
side = AgentSide(client, agent_id="researcher")
side.red_lines() # [{"kind": "capability", "pattern": "web_search", "text": "Never search the web", "scope": "organisation"}]
tools = side.allowed_tools(tools) # the web_search tool is gone before the model sees it
prompt = side.system_prompt_fragment() # "… You can never: Never search the web. These are red lines …"
try:
side.guarded("web_search_news", lambda: search("…"))
except ActionRefused as e:
e.decision["decision_path"] # "prohibited", raised locally, no call was made
client.add_red_line("resource", "db:customers", "Never touch the customer database") # approvals scope
client.request_red_line_removal(line_id, reason="…") # first person
client.confirm_red_line_removal(line_id) # a different key, after cooling
client.red_lines_self_test()["holds"]
In xybern.auto enforce mode a prohibited action is refused before the round trip, with the same PolicyBlocked the agent already handles, and the trace says "red line: …; never escalated, nothing lifts it".
Red lines and the rest of the model¶
A red line is a Constraint on every Authority at resolution time, which is why it needs no rule of its own and why nothing downstream can see the prohibited capability as granted. It sits beside, not inside, the Charter: a Charter rule is reasoning about an action in context, a red line is the absence of authority. Both are in the Charter hash, so a receipt proves both.