Skip to content

Building an AI agent is easy.

Building one that safely interacts with production systems is much harder.

Unlike traditional applications, AI agents make decisions dynamically. A single prompt can trigger multiple API calls, execute workflows, or interact with critical business systems. Without proper safeguards, mistakes can quickly become production incidents.

Swytchcode provides multiple layers of protection to help you build reliable AI applications. This guide explains the recommended practices for deploying AI agents in production.


Defense in Depth

No single safeguard is enough.

Instead, combine multiple layers of protection.

User Prompt
│
▼
AI Agent
│
▼
Trusted Tools
(tooling.json)
│
▼
Policy Validation
(policies.json)
│
▼
Execution Controls
(manifest.json)
│
▼
Authentication
│
▼
Provider API

If one layer fails, the remaining layers continue protecting your application.


Principle of Least Privilege

Only expose the tools your application actually needs.

For example, if an AI assistant only creates GitHub issues, it should not also have permission to:

  • Delete repositories
  • Manage organization members
  • Create deployments
  • Modify repository settings

Every additional capability increases the potential impact of an unexpected or incorrect request.

Keep your trusted tool list as small as possible.


Run agents safely

Policies are written at build time and enforced at run time. A deployed agent must not be able to change them. Swytchcode enforces policies only on calls that go through Swytchcode, so set up the agent’s environment so it has no other path:

  • Connect with the agent MCP profile only (swy mcp serve --profile agent, the default). It can list policies but has no tools to add or remove them. Keep --profile full for your editor.
  • No shell or file-system access to the project. An agent that can run commands or edit files can change or delete .swytchcode/integrations/policies.json, and a missing file means no guards.
  • Deploy policies.json read-only, exactly as it was committed and reviewed.
  • No access to provider API keys (.env files, secrets). With the keys, an agent can call the provider’s API directly, for example with curl, and skip Swytchcode and every policy.

A personal agent (Hermes, OpenClaw, ZeroClaw driven from a chat) uses the operator profile instead. It may add stricter policies but can’t remove or loosen them, and its project gets a baseline policy that holds every call that changes something for approval. See Personal agents.

REQUIRES_APPROVAL policies still reach a human at run time through human approval. Each approval covers one call, unless the policy sets reuse.

Know what policies can and can’t do:

  • Limits are per machine. rate, sum, and the other conditions on earlier calls count calls made from one project on one machine. Five agents on five machines each get their own daily cap.
  • Response policies can’t undo a call. They hide or cut what the agent sees; the provider has already acted.
  • Detectors are pattern-based. contains_pii, contains_secret, and REDACT’s detect catch common formats, not every one.
  • Only calls through Swytchcode are checked. That’s why the agent must not have the keys or a shell.

Separate Development and Production

Never use production resources during development.

Instead:

Development
│
▼
Sandbox APIs
│
▼
Testing
│
▼
Production

Use sandbox endpoints whenever they are available.

Before switching to production, verify that:

  • Policies have been validated.
  • Authentication is configured correctly.
  • Expected requests behave as intended.

Protect Destructive Operations

Operations that modify or delete data deserve additional protection.

Examples include:

  • Deleting repositories
  • Canceling subscriptions
  • Refunding payments
  • Revoking user access
  • Removing infrastructure
  • Deleting databases

Consider blocking these operations entirely in production unless they are explicitly required. In a version-2 file, one policy can cover every tool:

{
"id": "no-prod-deletes",
"target": ["*"],
"when": {
"operator": "all",
"conditions": [
{ "field": "$http_method", "operator": "==", "value": "DELETE" },
{ "field": "$env", "operator": "==", "value": "production" }
]
},
"action": { "type": "POLICY_BLOCKED", "message": "Deletes are disabled in production" }
}

Or for a single method:

{
"id": "block-database-reset",
"target": ["postgres.database.reset"],
"when": { "field": "database", "operator": "exists" },
"action": {
"type": "POLICY_BLOCKED",
"message": "Database resets are disabled in production."
}
}

When possible, separate read-only tools from write operations - only enable the write method in tooling.json for the environments and agents that genuinely need it.


Keep Sensitive Data from the Agent

What a provider returns goes into the agent’s context, and from there possibly into logs, prompts, and other tools. A response policy changes the response before the agent - or the local audit log - sees it:

{
"id": "hide-sensitive-response-data",
"target": ["*"],
"stage": "response",
"when": { "field": "$status_code", "operator": "<", "value": 300 },
"action": { "type": "REDACT", "detect": ["card", "ssn", "iban", "secret"] }
}

Use TRUNCATE to cap how many records one call returns, and a sum over $response_items to cap records read per day. See Response Policies.


Validate Every Request

Do not assume that generated requests are correct.

Always validate important request fields before execution.

Examples include:

  • Payment amounts
  • Email addresses
  • Resource identifiers
  • Organization names
  • Deployment environments
  • Regions

Reject invalid requests before they reach the provider.


Use Idempotency for Mutating Operations

Network failures happen.

Retries happen.

Without idempotency, the same request can execute more than once.

Create Payment
│
▼
Request Times Out
│
▼
Automatic Retry
│
▼
Duplicate Payment

With idempotency enabled:

Create Payment
│
▼
Request Times Out
│
▼
Retry
│
▼
Existing Operation Returned

For APIs that support idempotency, enable it whenever requests create, modify, or delete resources.


Configure Retries Carefully

Retries improve reliability, but they should be used selectively.

Good retry candidates include:

  • Temporary server failures
  • Network interruptions
  • Rate limiting
  • Service unavailable responses

Avoid retrying requests that fail because of invalid input or authorization issues.

A retry should only happen when another attempt has a reasonable chance of succeeding.


Limit Concurrency

AI agents often execute multiple operations simultaneously.

Without limits, this can overwhelm downstream services.

Instead of allowing unlimited parallel requests:

100 Parallel Requests

Use reasonable concurrency limits based on the provider’s recommendations.

This reduces:

  • Rate limiting
  • Resource exhaustion
  • Unexpected API failures

Secure Authentication

Treat API credentials as production secrets.

Never:

  • Hardcode API keys
  • Commit credentials to Git repositories
  • Embed secrets in prompts
  • Store secrets in source code

Instead:

  • Use environment variables.
  • Use OAuth where supported.
  • Rotate credentials regularly.
  • Grant only the minimum required permissions.

Restrict Network Access

Whenever possible, limit outbound requests to trusted providers.

Instead of allowing requests to any destination, configure an allowlist of expected hosts.

For example:

  • api.stripe.com
  • api.github.com
  • api.slack.com

Restricting network access helps prevent accidental or unauthorized communication with unexpected endpoints.


Pin Integration Versions

Always use pinned integration versions.

Avoid automatically upgrading integrations in production without testing.

Version pinning provides:

  • Reproducible behavior
  • Predictable request formats
  • Easier debugging
  • Safer deployments

Review new integration versions before adopting them.


Test Before Deploying

Every change should follow a predictable deployment process.

Update Configuration
│
▼
Validate Policies
│
▼
Run Sandbox Tests
│
▼
Review Results
│
▼
Deploy to Production

Testing before deployment reduces the likelihood of production incidents and makes behavior easier to verify. In command form, that pipeline is:

Terminal window
swy policy validate # catch errors in policies.json and run its tests
swy exec <canonical_id> --dry-run # run every policy on a real request without executing it
# review results, then deploy

Run swy policy validate in CI so a broken rule or a failing policy test stops the deploy.


Monitor and Audit

Production systems should be observable. Swytchcode keeps a local audit trail under ~/.swytchcode/audit/ that you can query directly, without needing Cloud Sync or signing in:

Terminal window
swy audit stats # total runs, success rate, last run, top provider
swy audit network -n 20 # recent outbound calls: host, method, status, duration
swy audit policy -n 20 # recent policy decisions: blocked, changed, hidden, monitored
swy policy state # counts kept by rate, sum, and repeat limits
swy doctor # tooling, bundles, auth, permissions, secrets

Regularly review:

  • Enabled tools (swy list tooling) and active integrations (swy list integrations)
  • Policy changes - diff policies.json in code review like any other config file
  • Failed executions and their exit codes (see Troubleshooting)
  • Policy violations via swy audit policy - this is a read-only history of what got blocked or held, distinct from swy policy list, which shows the rules themselves
  • Authentication failures - swy whoami and swy auth status show current auth state; failing calls also show up in swy audit network
  • Workspace log storage in the dashboard, if you turned it on for that workspace
  • Pending approval requests in Slack

Treat changes to policies and integrations with the same level of review as application code.

For high-impact production actions, require human approval so a person must confirm the command before it runs.


Production Checklist

Before deploying an AI agent, verify the following:

  • Only required tools are enabled (swy list tooling).
  • Policies have been validated and their tests pass (swy policy validate, in CI).
  • New rules were tried in monitor mode before enforcing them.
  • Responses with sensitive data are redacted before the agent sees them.
  • The deployed agent uses the agent MCP profile (or operator for a personal agent), has no shell access, and cannot read provider API keys (Run agents safely).
  • Sandbox testing has been completed.
  • Production credentials are configured securely (swy auth status, swy doctor).
  • Integration versions are pinned.
  • Idempotency is enabled for mutating operations.
  • Retry behavior has been reviewed.
  • Concurrency limits have been configured.
  • Network access is restricted where possible (swy doctor --network).
  • Secrets are managed securely.
  • Policy and configuration changes have been reviewed.
  • High-impact commands require human approval where appropriate.
  • Workspace log storage is on if you need a searchable dashboard history.

Key Takeaways

A production-ready AI agent should be:

  • Least-privileged - Only the required capabilities are available.
  • Policy-driven - Every request is validated before execution.
  • Reliable - Retries, timeouts, and idempotency are configured appropriately.
  • Observable - Behavior can be monitored and audited.
  • Predictable - Configuration is version-controlled and reproducible.

By combining trusted tools, policy validation, execution controls, and secure authentication, you can confidently deploy AI agents that interact with real-world APIs while minimizing operational risk.