CydraLabs

Documentation

Policy language

CydraGateway policies are structured, versioned rule documents evaluated deterministically for every agent action. This page covers the rule format, the decision input, how decisions combine, and how to test changes before they go live.

Policies and versions

  • A policy has a key, a name, a description and a list of versions. Its rules are stored as data; you never deploy code to change a decision.
  • A version is either draft, published or superseded. It records the author, a change note and a content hash. Drafts never affect live decisions.
  • Publishing is four-eyes: the publisher must be a different person from the version's author. Publishing makes the version active and supersedes the previous one. To roll back, create a new draft with the earlier rules and publish it; history is never rewritten.
  • Changes use optimistic concurrency: creating a version, publishing and changing status need If-Match: <policy version> (missing: 428, stale: 409).
  • Every active policy contributes its published rules to one rule set; they are evaluated together. The baseline pack cannot be deactivated, and containment rules are managed through containment actions, not edited directly.

Rule documents

A rule
{
  "id": "FIN-001",
  "description": "Payments of £1,000 or more need approval",
  "effect": "require_approval",
  "priority": 100,
  "reason_code": "PAYMENT_ABOVE_THRESHOLD",
  "conditions": [
    {"field": "tool.privilege_class", "op": "eq",  "value": "financial"},
    {"field": "action.amount",        "op": "gte", "value": 1000}
  ],
  "obligations": {"approvals_required": 1},
  "enabled": true
}
Rule fields
FieldRequiredMeaning
idYesUnique within the policy. Letters, digits, - and _ (up to 64).
effectYesallow, deny or require_approval.
reason_codeYesUPPER_SNAKE_CASE code reported with the decision and in evidence, for example SECRET_DETECTED.
conditionsYes1 to 20 conditions. All must hold for the rule to match (logical AND).
descriptionNoHuman-readable explanation (up to 500 characters).
obligationsNoFor require_approval: approvals_required, 1 to 5 distinct approvers (default 1).
enabledNoDefault true. Disabled rules are ignored.
priorityNoInformational. Decisions combine by effect, not by priority.

A condition is {"field", "op", "value"}: field is a dotted path into the decision input (for example tool.privilege_class). For an or, write two rules with the same effect.

Operators

Condition operators
OperatorHolds whenIf the field is missing
eqThe field equals the value.Does not hold
neqThe field does not equal the value.Holds
inThe field equals one of the values (value must be a list).Does not hold
not_inThe field equals none of the values (value must be a list).Holds
gt, gte, lt, lteNumeric comparison. Both sides must be numbers.Does not hold
existsThe field is present and not null.Does not hold
not_existsThe field is absent or null.Holds
containsThe field is a list containing the value.Does not hold
prefixThe field is a string starting with the value.Does not hold

Decision input

The gateway builds the decision input from the authenticated agent, the registry, inspection and the request. It never takes these values from the agent's own claims. The rule builder lists these fields:

Decision input fields
FieldValues
agent.statusactive, suspended, revoked
agent.environmentdevelopment, staging, production
agent.risk_score / agent.risk_band0–100 / low, moderate, high, critical, or unknown until the agent is scored (last computed score)
agent.owner_attestation_currenttrue when an owner has attested recently
agent.criticalitylow, medium, high, critical
agent.idThe agent's ID
identity.auth_strengthStrength of the workload identity's authentication
delegation.present / delegation.in_scope / delegation.subjectWhether the agent acts for a user, whether the tool is within that user's consented scopes, and the user
tool.keyThe tool key, for example payments.transfer.create
tool.privilege_classread, write, destructive, financial, admin
tool.approval_classnone, single, dual
tool.mcp_trust_stateapproved, unknown, unsigned, quarantined (not_applicable outside MCP)
tool.target_typemodel, mcp_tool, api
action.operation / action.targetOperation and target from the request
action.environmentEnvironment of the action (defaults to the agent's)
action.amountNumeric amount parameter, when present
action.channelgateway (agent) or console (testing console)
data.classificationpublic, internal, confidential, personal, regulated, restricted
data.contains_personal_datatrue when the target data resource holds personal data
model.approved / model.approved_for_dataWhether the model is approved, and approved for this data classification
inspection.secrets / inspection.prompt_injection / inspection.piiResults of content inspection on parameters and justification
binding.granted / binding.delegated / binding.constraints_satisfiedWhether a permission covers this tool and operation, whether it is delegated, and whether constraints such as max_amount hold
rate.exceededtrue when the agent exceeded its per-tool rate (60 a minute by default)

Decision precedence

Every rule from every active policy is evaluated. The decision is then the earliest of these that applies:

  1. Platform invariants deny. These cannot be overridden by any rule: agent not active (AGENT_NOT_ACTIVE), gateway access disabled (GATEWAY_ACCESS_DISABLED), unknown tool (UNKNOWN_TOOL), blocked tool (TOOL_BLOCKED) and identity not active (IDENTITY_NOT_ACTIVE).
  2. Any matching deny rule denies. Deny outranks approval and allow.
  3. Any matching approval rule requires approval, unless the request carries a valid approval token for this exact request. The number of approvers is the highest approvals_required among the matching approval rules.
  4. A matching allow rule, or a verified approval, allows. With a verified approval the reasons also include APPROVAL_VERIFIED.
  5. Nothing matched: deny with NO_MATCHING_ALLOW. The platform is default-deny.

The decision reports its reason codes (from the deciding rules), the IDs of every matching rule and of the deciding rules, the obligations, and the engine used. All of it is recorded in the evidence chain. If the policy engine fails, the decision fails closed (PDP_UNAVAILABLE_FAIL_CLOSED).

Baseline pack

Every organisation starts with the CydraGateway baseline pack. It can be changed by publishing a new version (four-eyes) but not deactivated.

Baseline pack rules
RuleEffectReason codePurpose
POL-001denyAGENT_NOT_REGISTEREDUnregistered, inactive or wrong-organisation agent
POL-002require_approvalPRODUCTION_HIGH_IMPACTProduction write, destructive, financial or admin tool
POL-003denySECRET_DETECTEDHigh-confidence credential pattern in outbound parameters
POL-004denyPROMPT_INJECTIONInstruction-override or exfiltration indicator
POL-005denySENSITIVE_DATA_TO_UNAPPROVED_MODELRegulated or restricted data to a model not approved for it
POL-006denyUNTRUSTED_MCP_PRIVILEGED_TOOLPrivileged tool on an MCP server of unknown, unsigned or quarantined provenance
POL-007require_approval (2)CRITICAL_AGENT_RISKCritical Agent Risk Score (75 or more) and a non-read action
POL-008denyRATE_LIMIT_EXCEEDEDAgent exceeded its tool request rate
POL-009require_approvalOWNER_ATTESTATION_EXPIREDProduction agent with an expired owner attestation, high-impact action
POL-010denyAGENT_SUSPENDEDSuspended or revoked agent
GRANT-001denyPERMISSION_NOT_GRANTEDNo permission for this tool and operation
GRANT-002denyDELEGATION_OUT_OF_SCOPEDelegated tool used outside the user's consented scope
GRANT-003denyPERMISSION_CONSTRAINT_EXCEEDEDParameters exceed a permission constraint, such as a maximum amount
ALLOW-001allowPERMISSION_GRANTEDExplicitly granted tool operation

Examples

Dual approval for large payments in production

{
  "id": "FIN-002",
  "effect": "require_approval",
  "reason_code": "HIGH_VALUE_PAYMENT",
  "conditions": [
    {"field": "tool.privilege_class", "op": "eq",  "value": "financial"},
    {"field": "action.environment",   "op": "eq",  "value": "production"},
    {"field": "action.amount",        "op": "gte", "value": 25000}
  ],
  "obligations": {"approvals_required": 2}
}

No personal data to email tools

{
  "id": "DLP-001",
  "effect": "deny",
  "reason_code": "PERSONAL_DATA_TO_EMAIL",
  "conditions": [
    {"field": "tool.key",       "op": "prefix", "value": "email."},
    {"field": "inspection.pii", "op": "eq",     "value": true}
  ]
}

Freeze destructive actions for one high-risk agent

{
  "id": "OPS-001",
  "effect": "deny",
  "reason_code": "CHANGE_FREEZE",
  "conditions": [
    {"field": "agent.risk_band",      "op": "in", "value": ["high", "critical"]},
    {"field": "tool.privilege_class", "op": "eq", "value": "destructive"}
  ]
}

Testing

  • Test this draft on a policy page runs a decision with the draft rules added to your active rule set (POST /api/v1/policies/simulate with draft_rules). Nothing is stored or executed.
  • The Gateway console simulates or submits an action as one of your agents against the active rules, with the full decision, inspection results and timeline.
  • Saving a version validates it: unique rule IDs, a known effect and operator, a reason code, at least one condition, and list values for in and not_in.

Golden decision cases

Decisions are made by one of two evaluators with identical semantics: Open Policy Agent (Rego) and an embedded evaluator. Both run against the same set of golden decision cases in every build, so they cannot drift apart. A selection:

Golden decision cases (selection)
CaseExpected decisionReason codes
Granted read in productionallowPERMISSION_GRANTED
No rules at alldenyNO_MATCHING_ALLOW
Production financial toolrequire_approval (1)PRODUCTION_HIGH_IMPACT
…the same with a verified approvalallowAPPROVAL_VERIFIED, PERMISSION_GRANTED, PRODUCTION_HIGH_IMPACT
Secret in parameters, even with approvaldenySECRET_DETECTED
Suspended agent, even with no rulesdenyAGENT_NOT_ACTIVE
Unknown tooldenyUNKNOWN_TOOL
Privileged tool on an unknown MCP serverdenyUNTRUSTED_MCP_PRIVILEGED_TOOL
Read tool on an unknown MCP serverallowPERMISSION_GRANTED
Critical risk score and production financial toolrequire_approval (2)CRITICAL_AGENT_RISK, PRODUCTION_HIGH_IMPACT
Missing numeric field with gteallow (the rule does not match)PERMISSION_GRANTED
Boolean compared with a numberdeny (no match)NO_MATCHING_ALLOW
Disabled ruleignoredPERMISSION_GRANTED

See the architecture for where the decision sits in the ten-step workflow, and the quick start to write and test a rule of your own.

Applies to the CydraLabs proof-of-concept platform. Last updated 4 October 2026. Questions or corrections: contact us.