Agent Deployment Guide
7 min read
Deploy your custom agents and make them accessible to Mindra Platform.
Deployment Options
Option 1: Docker (Recommended)
Package your agent as a Docker container for consistent deployment.
Step 1: Create Dockerfile
TypeScript Agent:
FROM node:20-alpine
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
EXPOSE 8003
CMD ["node", "dist/index.js"]
Python Agent:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "agent.py"]
Go Agent:
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o agent main.go
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/agent .
EXPOSE 8002
CMD ["./agent"]
Step 2: Build Image
docker build -t my-agent:latest .
Step 3: Test Locally
docker run -p 8003:8003 \
-e ANTHROPIC_API_KEY=your_key \
my-agent:latest
# Test
curl http://localhost:8003/health
Step 4: Push to Registry
# Docker Hub
docker tag my-agent:latest username/my-agent:latest
docker push username/my-agent:latest
# AWS ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com
docker tag my-agent:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/my-agent:latest
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/my-agent:latest
# Google Container Registry
docker tag my-agent:latest gcr.io/my-project/my-agent:latest
docker push gcr.io/my-project/my-agent:latest
Option 2: Kubernetes
Deploy to Kubernetes for production-grade orchestration.
Deployment YAML
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-agent
labels:
app: my-agent
spec:
replicas: 3
selector:
matchLabels:
app: my-agent
template:
metadata:
labels:
app: my-agent
spec:
containers:
- name: my-agent
image: username/my-agent:latest
ports:
- containerPort: 8003
env:
- name: PORT
value: "8003"
- name: ANTHROPIC_API_KEY
valueFrom:
secretKeyRef:
name: agent-secrets
key: anthropic-api-key
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8003
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8003
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: my-agent
spec:
selector:
app: my-agent
ports:
- protocol: TCP
port: 80
targetPort: 8003
type: LoadBalancer
---
apiVersion: v1
kind: Secret
metadata:
name: agent-secrets
type: Opaque
stringData:
anthropic-api-key: "your_key_here"
Deploy
kubectl apply -f deployment.yaml
# Check status
kubectl get pods
kubectl get services
# Get public URL
kubectl get service my-agent
Option 3: Cloud Platforms
AWS (ECS/Fargate)
# Create ECS cluster
aws ecs create-cluster --cluster-name my-agents
# Create task definition
cat > task-definition.json <<EOF
{
"family": "my-agent",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"containerDefinitions": [
{
"name": "my-agent",
"image": "123456789.dkr.ecr.us-east-1.amazonaws.com/my-agent:latest",
"portMappings": [
{
"containerPort": 8003,
"protocol": "tcp"
}
],
"environment": [
{
"name": "PORT",
"value": "8003"
}
],
"secrets": [
{
"name": "ANTHROPIC_API_KEY",
"valueFrom": "arn:aws:secretsmanager:us-east-1:123456789:secret:agent-keys"
}
]
}
]
}
EOF
aws ecs register-task-definition --cli-input-json file://task-definition.json
# Create service
aws ecs create-service \
--cluster my-agents \
--service-name my-agent \
--task-definition my-agent \
--desired-count 2 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-xxx],securityGroups=[sg-xxx],assignPublicIp=ENABLED}"
Google Cloud Run
# Deploy
gcloud run deploy my-agent \
--image gcr.io/my-project/my-agent:latest \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--port 8003 \
--set-env-vars PORT=8003 \
--set-secrets ANTHROPIC_API_KEY=agent-keys:latest
# Get URL
gcloud run services describe my-agent --region us-central1 --format 'value(status.url)'
Azure Container Apps
# Create container app environment
az containerapp env create \
--name my-agent-env \
--resource-group my-rg \
--location eastus
# Deploy container
az containerapp create \
--name my-agent \
--resource-group my-rg \
--environment my-agent-env \
--image username/my-agent:latest \
--target-port 8003 \
--ingress external \
--min-replicas 1 \
--max-replicas 5 \
--secrets anthropic-key=your_key \
--env-vars PORT=8003 ANTHROPIC_API_KEY=secretref:anthropic-key
# Get URL
az containerapp show \
--name my-agent \
--resource-group my-rg \
--query properties.configuration.ingress.fqdn
Option 4: Self-Hosted
Run on your own infrastructure.
Using Docker Compose
# docker-compose.yml
version: '3.8'
services:
my-agent:
image: username/my-agent:latest
ports:
- "8003:8003"
environment:
- PORT=8003
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8003/health"]
interval: 30s
timeout: 10s
retries: 3
deploy:
replicas: 3
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
docker-compose up -d
Using systemd
# Create service file
sudo tee /etc/systemd/system/my-agent.service > /dev/null <<EOF
[Unit]
Description=My Custom Agent
After=network.target
[Service]
Type=simple
User=agent
WorkingDirectory=/opt/my-agent
Environment="PORT=8003"
Environment="ANTHROPIC_API_KEY=your_key"
ExecStart=/usr/local/bin/node /opt/my-agent/dist/index.js
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Enable and start
sudo systemctl enable my-agent
sudo systemctl start my-agent
# Check status
sudo systemctl status my-agent
Production Checklist
Security
- Use HTTPS (TLS/SSL certificates)
- Store secrets securely (environment variables, secret managers)
- Implement rate limiting
- Add request authentication (API keys, JWT)
- Enable CORS only for necessary origins
- Keep dependencies updated
- Run security scans (npm audit, Snyk)
Performance
- Enable horizontal scaling (multiple instances)
- Implement health checks
- Configure resource limits (CPU, memory)
- Add caching where appropriate
- Optimize Docker image size
- Use connection pooling for databases
- Implement request queuing for high load
Monitoring
- Add logging (structured JSON logs)
- Export metrics (Prometheus format)
- Configure alerts (downtime, errors, high latency)
- Set up APM (Application Performance Monitoring)
- Track error rates and response times
- Monitor resource usage
Reliability
- Implement graceful shutdown
- Add timeout handling
- Configure automatic restarts
- Set up backup instances
- Implement circuit breakers
- Add retry logic with exponential backoff
- Test disaster recovery
Exposing Your Agent
Your agent must be publicly accessible via HTTPS for Mindra Platform to reach it.
Options
1. Public Load Balancer
AWS Application Load Balancer:
aws elbv2 create-load-balancer \
--name my-agent-lb \
--subnets subnet-xxx subnet-yyy \
--security-groups sg-xxx \
--scheme internet-facing
Google Cloud Load Balancer:
gcloud compute forwarding-rules create my-agent-lb \
--global \
--target-http-proxy=my-agent-proxy \
--ports=443
2. Ingress Controller (Kubernetes)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-agent-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- my-agent.example.com
secretName: my-agent-tls
rules:
- host: my-agent.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-agent
port:
number: 80
3. Reverse Proxy (Nginx)
server {
listen 443 ssl http2;
server_name my-agent.example.com;
ssl_certificate /etc/letsencrypt/live/my-agent.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my-agent.example.com/privkey.pem;
location / {
proxy_pass http://localhost:8003;
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_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
}
4. Cloudflare Tunnel
# Install cloudflared
# https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/
# Create tunnel
cloudflared tunnel create my-agent
# Configure tunnel
cat > config.yml <<EOF
tunnel: <tunnel-id>
credentials-file: /path/to/<tunnel-id>.json
ingress:
- hostname: my-agent.example.com
service: http://localhost:8003
- service: http_status:404
EOF
# Run tunnel
cloudflared tunnel run my-agent
Environment Variables
Manage configuration through environment variables:
# Required
PORT=8003 # HTTP port
NODE_ENV=production # Environment
# Optional - API Keys
ANTHROPIC_API_KEY=sk-xxx # If using Claude
OPENAI_API_KEY=sk-xxx # If using OpenAI
# Optional - Database
DATABASE_URL=postgresql://... # If using database
REDIS_URL=redis://... # If using Redis
# Optional - Monitoring
PROMETHEUS_PORT=9090 # Metrics port
LOG_LEVEL=info # Log level
# Optional - Security
API_KEY_SECRET=xxx # For request authentication
CORS_ORIGINS=https://api.mindra.co # CORS allowed origins
Testing Deployment
1. Health Check
curl https://my-agent.example.com/health
Expected:
{
"status": "healthy",
"timestamp": 1699632000
}
2. Info Endpoint
curl https://my-agent.example.com/info
Expected:
{
"id": "my-custom-agent",
"name": "My Custom Agent",
"version": "1.0.0"
}
3. Execute Endpoint
curl -X POST https://my-agent.example.com/execute \
-H "Content-Type: application/json" \
-d '{
"input": {
"prompt": "test query",
"context": {}
},
"metadata": {
"requestId": "test",
"userId": "test",
"timeout": 30000
}
}'
4. Load Test
# Using Apache Bench
ab -n 1000 -c 10 https://my-agent.example.com/health
# Using k6
k6 run load-test.js
Next Steps
Once deployed, register your agent with Mindra Platform:
Support
- Deployment Issues: info@mindra.co
- Infrastructure: info@mindra.co