Appearance
Production Deployment
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Production checklist
Security
- [ ] HTTPS enabled with valid certificates
- [ ]
SWML_BASIC_AUTH_PASSWORDconfigured (username defaults tosignalwire) - [ ] Firewall rules in place
- [ ] No secrets in code or logs (SDK masks credentials in startup output automatically)
Reliability
- [ ] Process manager (systemd/supervisor)
- [ ] Health checks configured
- [ ] Logging to persistent storage
- [ ] Error monitoring/alerting
Performance
- [ ] Multiple workers for concurrency
- [ ] Reverse proxy (nginx) for SSL termination
- [ ] Load balancing if needed
Environment variables
## Authentication (password required; username defaults to 'signalwire')
export SWML_BASIC_AUTH_PASSWORD="your-secure-password"
# export SWML_BASIC_AUTH_USER="signalwire" # optional, defaults to 'signalwire'
<Badge type="tip" text="Fresh" />
## SSL Configuration
export SWML_SSL_ENABLED="true"
export SWML_SSL_CERT_PATH="/etc/ssl/certs/agent.crt"
export SWML_SSL_KEY_PATH="/etc/ssl/private/agent.key"
## Domain configuration
export SWML_DOMAIN="agent.example.com"
## Proxy URL (if behind load balancer/reverse proxy)
export SWML_PROXY_URL_BASE="https://agent.example.com"
# APP_URL is accepted as a fallback for SWML_PROXY_URL_BASERunning in production
Production deployment differs significantly by language. Each SDK provides its own HTTP server or integrates with language-specific production servers.
Python
TypeScript
Use uvicorn with multiple workers:
## Run with 4 workers
uvicorn my_agent:app --host 0.0.0.0 --port 3000 --workers 4Create an entry point module:
#!/usr/bin/env python3
# my_agent.py
from signalwire import AgentBase
class MyAgent(AgentBase):
def __init__(self):
super().__init__(name="my-agent")
self.add_language("English", "en-US", "rime.spore")
self.prompt_add_section("Role", "You are a helpful assistant.")
if __name__ == "__main__":
agent = MyAgent()
agent.run(host="0.0.0.0", port=3000)Systemd service
Create /etc/systemd/system/signalwire-agent.service. Adjust ExecStart for your language:
| Language | ExecStart Example |
|---|---|
| Python | /opt/agent/venv/bin/uvicorn app:app --host 127.0.0.1 --port 3000 --workers 4 |
| TypeScript | /usr/bin/node /opt/agent/app.mjs |
[Unit]
Description=SignalWire AI Agent
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/agent
Environment="SWML_BASIC_AUTH_USER=your-username"
Environment="SWML_BASIC_AUTH_PASSWORD=your-password"
ExecStart=/opt/agent/venv/bin/uvicorn app:app --host 127.0.0.1 --port 3000 --workers 4
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetEnable and start:
sudo systemctl enable signalwire-agent
sudo systemctl start signalwire-agent
sudo systemctl status signalwire-agentNginx reverse proxy
## /etc/nginx/sites-available/agent
server {
listen 443 ssl http2;
server_name agent.example.com;
ssl_certificate /etc/ssl/certs/agent.crt;
ssl_certificate_key /etc/ssl/private/agent.key;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
}
}
server {
listen 80;
server_name agent.example.com;
return 301 https://$server_name$request_uri;
}Enable the site:
sudo ln -s /etc/nginx/sites-available/agent /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginxProduction architecture
Production architecture diagram showing nginx, uvicorn workers, and SignalWire Cloud.
Production Architecture
SSL configuration
Using environment variables
export SWML_SSL_ENABLED="true"
export SWML_SSL_CERT_PATH="/path/to/cert.pem"
export SWML_SSL_KEY_PATH="/path/to/key.pem"Let’s Encrypt with Certbot
## Install certbot
sudo apt install certbot python3-certbot-nginx
## Get certificate
sudo certbot --nginx -d agent.example.com
## Auto-renewal is configured automaticallyHealth checks
For AgentServer deployments:
## Health check endpoint
curl https://agent.example.com/healthResponse:
{
"status": "ok",
"agents": 1,
"routes": ["/"]
}For load balancers, use this endpoint to verify agent availability.
Logging configuration
import logging
## Configure logging for production
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[\
logging.FileHandler('/var/log/agent/agent.log'),\
logging.StreamHandler()\
]
)Or use environment variable:
export SIGNALWIRE_LOG_MODE=defaultMonitoring
Prometheus metrics
Add custom metrics to your agent:
from prometheus_client import Counter, Histogram, start_http_server
## Start metrics server on port 9090
start_http_server(9090)
## Define metrics
call_counter = Counter('agent_calls_total', 'Total calls handled')
call_duration = Histogram('agent_call_duration_seconds', 'Call duration')External monitoring
- Uptime monitoring: Monitor the health endpoint
- Log aggregation: Ship logs to ELK, Datadog, or similar
- APM: Use Application Performance Monitoring tools
Scaling considerations
Vertical scaling
| Language | Scaling Approach |
|---|---|
| Python | Increase uvicorn workers (--workers N) |
| TypeScript | Increase PM2 instances (pm2 scale agent 8) |
- Use larger server instances
- Optimize agent code and external calls
Horizontal scaling
- Multiple server instances behind load balancer
- Stateless agent design
- Shared session storage (Redis) if needed
Serverless
- Auto-scaling with Lambda/Cloud Functions
- Pay per invocation
- No server management
Built-in security features
The SDK includes several security hardening features enabled by default.
Security headers
All HTTP responses automatically include security headers:
| Header | Value | Purpose |
|---|---|---|
X-Content-Type-Options | nosniff | Prevent MIME-type sniffing |
X-Frame-Options | DENY | Prevent clickjacking |
Referrer-Policy | strict-origin-when-cross-origin | Limit referrer information |
Strict-Transport-Security | max-age=31536000; includeSubDomains | Force HTTPS (when SSL enabled) |
No configuration is needed, these headers are added automatically by middleware on AgentBase, AgentServer, and SWMLService.
SSRF protection
DataMap HTTP requests, skill remote URLs, and MCP gateway URLs are validated against private IP ranges to prevent Server-Side Request Forgery attacks. By default, requests to internal networks (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 169.254.0.0/16, and IPv6 equivalents) are blocked.
To allow private URLs (e.g., when your backend services are on a private network):
export SWML_ALLOW_PRIVATE_URLS=trueTiming-safe authentication
Basic auth credential comparison uses hmac.compare_digest() to prevent timing side-channel attacks. SWAIG token validation also uses constant-time comparison.
Credential masking
Startup log output shows (credentials configured) instead of the actual password:
Agent 'my-agent' is available at:
URL: http://0.0.0.0:3000
Basic Auth: signalwire:(credentials configured) (source: environment)Default authentication username
SWML_BASIC_AUTH_USER defaults to signalwire when not explicitly set. You only need to configure SWML_BASIC_AUTH_PASSWORD:
export SWML_BASIC_AUTH_PASSWORD="your-secure-password"
# Username defaults to 'signalwire', no need to set SWML_BASIC_AUTH_USERProxy header validation
X-Forwarded headers (X-Forwarded-Host, X-Forwarded-Proto) are only trusted when explicitly configured. Set SWML_TRUST_PROXY_HEADERS=true if your agent runs behind a reverse proxy and you want the SDK to auto-detect the public URL from forwarded headers:
export SWML_TRUST_PROXY_HEADERS=trueWhen SWML_PROXY_URL_BASE is set via environment variable, proxy headers are automatically trusted for URL construction.
Security best practices
DO:
- Use HTTPS everywhere
- Set strong basic auth credentials
- Use environment variables for secrets
- Enable firewall and limit access
- Regularly update dependencies
- Monitor for suspicious activity
DON’T:
- Expose debug endpoints in production
- Log sensitive data
- Use default credentials
- Disable SSL verification
- Run as root user
Production architecture diagram showing nginx, uvicorn workers, and SignalWire Cloud.
