Skip to content

policies.json defines runtime guard policies for your Swytchcode project.

Unlike tooling.json, which controls what can execute, policies.json controls when a tool is allowed to execute based on the request being made.

Every policy is evaluated before execution, allowing you to block requests that violate your organization’s rules.

The file lives at:

.swytchcode/integrations/policies.json

How it works

Before executing any method, Swytchcode checks whether a matching policy exists. If a policy condition evaluates to true, the configured action is applied immediately.


Managing Policies

Swytchcode provides CLI commands for managing policies.

Add a policy

Terminal window
swy policy add

Creates a new policy interactively.


List policies

Terminal window
swy policy list

Displays every configured policy.


Remove a policy

Terminal window
swy policy remove <policy-id>

Deletes a policy by its ID.


Validate policies

Terminal window
swy policy validate

Validation checks for:

  • Unknown operators
  • Missing required fields
  • Duplicate IDs
  • Invalid action types
  • Empty targets
  • Invalid value types
  • Dotted field paths
  • Malformed nested conditions

Validation errors are reported with human-readable messages before execution.


Review past violations

swy policy only manages the rules - it doesn’t show you what’s happened historically. Every time a policy blocks a request, Swytchcode logs the violation to a local, read-only history. To review it:

Terminal window
swy audit policy # recent policy-violation entries
swy audit policy -n 20 # last 20 entries
swy audit policy --info <id> # full detail for one violation (id looks like pol_...)

This is useful when a policy blocks something unexpectedly and you need to see exactly which field/value tripped the rule, without touching policies.json itself. See the Command Reference for the full swy audit surface.


Fail-Closed Behavior

policies.json follows a fail-closed validation model.

SituationBehavior
File does not existNo policies are applied. Execution continues normally.
File exists and is validPolicies are evaluated before execution.
File exists but is malformedExecution stops with a validation error.

This ensures invalid policy definitions never silently bypass security checks.


File Structure

A minimal policy file looks like this:

{
"defaults": {
"on_violation": "fail",
"evaluation": "pre_execution"
},
"policies": [
{
"id": "star-repo-approval",
"target": [
"github.repo.star"
],
"when": {
"field": "name",
"operator": "exists"
},
"action": {
"type": "POLICY_BLOCKED",
"message": "Starring repositories is blocked."
}
}
]
}

The file consists of two sections:

  • defaults
  • policies

defaults

The defaults object defines how policy evaluation behaves.

{
"defaults": {
"on_violation": "fail",
"evaluation": "pre_execution"
}
}

on_violation

Determines what happens when a policy condition matches.

{
"on_violation": "fail"
}

Currently, only one value is supported.

ValueDescription
failImmediately stops execution.

Any other value fails validation.


evaluation

Specifies when policies are evaluated.

{
"evaluation": "pre_execution"
}

Supported value:

ValueDescription
pre_executionEvaluate policies before any API request is made.

Future versions may introduce additional evaluation stages.


Policy Objects

Every rule inside the policies array represents a single guard.

Example:

{
"id": "block-large-payments",
"target": [
"stripe.create_payment"
],
"when": {
"field": "amount",
"operator": ">",
"value": 100000
},
"action": {
"type": "POLICY_BLOCKED",
"message": "Payments above the allowed limit are blocked."
}
}

Each policy contains four required fields.


id

A unique identifier for the policy.

{
"id": "block-large-payments"
}

If another policy uses the same ID, it replaces the existing policy.


target

Defines which methods or workflows the policy protects.

{
"target": [
"stripe.create_payment"
]
}

A policy only runs when one of these canonical IDs is executed.

Multiple tools can be protected.

{
"target": [
"stripe.create_payment",
"stripe.refund_payment"
]
}

when

Defines the condition that triggers the policy.

{
"when": {
"field": "amount",
"operator": ">",
"value": 100000
}
}

If this condition evaluates to true, Swytchcode executes the configured action.

Conditions are covered in detail below.


action

Defines what happens when a condition matches.

{
"action": {
"type": "POLICY_BLOCKED",
"message": "Payments above the limit are blocked."
}
}

Both type and message are required.


Action Types

Supported action types are:

ActionDescription
AUTH_FAILEDAuthentication failed.
POLICY_BLOCKEDRequest blocked by policy.

Example:

{
"action": {
"type": "POLICY_BLOCKED",
"message": "Too many requests."
}
}

When a policy blocks execution:

  • the request is never sent
  • execution stops immediately
  • Swytchcode exits with code 4

Conditions

Conditions determine when a policy should apply.

There are two types:

  • Leaf conditions
  • Group conditions

Leaf Conditions

Leaf conditions compare a single request field.

Example:

{
"field": "amount",
"operator": ">",
"value": 100000
}

Swytchcode evaluates the resolved request arguments before execution.


Group Conditions

Group conditions combine multiple rules.

They use one of three logical operators.

OperatorDescription
allEvery condition must match (AND).
anyAt least one condition must match (OR).
notInverts a condition (NOT).

Example:

{
"operator": "all",
"conditions": [
{
"field": "currency",
"operator": "==",
"value": "usd"
},
{
"field": "amount",
"operator": ">",
"value": 5000
}
]
}

Execution is blocked only if both conditions evaluate to true.


Comparison Operators

Equality & Ordering

Operator
==
!=
>
>=
<
<=

These operators require scalar values.

Example:

{
"field": "amount",
"operator": ">",
"value": 1000
}

Membership

Operator
in
not_in

The value must be an array.

{
"field": "currency",
"operator": "in",
"value": [
"usd",
"eur"
]
}

Substring

Operator
contains
not_contains
{
"field": "email",
"operator": "contains",
"value": "@company.com"
}

String Matching

Operator
starts_with
ends_with
matches

Example:

{
"field": "branch",
"operator": "starts_with",
"value": "release/"
}

matches accepts a regular expression up to 512 characters.


Presence

These operators do not require a value.

Operator
exists
not_exists
empty
not_empty

Example:

{
"field": "api_key",
"operator": "exists"
}

Time Comparison

Supported operators:

Operator
before
after

Example:

{
"field": "expires_at",
"operator": "before",
"value": "2026-12-31T00:00:00Z"
}

Time Windows

Supported operators:

Operator
between
outside

The value must contain exactly two timestamps.

{
"field": "created_at",
"operator": "between",
"value": [
"2026-01-01T00:00:00Z",
"2026-12-31T23:59:59Z"
]
}

Nested Conditions

Complex policies can combine multiple logical operators.

Example:

{
"when": {
"operator": "all",
"conditions": [
{
"field": "amount",
"operator": ">",
"value": 100000
},
{
"field": "currency",
"operator": "in",
"value": [
"usd",
"eur"
]
},
{
"operator": "not",
"conditions": [
{
"field": "test_mode",
"operator": "exists"
}
]
}
]
}
}

This policy only matches when:

  1. Amount is greater than 100000
  2. Currency is either usd or eur
  3. test_mode is not present

Best Practices

  • Keep policies focused on a single responsibility.
  • Use descriptive policy IDs.
  • Validate policies after every change.
  • Prefer multiple small policies over one complex rule.
  • Store policies in version control alongside your project.
  • Test policies in sandbox mode before deploying to production.

Now that you understand runtime guard policies, continue with: