Remote Execution
Run agentful agents on remote servers through a secure HTTP API using agentful serve.
Default port: 3000 (configurable with --port flag)
Quick Start
# Start server with Tailscale (recommended) - default port 3000
agentful serve
# Start server with HMAC authentication on custom port
agentful serve --auth=hmac --secret=$SECRET --https --cert=cert.pem --key=key.pem --port=8080
# Start server for local SSH tunnel access
agentful serve --auth=noneAuthentication Modes
Tailscale (Recommended)
Zero-configuration networking with WireGuard encryption. Perfect for free VPS deployments.
Benefits:- Network-level security (no application auth needed)
- Works behind NAT/firewalls automatically
- Free tier supports 100 devices
- Zero-trust architecture
# Install Tailscale on server
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
# Start agentful server
agentful serve
# Trigger from any device on your tailnet
curl http://server-name:3000/trigger \
-H "Content-Type: application/json" \
-d '{"agent":"backend","task":"Review API changes"}'HMAC Authentication
Signature-based authentication with replay protection. Use for public endpoints and CI/CD integration.
Features:- HMAC-SHA256 signatures
- 5-minute replay protection window
- Rate limiting (60 req/min per IP)
- Requires HTTPS in production
# Generate strong secret
export SECRET=$(openssl rand -hex 32)
# Start server with HTTPS
agentful serve \
--auth=hmac \
--secret=$SECRET \
--https \
--cert=/etc/letsencrypt/live/example.com/fullchain.pem \
--key=/etc/letsencrypt/live/example.com/privkey.pemimport crypto from 'crypto';
const secret = process.env.AGENTFUL_SECRET;
const body = JSON.stringify({
agent: 'backend',
task: 'Implement user authentication'
});
// Generate timestamp
const timestamp = Date.now().toString();
// Generate HMAC signature
const signature = crypto
.createHmac('sha256', secret)
.update(timestamp + body)
.digest('hex');
// Make request
const response = await fetch('https://example.com:3000/trigger', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Agentful-Signature': signature,
'X-Agentful-Timestamp': timestamp,
},
body,
});SSH Tunnel
Localhost-only access for traditional SSH tunnel setups.
Setup:# On server: start server bound to localhost only
agentful serve --auth=none
# On client: create SSH tunnel
ssh -L 3000:localhost:3000 user@server
# Trigger from local machine
curl http://localhost:3000/trigger \
-H "Content-Type: application/json" \
-d '{"agent":"reviewer","task":"Review code quality"}'API Endpoints
POST /trigger
Execute an agent with a task.
Request:{
"agent": "backend",
"task": "Implement user authentication",
"timeout": 600000,
"env": {
"NODE_ENV": "production"
}
}{
"executionId": "550e8400-e29b-41d4-a716-446655440000",
"state": "pending",
"agent": "backend",
"task": "Implement user authentication"
}GET /status/
Check execution status and retrieve output.
Response:{
"id": "550e8400-e29b-41d4-a716-446655440000",
"agent": "backend",
"task": "Implement user authentication",
"state": "completed",
"startTime": 1737536400000,
"endTime": 1737536723000,
"duration": 323000,
"output": "✅ Implemented JWT authentication...",
"exitCode": 0,
"error": null,
"metadata": {
"name": "backend",
"description": "Backend development specialist"
}
}State values: pending, running, completed, failed
GET /agents
List all available agents.
Response:{
"agents": [
"backend",
"frontend",
"tester",
"reviewer",
"fixer"
]
}GET /executions
List recent executions with optional filtering.
Query parameters:agent- Filter by agent namestate- Filter by statelimit- Max results (default: 100)
{
"executions": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"agent": "backend",
"task": "Implement user authentication",
"state": "completed",
"startTime": 1737536400000,
"endTime": 1737536723000,
"duration": 323000,
"exitCode": 0
}
],
"count": 1
}GET /health
Health check endpoint (no authentication required).
Response:{
"status": "healthy",
"uptime": 3600,
"version": "1.0.0"
}Running in Background
Using Process Managers (Recommended)
For production deployments, use a process manager like systemd or PM2 instead of the --daemon flag.
systemd (Linux)
# Create systemd service file
sudo tee /etc/systemd/system/agentful.service > /dev/null <<EOF
[Unit]
Description=agentful Remote Execution Server
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/project
ExecStart=/usr/bin/npx @itz4blitz/agentful serve --auth=tailscale
Restart=on-failure
RestartSec=10
StandardOutput=append:/var/log/agentful/server.log
StandardError=append:/var/log/agentful/server.err.log
[Install]
WantedBy=multi-user.target
EOF
# Create log directory
sudo mkdir -p /var/log/agentful
sudo chown ubuntu:ubuntu /var/log/agentful
# Start service
sudo systemctl daemon-reload
sudo systemctl enable agentful
sudo systemctl start agentful
# Check status
sudo systemctl status agentful
sudo journalctl -u agentful -fPM2 (Cross-platform)
# Install PM2
npm install -g pm2
# Start server
pm2 start "npx @itz4blitz/agentful serve --auth=tailscale" --name agentful
# Save process list for auto-restart
pm2 save
pm2 startup
# Monitor
pm2 status
pm2 logs agentful
pm2 monit
# Stop/restart
pm2 stop agentful
pm2 restart agentfulManual Background Execution
If you don't have a process manager, use nohup:
# Start server in background
nohup agentful serve --auth=tailscale > .agentful/server.log 2>&1 &
# Save PID for later
echo $! > .agentful/server.pid
# Check if running
ps aux | grep "$(cat .agentful/server.pid)"
# View logs
tail -f .agentful/server.log
# Stop server
kill $(cat .agentful/server.pid)
rm .agentful/server.pidNote: The --daemon flag is currently not supported due to platform-specific process detachment issues. Use one of the methods above instead.
Deployment Examples
Oracle Cloud Free Tier + Tailscale
Oracle offers a generous free tier with 4 ARM cores and 24GB RAM forever.
# 1. Create Oracle Cloud VM
# - ARM Ampere A1 (4 cores, 24GB RAM)
# - Ubuntu 22.04 LTS
# 2. Install dependencies
sudo apt update && sudo apt upgrade -y
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs git
# 3. Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
# 4. Install agentful
npm install -g @itz4blitz/agentful
# 5. Clone your project
git clone https://github.com/yourname/project.git
cd project
# 6. Create systemd service
sudo tee /etc/systemd/system/agentful.service > /dev/null <<EOF
[Unit]
Description=agentful Remote Execution Server
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/project
ExecStart=/usr/bin/npx @itz4blitz/agentful serve
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# 7. Start service
sudo systemctl daemon-reload
sudo systemctl enable agentful
sudo systemctl start agentful
# 8. Check status
sudo systemctl status agentful
sudo journalctl -u agentful -fHMAC with Let's Encrypt SSL
# 1. Install Certbot
sudo apt install -y certbot
# 2. Get SSL certificate
sudo certbot certonly --standalone -d yourdomain.com
# 3. Create systemd service with HMAC
sudo tee /etc/systemd/system/agentful.service > /dev/null <<EOF
[Unit]
Description=agentful Remote Execution Server
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/project
Environment="AGENTFUL_SECRET=$(openssl rand -hex 32)"
ExecStart=/usr/bin/npx @itz4blitz/agentful serve \\
--auth=hmac \\
--secret=\${AGENTFUL_SECRET} \\
--https \\
--cert=/etc/letsencrypt/live/yourdomain.com/fullchain.pem \\
--key=/etc/letsencrypt/live/yourdomain.com/privkey.pem
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# 4. Start service
sudo systemctl daemon-reload
sudo systemctl enable agentful
sudo systemctl start agentfulSecurity Considerations
Input Validation
All inputs are validated and sanitized:
- Agent names: Alphanumeric, hyphens, underscores only
- Task descriptions: Max 10KB, no shell metacharacters
- Request bodies: Max 10MB
- Output storage: Max 1MB per execution
- Environment variables: Whitelist only (
NODE_ENV,DEBUG,LOG_LEVEL)
Rate Limiting
Default limits:
- 60 requests per minute per IP
- Returns
429 Too Many RequestswithRetry-Afterheader
Replay Protection
HMAC mode uses timestamp-based replay protection:
- Requests older than 5 minutes are rejected
- Signature cache limited to 10,000 entries
- LRU eviction when cache full
Secret Requirements
HMAC secrets must be:
- Minimum 32 characters (256 bits)
- Generated with cryptographically secure random (e.g.,
openssl rand -hex 32)
CORS Configuration
CORS is disabled by default (same-origin only). Enable with:
agentful serve --auth=hmac --cors-origin=https://app.example.comMonitoring
Health Checks
# Check server health
curl http://localhost:3000/health
# Response
{
"status": "healthy",
"uptime": 3600,
"version": "1.0.0"
}Logs
Server logs include:
- Request authentication results
- Execution start/completion
- Error details
- Rate limit violations
# View logs with systemd
sudo journalctl -u agentful -f
# View logs in PM2
pm2 logs agentfulMetrics
Track key metrics:
- Execution count and duration
- Success/failure rates
- Rate limit hits
- Memory usage
Troubleshooting
"Invalid agent name" error
Agent names must match /^[a-zA-Z0-9_-]+$/. Check that:
- Agent file exists in
.claude/agents/ - Name contains only alphanumeric, hyphens, underscores
"HMAC signature verification failed"
Common causes:
- Clock skew (timestamp >5 minutes old)
- Wrong secret
- Signature calculated incorrectly
- Body modified after signature generated
"Rate limit exceeded"
Server returns 429 Too Many Requests. Wait for Retry-After seconds or implement backoff.
Execution timeouts
Default timeout is 10 minutes. Increase with timeout parameter:
{
"agent": "backend",
"task": "Long-running task",
"timeout": 1800000
}Client Usage
Once your server is running, use the agentful remote CLI to trigger executions from anywhere.
Configure Remote
# Add a remote server
agentful remote add prod http://my-server:3000
# With HMAC authentication
agentful remote add prod https://my-server:3000 --auth=hmac --secret=$SECRET
# List configured remotes
agentful remote listExecute Agents
# Trigger execution
agentful remote exec backend "Fix memory leak" --remote=prod
# With live output (polls until complete)
agentful remote exec reviewer "Review PR #123" --remote=prod --follow
# Check status
agentful remote status abc123 --remote=prod
# List available agents
agentful remote agents --remote=prod
# List recent executions
agentful remote executions --remote=prod --state=completed --limit=10Scheduled Execution (Cron)
Run agents on a schedule using cron or systemd timers.
Cron Examples
# Edit crontab
crontab -e
# Run nightly validation at 2 AM
0 2 * * * agentful remote exec reviewer "Run nightly validation" --remote=prod
# Security audit every Sunday at 3 AM
0 3 * * 0 agentful remote exec reviewer "Security audit" --remote=prod
# Daily backup at midnight
0 0 * * * agentful remote exec backend "Backup database" --remote=prod
# Hourly health check
0 * * * * agentful remote health prod || echo "Server down!" | mail -s "Alert" admin@example.comSystemd Timer
For more control, use systemd timers:
# /etc/systemd/system/agentful-nightly.service
[Unit]
Description=Agentful Nightly Validation
[Service]
Type=oneshot
User=ubuntu
ExecStart=/usr/bin/agentful remote exec reviewer "Run nightly validation" --remote=prod --follow# /etc/systemd/system/agentful-nightly.timer
[Unit]
Description=Run Agentful Nightly Validation
[Timer]
OnCalendar=daily
OnCalendar=02:00
Persistent=true
[Install]
WantedBy=timers.target# Enable and start timer
sudo systemctl daemon-reload
sudo systemctl enable agentful-nightly.timer
sudo systemctl start agentful-nightly.timer
# Check timer status
sudo systemctl list-timers agentful-nightly.timerCI/CD Integration
Trigger remote agents from CI/CD pipelines.
GitHub Actions
name: Code Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
steps:
- name: Trigger agentful reviewer
run: |
npm install -g @itz4blitz/agentful
agentful remote add ci ${{ secrets.AGENTFUL_URL }} \
--auth=hmac \
--secret=${{ secrets.AGENTFUL_SECRET }}
agentful remote exec reviewer "Review PR #${{ github.event.pull_request.number }}" \
--remote=ci \
--followGitLab CI
code_review:
stage: test
script:
- npm install -g @itz4blitz/agentful
- agentful remote add ci $AGENTFUL_URL --auth=hmac --secret=$AGENTFUL_SECRET
- agentful remote exec reviewer "Review MR !$CI_MERGE_REQUEST_IID" --remote=ci --follow
only:
- merge_requestscurl (No Dependencies)
#!/bin/bash
# trigger-agent.sh
SERVER="https://my-server:3000"
SECRET="your-hmac-secret"
AGENT="$1"
TASK="$2"
# Generate HMAC signature
TIMESTAMP=$(date +%s000)
BODY='{"agent":"'$AGENT'","task":"'$TASK'"}'
SIGNATURE=$(echo -n "${TIMESTAMP}${BODY}" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)
# Trigger execution
RESPONSE=$(curl -s -X POST "$SERVER/trigger" \
-H "Content-Type: application/json" \
-H "X-Agentful-Signature: $SIGNATURE" \
-H "X-Agentful-Timestamp: $TIMESTAMP" \
-d "$BODY")
EXEC_ID=$(echo "$RESPONSE" | jq -r '.executionId')
echo "Execution started: $EXEC_ID"
# Poll for completion
while true; do
sleep 5
STATUS=$(curl -s "$SERVER/status/$EXEC_ID" \
-H "X-Agentful-Signature: $(echo -n "${TIMESTAMP}" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)" \
-H "X-Agentful-Timestamp: $TIMESTAMP")
STATE=$(echo "$STATUS" | jq -r '.state')
if [ "$STATE" = "completed" ]; then
echo "✓ Execution completed"
echo "$STATUS" | jq -r '.output'
exit 0
elif [ "$STATE" = "failed" ]; then
echo "✗ Execution failed"
echo "$STATUS" | jq -r '.error'
exit 1
fi
doneNext Steps
- CI/CD Integration - Use agentful in GitHub Actions, GitLab CI
- Commands - Learn about agentful slash commands
- Agents - Understand specialized agent roles