Environment Boundaries and Constraints › Training vs. Production Environments

Michael BrenndoerferJuly 17, 20253 min read
AI Agent HandbookAll chapters
Part 8 of 15Environment and Interaction - The Agent's World
Chapter 23Environment Boundaries and Constraints › Training vs. Production Environments
Reading section 5 of 11 · Training vs. Production Environments · 3 minSection 5 of 11 · 3 min

Book contents

Section 5 of 11 · 3 min read

Environment Boundaries and Constraints › Training vs. Production EnvironmentsOne section · Sections in this chapter5 / 11 ↓

As you develop your agent, you'll work in different environments with different constraints. Understanding this distinction helps you test safely and deploy confidently.

Training and Testing Environments

When you're developing and testing your agent, you want an environment that:

  • Mimics production but uses fake or sanitized data
  • Allows experimentation without real consequences
  • Provides detailed logging for debugging
  • Can be reset easily when things go wrong

Here's a simple way to distinguish environments:

In[7]:
Code
## Example (GPT-5)
## Using GPT-5 for this straightforward environment configuration

import os


class EnvironmentConfig:
    def __init__(self, mode="development"):
        self.mode = mode
        self.setup_environment()

    def setup_environment(self):
        """Configure based on environment mode"""
        if self.mode == "development":
            self.database = "test_db"
            self.api_calls_enabled = False
            self.require_confirmations = False
            self.verbose_logging = True
            self.use_real_data = False

        elif self.mode == "staging":
            self.database = "staging_db"
            self.api_calls_enabled = True
            self.require_confirmations = True
            self.verbose_logging = True
            self.use_real_data = False

        elif self.mode == "production":
            self.database = "prod_db"
            self.api_calls_enabled = True
            self.require_confirmations = True
            self.verbose_logging = False
            self.use_real_data = True

    def can_perform_action(self, action):
        """Check if action is allowed in this environment"""
        if self.mode == "development":
            # In development, log but allow most things
            print(f"[DEV] Would perform: {action}")
            return True
        else:
            # In production, actually check permissions
            return self.check_real_permissions(action)


## Initialize for development
config = EnvironmentConfig(mode="development")

print(f"Running in {config.mode} mode")
print(f"Using database: {config.database}")
print(f"Real API calls: {config.api_calls_enabled}")
Out[7]:
Console
Running in development mode
Using database: test_db
Real API calls: False

In development mode, your agent might print what it would do instead of executing the action. This lets you test logic without consequences. When you move to production, those same actions become real.

Production Constraints

Production environments need stricter boundaries:

In[8]:
Code
## Example (Claude Sonnet 4.5)
## Using Claude Sonnet 4.5 for production-grade safety logic


class ProductionEnvironment:
    def __init__(self):
        self.safety_checks_enabled = True
        self.audit_logging = True
        self.rate_limits = {
            "email": {"max": 50, "window": 3600},  # 50 per hour
            "api_call": {"max": 1000, "window": 3600},
            "file_write": {"max": 100, "window": 3600},
        }

    def execute_action(self, action_type, action_data):
        """Execute an action with production safety checks"""

        # Check rate limits
        if not self.check_rate_limit(action_type):
            return {"success": False, "error": "Rate limit exceeded"}

        # Perform safety checks
        if self.safety_checks_enabled:
            safety_result = self.run_safety_checks(action_type, action_data)
            if not safety_result["safe"]:
                self.log_security_event(action_type, safety_result)
                return {
                    "success": False,
                    "error": f"Safety check failed: {safety_result['reason']}",
                }

        # Log for audit
        if self.audit_logging:
            self.log_action(action_type, action_data)

        # Execute the actual action
        result = self.perform_action(action_type, action_data)
        return result

    def run_safety_checks(self, action_type, action_data):
        """Run safety checks before executing"""
        # Check for suspicious patterns
        if action_type == "email" and "urgent" in str(action_data).lower():
            # Might be a phishing attempt
            return {"safe": False, "reason": "Suspicious email content"}

        # Add more checks as needed
        return {"safe": True}

    def log_action(self, action_type, action_data):
        """Log actions for audit trail"""
        # In a real system, this would write to a secure log
        print(f"[AUDIT] {action_type}: {action_data}")

    def check_rate_limit(self, action_type):
        """Check if action is within rate limits"""
        # Simplified for example
        return True

    def perform_action(self, action_type, action_data):
        """Actually perform the action"""
        return {"success": True, "message": "Action completed"}

    def log_security_event(self, action_type, details):
        """Log security events for review"""
        print(f"[SECURITY] Blocked {action_type}: {details['reason']}")


## Production environment with full safety checks
prod_env = ProductionEnvironment()

## Try to execute an action
result = prod_env.execute_action(
    "email", {"to": "user@example.com", "subject": "Meeting notes"}
)
print(result)
Out[8]:
Console
[AUDIT] email: {'to': 'user@example.com', 'subject': 'Meeting notes'}
{'success': True, 'message': 'Action completed'}

Notice how production adds layers of protection: rate limiting, safety checks, audit logging. These aren't needed in development, but they're essential when real users and real data are involved.