Argument & Semantic Policies
Guardrails look at content. Policies look at behavior: what a tool call is actually about to do. Brutor has two policy engines:
| Argument policies | Semantic policies | |
|---|---|---|
| Mechanism | Deterministic analyzers (SQL parser, URL/shell/path/JSON inspection) | LLM judge evaluating a natural-language constraint |
| Latency / cost | Microseconds, free | One judge-model call per evaluated request |
| Determinism | 100% reproducible | Model judgment — use shadow mode first |
| Best for | “No writes to the sales DB”, “no requests to private IPs” | “Agents must never commit to pricing or discounts” |
Use argument policies wherever the rule can be expressed structurally. Reach for semantic policies when the rule lives in meaning, not syntax.
Argument policies
Section titled “Argument policies”An argument policy targets one argument of one tool (or all tools) on a surface, runs a deterministic analyzer over the value, and denies or warns based on rules.
Fields: name, description, surface (llm_output_tool_calls | mcp_input | skill_input), target (tool/skill name, or "*"), argument_key (which JSON argument to analyze), analyzer (sql | url | shell | path | json), rules, severity (deny | warn), enabled, group_ids (resource-group binding).
llm_output_tool_calls inspects tool calls the LLM proposes in its output (before your agent executes them); mcp_input and skill_input inspect calls arriving at the MCP/skill gateway.

Example: read-only SQL tool
Section titled “Example: read-only SQL tool”curl -X POST http://localhost:5050/v1/admin/argument-policies \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "sales-db-read-only", "description": "The sales DB tool may only run single read statements", "surface": "llm_output_tool_calls", "target": "query_sales_db", "argument_key": "sql", "analyzer": "sql", "severity": "deny", "enabled": true, "rules": [ { "deny_if": "writes", "message": "Write statements are not allowed on the sales DB" }, { "deny_if": "multi_statement", "message": "One statement per call" }, { "deny_if": "touches_any", "values": ["salaries", "employees_pii"], "message": "Restricted tables" } ], "group_ids": ["9f2c..."] }'A denied call is rejected before execution and logged with argument_policy_denied = true in the proxy logs. With severity: "warn" the call proceeds but the violation is recorded.
Rule predicates by analyzer
Section titled “Rule predicates by analyzer”Rules are {deny_if | allow_only_if, values?, message?}. Predicates marked * require values.
| Analyzer | Predicates |
|---|---|
sql |
writes, multi_statement, statement_type_in, statement_type_not_in, touches_any, touches_none_of, subquery_depth_gt* |
url |
host_in_private_range, scheme_in, scheme_not_in, host_in, host_not_in |
shell |
command_in, command_not_in, flag_present, flag_not_present |
path |
traverses_parent, absolute_required, inside_root, outside_root |
json |
schema_invalid, field_present, field_not_present |
Policies can be exported and versioned as YAML: GET /v1/admin/argument-policies/export.yaml / POST /v1/admin/argument-policies/import.yaml. Group bindings are set with PATCH /v1/admin/argument-policies/{id}/groups.
Semantic policies
Section titled “Semantic policies”A semantic policy is a natural-language constraint enforced by an LLM judge. The gateway sends the request content plus your constraint_text to a judge model and blocks or warns based on the verdict.
Fields: name, description, constraint_text (the natural-language rule), action (block | warn), mode (shadow | enforce), surfaces (any of chat_input, mcp_input, a2a_inbound, a2a_outbound, skill_input), judge_model_id (a specific model to judge with; null = tenant default), enabled, resource_group_ids.

Scope: when resource_group_ids is empty or omitted, the policy is tenant-wide; otherwise it applies only to the listed resource groups.
curl -X POST http://localhost:5050/v1/admin/semantic-policies \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "no-pricing-commitments", "description": "Customer-facing agents must never commit to pricing", "constraint_text": "The request must not ask the assistant to quote, promise, or negotiate prices, discounts, or contractual terms on behalf of the company.", "action": "block", "mode": "shadow", "surfaces": ["chat_input", "a2a_inbound"], "enabled": true, "resource_group_ids": [] }'{ "id": "smp-...", "name": "no-pricing-commitments", "action": "block", "mode": "shadow", "surfaces": ["chat_input", "a2a_inbound"], "enabled": true}Shadow → enforce rollout
Section titled “Shadow → enforce rollout”Never launch a semantic policy directly in enforce mode. The judge is a model; you want evidence of its judgment on your traffic first.
-
Create in
mode: "shadow". The judge runs on live traffic and records would-block decisions (proxy_subtype = semantic_policy_shadowin the proxy logs) — nothing is actually blocked. -
Review shadow hits in the Governance view and the proxy logs for a few days. Tighten
constraint_textuntil false positives are acceptably rare. A more capablejudge_model_idoften beats a longer constraint. -
Flip to
mode: "enforce"withPATCH /v1/admin/semantic-policies/{id} {"mode": "enforce"}. Blocks now return errors to callers and log assemantic_policy_block. -
Keep
action: "warn"as a middle ground — enforce mode, but violations only log and alert rather than block.
Choosing between the engines
Section titled “Choosing between the engines”- Rule mentions a table, host, path, flag, or field → argument policy. It’s free, instant, and never hallucinates.
- Rule mentions intent, topic, or tone (“no legal advice”, “no competitor disparagement”) → semantic policy, rolled out through shadow mode.
- Many real controls use both: an argument policy guarantees the SQL is read-only, while a semantic policy watches for the agent being talked into exfiltration-shaped requests.
Policy denials and shadow hits are first-class governance events: they appear in Mission Control → Governance, in the audit trail, and count toward compliance tagging where a profile is enabled.
