Skip to main content

Overview

The Deployment pack provides essential safety controls for AI agents that manage deployments, releases, or CI/CD workflows. It ensures production deployments are approved by humans and prevents dangerous force-deploy operations. Use this pack for:
  • DevOps automation agents
  • CI/CD pipeline tools
  • Release management systems
  • Infrastructure deployment agents
  • GitOps workflows

Complete Policy

deployment.yaml
version: "1.0"
name: deployment-pack
description: Guardrails for deployment and release tools.
rules:
  - id: deploy-require-approval-production
    name: Require approval for production deploys
    description: All production deployments must be approved by a human.
    enabled: true
    severity: critical
    action: require_approval
    tools:
      - deploy
      - publish
      - release
      - push_to_production
    condition_groups:
      - - field: arguments.environment
          operator: equals
          value: production
      - - field: arguments.environment
          operator: equals
          value: prod
      - - field: arguments.env
          operator: equals
          value: production
      - - field: arguments.env
          operator: equals
          value: prod
      - - field: arguments.target
          operator: equals
          value: production

  - id: deploy-block-force-push
    name: Block force deployments
    description: Block deployments with force/skip-checks flags.
    enabled: true
    severity: high
    action: block
    tools:
      - deploy
      - publish
      - release
    condition_groups:
      - - field: arguments.force
          operator: equals
          value: true
      - - field: arguments.skip_checks
          operator: equals
          value: true
      - - field: arguments.skip_tests
          operator: equals
          value: true

Rules Explained

1. Require Approval for Production Deploys

Rule ID: deploy-require-approval-production What it does: Requires explicit human approval before deploying to production environments. Detected production environment patterns:
  • arguments.environment === "production"
  • arguments.environment === "prod"
  • arguments.env === "production"
  • arguments.env === "prod"
  • arguments.target === "production"
Why it’s important: Production deployments can cause:
  • Service outages affecting customers
  • Data loss or corruption
  • Security vulnerabilities
  • Compliance violations
  • Revenue impact
AI agents should assist with deployment automation, but final production releases should be human-reviewed to ensure:
  • Correct version is being deployed
  • Rollback plan is ready
  • Timing is appropriate (not during peak hours)
  • All stakeholders are informed
Example:
// This requires human approval:
await deploy({ 
  environment: "production",
  version: "v2.5.0",
  service: "api-gateway"
});

// User sees approval request:
// "Approve deployment of api-gateway v2.5.0 to production?"

// Meanwhile, staging deploys are allowed automatically:
await deploy({ 
  environment: "staging",
  version: "v2.5.0",
  service: "api-gateway"
});
// ✓ Executes immediately (not production)

2. Block Force Deployments

Rule ID: deploy-block-force-push What it does: Blocks deployments that skip safety checks via flags like force, skip_checks, or skip_tests. Blocked flags:
  • arguments.force === true
  • arguments.skip_checks === true
  • arguments.skip_tests === true
Why it’s important: Force flags bypass critical safety mechanisms:
  • Tests - May deploy broken code
  • Checks - May violate security/compliance policies
  • Validation - May deploy incompatible versions
These flags exist for emergency recovery scenarios, but should never be used by automated agents. Example blocked calls:
// All of these are blocked:
await deploy({ 
  environment: "staging",
  version: "v2.5.0",
  force: true  // BLOCKED
});

await publish({ 
  package: "@myapp/core",
  skip_tests: true  // BLOCKED
});

await release({ 
  tag: "v1.0.0",
  skip_checks: true  // BLOCKED
});
When you might disable this rule: If your deployment system uses force for legitimate purposes (e.g., force-replacing a cache), you can:
  1. Rename the parameter in your tool
  2. Override the rule to only check production deploys
  3. Add a custom rule for your specific workflow

Usage Example

Basic Setup

veto.config.yaml
version: "1.0"
extends: "@veto/deployment"

mode: "strict"

# Configure approval workflow
approval:
  callbackUrl: "https://your-approval-service.com/approve"
  timeout: 300000  # 5 minutes for deploy approval
  timeoutBehavior: "block"

With TypeScript SDK

import { Veto } from 'veto-sdk';

const veto = await Veto.init();

const deploymentTools = [
  {
    name: 'deploy',
    description: 'Deploy a service to an environment',
    handler: async ({ environment, version, service }: {
      environment: string;
      version: string;
      service: string;
    }) => {
      // Call your deployment system (Kubernetes, AWS, etc.)
      const result = await deploymentAPI.deploy({
        env: environment,
        image: `${service}:${version}`,
      });
      return { deploymentId: result.id, status: 'deployed' };
    },
  },
  {
    name: 'release',
    description: 'Create a new release',
    handler: async ({ tag, skipChecks }: {
      tag: string;
      skip_checks?: boolean;
    }) => {
      const result = await githubAPI.createRelease({ tag });
      return { releaseUrl: result.url };
    },
  },
];

const wrappedTools = veto.wrap(deploymentTools);

// Use with your AI agent
// Production deploys automatically trigger approval flow

Customization

Add More Environments to Approval

Require approval for staging or pre-production environments:
rules:
  - id: custom-require-approval-staging
    name: Require approval for staging deploys
    action: require_approval
    severity: high
    tools:
      - deploy
      - publish
      - release
    condition_groups:
      - - field: arguments.environment
          operator: equals
          value: staging
      - - field: arguments.environment
          operator: equals
          value: preprod

Block Deployments During Business Hours

Prevent production deployments during peak traffic:
rules:
  - id: custom-block-business-hours-deploy
    name: Block production deploys during business hours
    action: block
    severity: high
    tools:
      - deploy
      - publish
    conditions:
      - field: arguments.environment
        operator: equals
        value: production
      # Note: Time-based conditions require custom validation logic
      # This is a simplified example

Add Canary Deployment Protection

Require approval for full rollouts, but allow canary deploys:
rules:
  - id: custom-allow-canary-deploys
    name: Allow canary deployments to production
    action: allow
    tools:
      - deploy
    conditions:
      - field: arguments.environment
        operator: equals
        value: production
      - field: arguments.strategy
        operator: equals
        value: canary
      - field: arguments.traffic_percentage
        operator: less_than
        value: 10  # Only up to 10% traffic

Require Approval for Rollbacks

Even rollbacks should be reviewed:
rules:
  - id: custom-approve-rollbacks
    name: Require approval for production rollbacks
    action: require_approval
    severity: critical
    tools:
      - rollback
      - revert
    conditions:
      - field: arguments.environment
        operator: equals
        value: production

Integration with Deployment Systems

Kubernetes/Helm

const kubernetesTools = [
  {
    name: 'deploy',
    handler: async ({ environment, chart, values }: {
      environment: string;
      chart: string;
      values: Record<string, unknown>;
    }) => {
      const namespace = environment === 'production' ? 'prod' : 'staging';
      await helmClient.upgrade({
        chart,
        namespace,
        values,
      });
      return { status: 'deployed', namespace };
    },
  },
];

const wrappedTools = veto.wrap(kubernetesTools);
// Production deploys to 'prod' namespace require approval

AWS CodeDeploy

import { CodeDeployClient, CreateDeploymentCommand } from '@aws-sdk/client-codedeploy';

const awsTools = [
  {
    name: 'deploy',
    handler: async ({ environment, applicationName, revision }: {
      environment: string;
      applicationName: string;
      revision: { s3Location: string };
    }) => {
      const codedeploy = new CodeDeployClient({ region: 'us-east-1' });
      
      const deploymentGroupName = `${applicationName}-${environment}`;
      
      const command = new CreateDeploymentCommand({
        applicationName,
        deploymentGroupName,
        revision,
      });
      
      const result = await codedeploy.send(command);
      return { deploymentId: result.deploymentId };
    },
  },
];

const wrappedTools = veto.wrap(awsTools);

Vercel/Netlify

const vercelTools = [
  {
    name: 'deploy',
    handler: async ({ environment, projectId }: {
      environment: string;
      projectId: string;
    }) => {
      const target = environment === 'production' ? 'production' : 'preview';
      
      const deployment = await vercelClient.deployments.create({
        projectId,
        target,
      });
      
      return { url: deployment.url, deploymentId: deployment.id };
    },
  },
];

const wrappedTools = veto.wrap(vercelTools);
// Deployments to 'production' target require approval

Approval Workflow Example

Integrate with Slack for deployment approvals:
approval-slack-integration.ts
import express from 'express';
import { WebClient } from '@slack/web-api';

const app = express();
const slack = new WebClient(process.env.SLACK_BOT_TOKEN);

app.post('/approve', async (req, res) => {
  const { toolName, arguments: args, requestId } = req.body;
  
  // Post to Slack channel with approval buttons
  await slack.chat.postMessage({
    channel: '#deployments',
    text: `Deployment approval required`,
    blocks: [
      {
        type: 'section',
        text: {
          type: 'mrkdwn',
          text: `*Deployment Request*\n` +
                `Environment: ${args.environment}\n` +
                `Service: ${args.service}\n` +
                `Version: ${args.version}`,
        },
      },
      {
        type: 'actions',
        elements: [
          {
            type: 'button',
            text: { type: 'plain_text', text: 'Approve' },
            style: 'primary',
            value: requestId,
            action_id: 'approve_deploy',
          },
          {
            type: 'button',
            text: { type: 'plain_text', text: 'Reject' },
            style: 'danger',
            value: requestId,
            action_id: 'reject_deploy',
          },
        ],
      },
    ],
  });
  
  res.json({ status: 'pending' });
});

app.listen(8787);

Testing

Test deployment rules before going live:
# Test production deploy (should require approval)
npx veto-cli guard check \
  --tool deploy \
  --args '{"environment": "production", "version": "v2.0.0", "service": "api"}' \
  --json

# Output:
# {
#   "action": "require_approval",
#   "rule": "deploy-require-approval-production"
# }

# Test staging deploy (should allow)
npx veto-cli guard check \
  --tool deploy \
  --args '{"environment": "staging", "version": "v2.0.0"}' \
  --json

# Output:
# {
#   "action": "allow"
# }

# Test force deploy (should block)
npx veto-cli guard check \
  --tool deploy \
  --args '{"environment": "staging", "force": true}' \
  --json

# Output:
# {
#   "action": "deny",
#   "rule": "deploy-block-force-push"
# }

Policy Pack Overview

Learn about all available policy packs

Coding Agent Pack

Additional protection for development operations

Human-in-the-Loop Guide

Set up approval workflows for deployments

Event Webhooks

Send deployment notifications to monitoring systems

Build docs developers (and LLMs) love