Skip to main content

Overview

The Communication pack provides guardrails for AI agents that send emails, messages, or notifications. It prevents mass messaging, blocks messages containing credentials, and automatically redacts PII from message outputs. Use this pack for:
  • Email automation agents
  • Customer support chatbots
  • Marketing automation tools
  • Notification systems
  • Messaging integrations (Slack, Teams, SMS)

Complete Policy

communication.yaml
version: "1.0"
name: communication-pack
description: Guardrails for email and messaging tools.
rules:
  - id: comm-block-mass-recipients
    name: Block mass email sends
    description: Require approval when sending to more than 5 recipients.
    enabled: true
    severity: high
    action: require_approval
    tools:
      - send_email
      - send_message
      - notify
      - send_notification
    conditions:
      - field: arguments.to
        operator: length_greater_than
        value: 5

  - id: comm-block-sensitive-content
    name: Block emails containing credentials
    description: Block messages that contain password-like or key-like strings.
    enabled: true
    severity: critical
    action: block
    tools:
      - send_email
      - send_message
    condition_groups:
      - - field: arguments.body
          operator: matches
          value: '(?:[Pp]assword|[Ss]ecret|[Aa][Pp][Ii][_-]?[Kk]ey|[Tt]oken)\s*[:=]\s*\S+'
      - - field: arguments.subject
          operator: matches
          value: "(?:[Pp]assword|[Cc]redentials|[Ss]ecret)"

output_rules:
  - id: comm-redact-pii-in-output
    name: Redact PII from messaging outputs
    description: Redact phone numbers and emails from messaging tool outputs.
    enabled: true
    severity: medium
    action: redact
    tools:
      - send_email
      - read_email
      - get_messages
    output_conditions:
      - field: output
        operator: matches
        value: '\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b'
    redact_with: "[REDACTED_PHONE]"

Rules Explained

Input Validation Rules

1. Block Mass Email Sends

Rule ID: comm-block-mass-recipients What it does: Requires human approval when sending emails/messages to more than 5 recipients. Why it’s important:
  • Spam prevention - Stops AI agents from unintentionally spamming users
  • Reputation protection - Mass emails can get your domain blacklisted
  • GDPR compliance - Mass communications require consent and privacy notices
  • Cost control - Prevents expensive bulk sends (especially SMS)
Example:
// This requires approval:
await sendEmail({ 
  to: ['[email protected]', '[email protected]', '[email protected]', 
       '[email protected]', '[email protected]', '[email protected]'],
  subject: 'Update',
  body: 'Important message'
});

// User sees:
// "Approve sending email to 6 recipients?"
// Recipients: user1@..., user2@..., [+4 more]
// Subject: Update
// [Approve] [Reject]

// Meanwhile, individual messages are allowed:
await sendEmail({ 
  to: ['[email protected]'],
  subject: 'Personal message',
  body: 'Hello!'
});
// ✓ Executes immediately (1 recipient)
Customizing the threshold:
rules:
  - id: comm-block-mass-recipients
    conditions:
      - field: arguments.to
        operator: length_greater_than
        value: 100  # Allow up to 100 recipients before requiring approval

2. Block Sensitive Content

Rule ID: comm-block-sensitive-content What it does: Blocks emails/messages that contain credentials, API keys, passwords, or secrets. Detection patterns: In message body:
  • password: <value>
  • Password = <value>
  • secret: <value>
  • API_KEY: <value>
  • api-key: <value>
  • token: <value>
In subject line:
  • Contains password
  • Contains credentials
  • Contains secret
Why it’s important:
  • Security risk - Credentials should never be sent via email (unencrypted)
  • Compliance - Violates PCI DSS, SOC 2, HIPAA
  • Data breach - Email can be intercepted, forwarded, or hacked
  • Social engineering - AI could be tricked into leaking credentials
Example blocked calls:
// BLOCKED: Password in body
await sendEmail({ 
  to: '[email protected]',
  subject: 'Account Setup',
  body: 'Your password: abc123xyz'
});
// Error: Message contains credentials

// BLOCKED: API key in body
await sendMessage({ 
  to: '+1234567890',
  body: 'API_KEY: sk_live_123abc456def'
});
// Error: Message contains credentials

// BLOCKED: Password in subject
await sendEmail({ 
  to: '[email protected]',
  subject: 'Password Reset',
  body: 'Click here to reset'
});
// Error: Subject contains sensitive keyword
Safe alternatives:
// ✓ Send a password reset link instead
await sendEmail({ 
  to: '[email protected]',
  subject: 'Reset Your Account',
  body: 'Click here: https://app.example.com/reset?token=...'
});

// ✓ Use a secure credential sharing tool
await sendEmail({ 
  to: '[email protected]',
  subject: 'Account Access',
  body: 'Your credentials are available at: https://vault.example.com/share/xyz'
});

Output Redaction Rules

3. Redact PII from Messaging Outputs

Rule ID: comm-redact-pii-in-output What it does: Automatically redacts phone numbers from tool outputs (sent messages, read emails, fetched messages). Pattern matched: \b\d{3}[-.]?\d{3}[-.]?\d{4}\b Matches:
  • 123-456-7890
  • 123.456.7890
  • 1234567890
Why it’s important:
  • Prevents AI from seeing/storing customer phone numbers
  • Reduces PII exposure in logs
  • Helps with GDPR/CCPA compliance
Example:
// Tool returns message content with phone number
const result = await readEmail({ messageId: '12345' });
// Original: { from: '[email protected]', body: 'Call me at 555-123-4567' }

// After redaction (what the AI sees):
// { from: '[email protected]', body: 'Call me at [REDACTED_PHONE]' }
Adding email redaction:
output_rules:
  - id: custom-redact-email-in-messages
    name: Redact email addresses from message outputs
    action: redact
    severity: medium
    tools:
      - read_email
      - get_messages
    output_conditions:
      - field: output
        operator: matches
        value: '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}'
    redact_with: "[REDACTED_EMAIL]"

Usage Example

Basic Setup

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

mode: "strict"

# Configure approval workflow for mass sends
approval:
  callbackUrl: "https://your-approval-service.com/approve"
  timeout: 60000  # 60 seconds
  timeoutBehavior: "block"

With TypeScript SDK

import { Veto } from 'veto-sdk';
import nodemailer from 'nodemailer';

const veto = await Veto.init();

const emailTools = [
  {
    name: 'send_email',
    description: 'Send an email to one or more recipients',
    handler: async ({ to, subject, body }: {
      to: string[];
      subject: string;
      body: string;
    }) => {
      const transporter = nodemailer.createTransport({
        host: 'smtp.example.com',
        port: 587,
        auth: {
          user: process.env.SMTP_USER,
          pass: process.env.SMTP_PASSWORD,
        },
      });
      
      const info = await transporter.sendMail({
        from: '[email protected]',
        to: to.join(','),
        subject,
        text: body,
      });
      
      return { messageId: info.messageId, sent: true };
    },
  },
  {
    name: 'send_message',
    description: 'Send an SMS message',
    handler: async ({ to, body }: { to: string; body: string }) => {
      // Call your SMS API (Twilio, AWS SNS, etc.)
      const result = await smsAPI.send({ to, message: body });
      return { messageId: result.id };
    },
  },
];

const wrappedTools = veto.wrap(emailTools);

// Use with your AI agent
// Mass sends require approval
// Credentials in messages are blocked

With Slack Integration

import { WebClient } from '@slack/web-api';
import { Veto } from 'veto-sdk';

const veto = await Veto.init();
const slack = new WebClient(process.env.SLACK_BOT_TOKEN);

const slackTools = [
  {
    name: 'send_message',
    handler: async ({ to, body }: { to: string[]; body: string }) => {
      // 'to' is an array of channel IDs or user IDs
      const results = await Promise.all(
        to.map(channel => 
          slack.chat.postMessage({ channel, text: body })
        )
      );
      return { sent: results.length, channels: to };
    },
  },
];

const wrappedTools = veto.wrap(slackTools);
// Sending to >5 channels requires approval

Customization

Different Limits by Message Type

Allow more recipients for notifications vs. emails:
rules:
  - id: comm-block-mass-recipients
    # Override for send_email only
    tools:
      - send_email
    conditions:
      - field: arguments.to
        operator: length_greater_than
        value: 5
  
  - id: custom-allow-more-notifications
    name: Allow up to 50 notification recipients
    action: require_approval
    tools:
      - notify
      - send_notification
    conditions:
      - field: arguments.to
        operator: length_greater_than
        value: 50

Block Specific Domains

Prevent sending to competitor domains:
rules:
  - id: custom-block-competitor-domains
    name: Block emails to competitor domains
    action: block
    severity: high
    tools:
      - send_email
    conditions:
      - field: arguments.to
        operator: matches
        value: '@(competitor1\\.com|competitor2\\.com)$'

Require Approval for External Emails

Only allow internal emails automatically:
rules:
  - id: custom-approve-external-emails
    name: Require approval for external emails
    action: require_approval
    severity: high
    tools:
      - send_email
    conditions:
      - field: arguments.to
        operator: not_matches
        value: '@yourcompany\\.com$'

Add Attachment Protection

Block potentially dangerous attachments:
rules:
  - id: custom-block-executable-attachments
    name: Block executable attachments
    action: block
    severity: critical
    tools:
      - send_email
    condition_groups:
      - - field: arguments.attachments
          operator: contains
          value: ".exe"
      - - field: arguments.attachments
          operator: contains
          value: ".bat"
      - - field: arguments.attachments
          operator: contains
          value: ".sh"
Ensure marketing emails include unsubscribe links:
rules:
  - id: custom-require-unsubscribe-link
    name: Block marketing emails without unsubscribe link
    action: block
    severity: high
    tools:
      - send_email
    conditions:
      - field: arguments.category
        operator: equals
        value: marketing
      - field: arguments.body
        operator: not_contains
        value: unsubscribe

Real-World Scenarios

Customer Support Agent

const supportTools = [
  {
    name: 'send_email',
    handler: async ({ to, subject, body, ticketId }) => {
      // Always single recipient for support
      await emailClient.send({
        to: [to],
        subject: `[Ticket #${ticketId}] ${subject}`,
        body,
        replyTo: '[email protected]',
      });
      return { sent: true };
    },
  },
  {
    name: 'read_email',
    handler: async ({ ticketId }) => {
      const messages = await emailClient.getThread(ticketId);
      return { messages };
    },
  },
];

const wrappedTools = veto.wrap(supportTools);
// Phone numbers in customer emails are auto-redacted
// Credentials in responses are blocked

Marketing Automation

marketing-automation.yaml
version: "1.0"
extends: "@veto/communication"

rules:
  # Require approval for sends over 1000 recipients
  - id: comm-block-mass-recipients
    conditions:
      - field: arguments.to
        operator: length_greater_than
        value: 1000
  
  # Require unsubscribe link
  - id: custom-require-unsubscribe-link
    name: Require unsubscribe link in marketing emails
    action: block
    severity: high
    tools:
      - send_email
    conditions:
      - field: arguments.body
        operator: not_contains
        value: "{{unsubscribe_url}}"

Internal Notification System

internal-notifications.yaml
version: "1.0"
extends: "@veto/communication"

rules:
  # Allow more recipients for internal notifications
  - id: comm-block-mass-recipients
    conditions:
      - field: arguments.to
        operator: length_greater_than
        value: 50  # Up to 50 employees
  
  # Disable credential blocking for internal system messages
  - id: comm-block-sensitive-content
    enabled: false

Testing

# Test mass recipient block
npx veto-cli guard check \
  --tool send_email \
  --args '{"to": ["[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]"], "subject": "Update", "body": "Message"}' \
  --json

# Output:
# {
#   "action": "require_approval",
#   "rule": "comm-block-mass-recipients"
# }

# Test credential blocking
npx veto-cli guard check \
  --tool send_email \
  --args '{"to": ["[email protected]"], "subject": "Account", "body": "Your password: abc123"}' \
  --json

# Output:
# {
#   "action": "deny",
#   "rule": "comm-block-sensitive-content"
# }

# Test valid single email (should allow)
npx veto-cli guard check \
  --tool send_email \
  --args '{"to": ["[email protected]"], "subject": "Hello", "body": "How are you?"}' \
  --json

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

Email Security Best Practices

Configure email authentication to prevent spoofing:
; SPF record
example.com. IN TXT "v=spf1 include:_spf.google.com ~all"

; DMARC record
_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:[email protected]"
Implement additional rate limiting beyond recipient count:
const veto = await Veto.init({
  budgets: [{
    tool: 'send_email',
    limit: 100,
    window: 3600,  // 100 emails per hour
  }],
});
Keep records for compliance and debugging:
const handler = async ({ to, subject, body }) => {
  await auditLog.write({
    action: 'email_sent',
    recipients: to,
    subject,
    timestamp: new Date(),
  });
  
  return await emailClient.send({ to, subject, body });
};
Prevent malformed or unprofessional messages:
const handler = async ({ to, templateId, variables }) => {
  const template = await getTemplate(templateId);
  const body = renderTemplate(template, variables);
  
  return await emailClient.send({ to, body });
};

Policy Pack Overview

Learn about all available policy packs

Data Access Pack

Additional PII redaction for customer data

Output Patterns Reference

Built-in regex patterns for PII detection

Human-in-the-Loop Guide

Set up approval workflows for mass sends

Build docs developers (and LLMs) love