# Policy Rules

A policy defines **when a tool is allowed to execute**.

Every request made through Swytchcode is evaluated against your configured policies before an API call is made. If a policy condition matches, Swytchcode applies the configured action immediately. Response policies run once more after the call, before the agent sees the result.

Policies allow you to enforce business rules, security requirements, and operational constraints without changing your application code.

---

## How Policy Evaluation Works

Whenever a tool is executed, Swytchcode performs the following checks:

```text
Tool Execution Requested
           │
           ▼
MODIFY policies change the call (if any match)
           │
           ▼
Evaluate the other policies on the (changed) call
           │
           ▼
Any block?  ──Yes──▶ Blocked (exit code 6)
           │No
           ▼
Any approval? ──Yes──▶ Held for a person (exit code 7)
           │No
           ▼
Call is sent
           │
           ▼
Response policies: hide, cut, or withhold the response
           │
           ▼
Result returned to the agent
```

A policy only applies to the methods listed in its `target`. When several policies match, a block wins over an approval, and an approval over an `ALLOW`. With `"on_no_match": "deny"`, a call no `ALLOW` policy matches is blocked, which turns the file into an allowlist.

---

## Anatomy of a Policy

Every policy consists of four parts:

```text
Policy
│
├── Target
├── Condition
├── Action
└── Identifier
```

Each part serves a specific purpose.

| Component | Purpose | JSON field |
|-----------|---------|------------|
| **ID** | Uniquely identifies the policy. | `id` |
| **Target** | Specifies which methods the policy applies to. | `target` |
| **Condition** | Determines when the rule should trigger. | `when` |
| **Action** | Defines what happens when the condition is met. | `action` |

Put together, a policy in `.swytchcode/integrations/policies.json` looks like this:

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

If `amount` on the request exceeds `100000`, `swy exec` (and the equivalent `swytchcode_exec` MCP call) stops before any network request is made, returns exit code `6`, and returns an error naming the policy and its `message`. To hold a command until a person confirms it, use [human approval](/policies/human-approval/) (`REQUIRES_APPROVAL`) instead of a hard block.

Besides blocking, a policy can:

- **Change the call** (`MODIFY`) - for example, cap a page size instead of failing.
- **Allow it** (`ALLOW`) - with `"on_no_match": "deny"`, only allowed calls run.
- **Hide or cut the response** (`REDACT`, `TRUNCATE`) - for example, replace card numbers with `[REDACTED]` before the agent sees them.
- **Only watch** (`"mode": "monitor"`) - record matches without acting, to try a rule first.

These need a [version-2 file](/configuration/policy-json/#file-versions). See [Action Types](/configuration/policy-json/#action-types) for the full list.

---

## Choosing a Target

Policies only evaluate requests that match one of their targets. `target` is always an array of canonical IDs.

```json
{ "target": ["github.repo.star"] }
```

only evaluates requests that star GitHub repositories.

Another policy might target:

```json
{ "target": ["stripe.payment.create"] }
```

to validate payment requests.

A single policy can protect multiple methods if they share the same business rule.

```json
{
  "target": [
    "stripe.payment.create",
    "stripe.payment.refund",
    "stripe.payment.capture"
  ]
}
```

In a version-2 file, a target can be a pattern: `"stripe.*"` guards every Stripe method, and `"*"` every tool. Combined with built-in fields such as `$http_method`, one policy can cover a whole class of calls - for example, every `DELETE` in production.

---

## Writing Conditions

Conditions determine **when** a policy should apply.

A condition evaluates information from the request being executed, and - in a version-2 file - about the call itself and earlier calls.

Examples include:

- Payment amount
- Currency
- Email address
- Branch name
- Environment
- Region
- Request metadata

A simple condition might read:

> Block any payment greater than 10,000.

which is written as:

```json
{ "field": "amount", "operator": ">", "value": 10000 }
```

Another might read:

> Block requests that aren't from a company email address.

```json
{ "field": "email", "operator": "not_contains", "value": "@yourcompany.com" }
```

A version-2 file adds more to compare against:

- **Nested fields**: `customer.email`, `items[*].price`.
- **Built-in fields** that Swytchcode fills in, which an agent can't set: `$http_method`, `$env`, `$host`, `$time`, `$weekday`, `$caller`, and `$email_domains` (the domain of every address anywhere in the request), among others.
- **Lists** kept in one place: `{"$list": "blocked_domains"}`.
- **Earlier calls**: `rate` (calls per window), `sum` (e.g. daily spend), `repeat`, `called_before`, `returned_by`.
- **Sensitive data**: `contains_pii` and `contains_secret`.

```json
{ "field": "$email_domains", "operator": "in", "value": ["gmail.com", "yahoo.com"], "ignore_case": true }
```

Policies should describe business intent rather than implementation details. The full set of supported operators - equality/ordering (`==`, `!=`, `>`, `>=`, `<`, `<=`), membership (`in`, `not_in`), substring (`contains`, `not_contains`), string matching (`starts_with`, `ends_with`, `matches`), presence (`exists`, `not_exists`, `empty`, `not_empty`), and time comparisons (`before`, `after`, `between`, `outside`) - is documented in the [policies.json reference](/configuration/policy-json/), with the version-2 [built-in fields](/configuration/policy-json/#built-in-fields), [condition options](/configuration/policy-json/#condition-options), and [conditions on earlier calls](/configuration/policy-json/#conditions-on-earlier-calls).

---

## Combining Conditions

Many production rules require more than one condition.

Swytchcode lets you combine leaf conditions (`field`/`operator`/`value`) into a group condition using `operator: "all" | "any" | "not"` plus a `conditions` array.

**`all` (AND)** - every condition must match:

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

---

**`any` (OR)** - at least one condition must match:

```json
{
  "operator": "any",
  "conditions": [
    { "field": "role", "operator": "==", "value": "admin" },
    { "field": "role", "operator": "==", "value": "support" }
  ]
}
```

---

**`not`** - inverts the nested condition:

```json
{
  "operator": "not",
  "conditions": [
    { "field": "test_mode", "operator": "exists" }
  ]
}
```

Groups can nest inside groups, so you can build rules like "amount over 10,000 AND currency is USD or EUR AND NOT test mode" as a single `when` block. See [Group Conditions](/configuration/policy-json/#group-conditions) in the policies.json reference for a full worked example.

---

## Common Policy Patterns

The most effective policies are usually simple. [Policy recipes](/policies/recipes/) has a ready-to-use policy for each of the patterns below.

### Spending Limits

Prevent expensive operations.

Examples:

- Payments above a threshold
- Refund limits
- Credit issuance limits

---

### Production Protection

Prevent accidental changes to production systems.

Examples:

- Block delete operations
- Prevent destructive workflows
- Disable infrastructure changes

---

### Organization Rules

Restrict operations based on company policies.

Examples:

- Company email domains only
- Approved GitHub organizations
- Approved cloud projects

---

### Environment Restrictions

Different environments often require different rules.

For example:

Development:

- Relaxed limits
- Test data
- Sandbox providers

Production:

- Strict validation
- Protected resources
- Higher security

---

### Time-Based Rules

Restrict execution during specific time windows.

Examples:

- Business hours only
- Maintenance windows
- Scheduled deployments

---

## Designing Good Policies

When writing policies, follow these principles.

### Keep policies focused

Instead of one large policy:

❌

```text
Everything Policy
```

Prefer:

✅

```text
Payment Limit

Repository Protection

Production Restriction

Email Validation
```

Smaller policies are easier to review and maintain.

---

### Write descriptive IDs

Good:

```text
block-production-deletes
```

Better than:

```text
policy-4
```

Policy IDs should describe their purpose.

---

### Avoid deeply nested logic

If a policy becomes difficult to understand, consider splitting it into multiple policies.

Simple policies are easier to debug and less likely to introduce unexpected behavior.

---

### Prefer allowlists

Instead of trying to block every unsafe value:

```text
Block:
A
B
C
D
E
```

Prefer explicitly allowing trusted values.

```text
Allow:
Production
Staging
```

Allowlists are easier to reason about and generally more secure.

---

## Validating Policies

Before deploying policies, always validate them.

```bash
swy policy validate
```

Validation checks for:

- Invalid operators
- Missing required fields
- Duplicate IDs
- Empty targets
- Invalid value types
- Unknown action types
- Incorrect condition structures
- Values that can't match the field's type in the tool's input schema

It also runs the [tests](#testing-policies) written in the file. Fix validation errors before running production workloads: while `policies.json` is invalid, every call is stopped.

---

## Testing Policies

Policies should be tested before deployment.

A typical workflow looks like this:

```text
Write Policy
      │
      ▼
Validate Policy
      │
      ▼
Test in Sandbox
      │
      ▼
Review Behavior
      │
      ▼
Deploy to Production
```

Three tools help:

**Tests in the file.** In a version-2 file, each policy can carry example calls and what should happen to them. `swy policy validate` runs them against the whole file and fails if one doesn't match, so they can run in CI:

```json
"tests": [
  { "args": { "amount": 250000 }, "expect": "block" },
  { "args": { "amount": 500 }, "expect": "allow" }
]
```

Tests can also give earlier calls (for rate limits), the expected changed arguments of a `MODIFY`, or a response for response policies. They never send, count, or log anything. See [Tests](/configuration/policy-json/#tests).

**Dry runs.** `--dry-run` runs every policy check on a real request without making the API call:

```bash
swy policy validate
swy exec <canonical_id> --dry-run
```

**Monitor mode.** `"mode": "monitor"` lets a new rule watch real traffic without blocking. Matches show up as `monitored` in `swy audit policy`; switch to enforcing once the rule catches exactly what you meant.

Once a policy is live, `swy audit policy` shows you which requests it has actually blocked, changed, or hidden, so you can tell a too-strict rule from a working one.

---

## Best Practices

- Write one policy per business rule.
- Use descriptive policy IDs.
- Prefer allowlists whenever possible.
- Keep conditions simple and readable.
- Validate policies after every change.
- Test policies in sandbox environments before production.
- Review policies alongside application code during code review.
- Add `tests` to each policy and run `swy policy validate` in CI.
- Try new rules in monitor mode first.
- Remove unused policies to keep configurations easy to maintain.

---

## Next steps

- [Policy recipes](https://docs.swytchcode.com/policies/recipes/) - Ready-to-use policies for email, payments, data safety, and more.
- [Human approval](https://docs.swytchcode.com/policies/human-approval/) - Hold a matching command until a person approves it in Slack.
- [Production Guardrails](https://docs.swytchcode.com/policies/production-guardrails/) - Recommended safeguards for running AI agents against production systems.
- [Best Practices](https://docs.swytchcode.com/policies/best-practices/) - Recommendations for maintainable, predictable, secure policy configurations.
- [Policies overview](https://docs.swytchcode.com/policies/overview/) - The policy engine that decides what an agent can do, when, and how.
