15 KiB
🚀 AI Dev Factory - Session Continuation Guide
Last Updated: 2024-11-28
Current Phase: Phase 2 - OpenHands Integration (API Mode)
Time to Completion: ~3-4 hours
Next Approach: OpenHands Server API Mode ✅
📊 CURRENT STATUS
✅ What's Working:
- Gitea: https://git.oky.sh (HTTPS, PostgreSQL backend)
- n8n: https://n8n.oky.sh (HTTPS, workflow automation)
- Caddy: Auto SSL with Let's Encrypt
- SSH: n8n → localhost credentials configured
- OpenHands CLI:
/home/bam/.local/bin/openhands(v1.3.0)
⚠️ Current Blocker:
- OpenHands headless mode (Docker) hangs on runtime startup
- Solution: Switch to OpenHands Server API mode
🎯 Goal:
Create automated workflow: Gitea push → n8n → OpenHands API → Build/Test
🔧 SYSTEM CONFIGURATION
VM Details:
Hostname: ai-dev-node
IP: 10.10.10.11
User: bam
CPU: 8 vCPU
RAM: 24GB (optimized from 40GB)
OS: Ubuntu 22.04
Services Running:
docker compose ps
# Expected output:
# - caddy (ports 80, 443)
# - gitea (port 3333 internal, 2229 SSH)
# - n8n (port 5678 internal)
# - postgres (port 5432 internal)
Important Directories:
/home/bam/services-stack/ # Docker services (Gitea, n8n, Caddy)
/home/bam/.local/bin/ # OpenHands CLI
/home/bam/.openhands/ # OpenHands config & sessions
├── agent_settings.json # Agent configuration
├── cache/ # Model cache
├── conversations/ # Chat history
├── sessions/ # Active sessions data
└── settings.json # LLM & server settings
/home/bam/workspace/ # Default workspace for builds
/home/bam/.ssh/n8n_key # SSH key for n8n automation
API Keys Location:
/home/bam/openhands/.env
# Contains:
# MINIMAX_API_KEY=xxx (Primary LLM)
# DEEPSEEK_API_KEY=xxx (Backup LLM)
# OPENAI_API_KEY=xxx (Optional 2nd backup)
🎯 NEXT STEPS: OpenHands Server API Setup
Step 1: Start OpenHands in Server Mode (15 min)
Goal: Run OpenHands as persistent HTTP API service
OpenHands serve uses port 3000 by default (cannot be changed in current version)
# Test server startup
/home/bam/.local/bin/openhands serve
# Expected: Server starts, listens on http://localhost:3000
Create systemd service for persistence:
sudo nano /etc/systemd/system/openhands.service
# Paste:
[Unit]
Description=OpenHands Server
After=network.target docker.service
Requires=docker.service
[Service]
Type=simple
User=bam
WorkingDirectory=/home/bam
Environment="PATH=/home/bam/.local/bin:/usr/local/bin:/usr/bin:/bin"
EnvironmentFile=/home/bam/openhands/.env
ExecStart=/home/bam/.local/bin/openhands serve
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
# Save and enable:
sudo systemctl daemon-reload
sudo systemctl enable openhands.service
sudo systemctl start openhands.service
sudo systemctl status openhands.service
Verify:
# Check if running
curl http://localhost:3000/
# Check logs
sudo journalctl -u openhands.service -f
Step 1.5: Configure Backup LLM Models (10 min)
Goal: Setup DeepSeek V2 as fallback when MiniMax fails
OpenHands can use multiple LLM providers with automatic fallback.
Check current config:
cat /home/bam/.openhands/settings.json
Update settings to include backup models:
nano /home/bam/.openhands/settings.json
Add LLM configuration:
{
"LLM_MODEL": "openai/MiniMax-M2",
"LLM_API_KEY": "${MINIMAX_API_KEY}",
"LLM_BASE_URL": "https://api.minimax.io/v1",
"LLM_FALLBACK_MODELS": [
{
"model": "deepseek/deepseek-coder-v2",
"api_key": "${DEEPSEEK_API_KEY}",
"base_url": "https://api.deepseek.com/v1"
},
{
"model": "gpt-4o",
"api_key": "${OPENAI_API_KEY}",
"base_url": "https://api.openai.com/v1"
}
],
"LLM_TIMEOUT": 60,
"LLM_RETRY_COUNT": 3
}
Verify API keys are loaded:
cat /home/bam/openhands/.env
# Should contain:
# MINIMAX_API_KEY=xxx
# DEEPSEEK_API_KEY=xxx
# OPENAI_API_KEY=xxx (optional backup)
Note: Exact config format may vary. Check OpenHands documentation or existing settings.json structure. The systemd service will load these env vars automatically.
Restart OpenHands to apply:
sudo systemctl restart openhands.service
sudo systemctl status openhands.service
Step 2: Discover API Endpoints (15 min)
Goal: Find available API endpoints for triggering tasks
Check OpenHands documentation:
# Look for API docs in help
/home/bam/.local/bin/openhands serve --help
# Or check if web UI exposes API docs:
# Visit: http://10.10.10.11:3000/docs
# Or: http://10.10.10.11:3000/api/docs
Expected endpoints (typical OpenHands API):
POST /api/sessions # Create new session
POST /api/sessions/{id}/messages # Send task message
GET /api/sessions/{id} # Get session status
GET /api/sessions/{id}/events # Get execution events
Test manually:
# Create session
curl -X POST http://localhost:3000/api/sessions \
-H "Content-Type: application/json" \
-d '{
"workspace": "/home/bam/workspace",
"model": "openai/MiniMax-M2",
"api_key": "your_minimax_key"
}'
# Response should include session_id
If API endpoints unclear:
- Check OpenHands GitHub docs
- Inspect network requests in web UI (browser DevTools)
- Look for OpenAPI/Swagger spec
Step 3: Create n8n → OpenHands API Workflow (45 min)
Goal: Build n8n workflow that calls OpenHands API
Workflow Design:
[1] Manual Trigger (for testing)
↓
[2] HTTP Request - Create Session
→ POST /api/sessions
→ Save session_id
↓
[3] HTTP Request - Send Task
→ POST /api/sessions/{session_id}/messages
→ Body: { "task": "Create file test.txt" }
↓
[4] Wait 5 seconds
↓
[5] HTTP Request - Get Status (loop until done)
→ GET /api/sessions/{session_id}
→ Check if "status": "completed"
↓
[6] If Node - Check Success
├─ TRUE → [7] Get Results
└─ FALSE → [8] Error Handler
n8n Configuration:
Node 1: Manual Trigger
- Just add it, no config
Node 2: HTTP Request - Create Session
Method: POST
URL: http://127.0.0.1:3000/api/sessions
Headers:
Content-Type: application/json
Body:
{
"workspace": "/home/bam/workspace",
"model": "openai/MiniMax-M2",
"api_key": "{{$env.MINIMAX_API_KEY}}"
}
Options:
Response Format: JSON
Node 3: HTTP Request - Send Task
Method: POST
URL: http://127.0.0.1:3000/api/sessions/{{ $json.session_id }}/messages
Body:
{
"task": "Create a file named test.txt with content: Hello from n8n API!"
}
Node 4: Wait Node
Time: 5 seconds
Node 5: HTTP Request - Get Status
Method: GET
URL: http://127.0.0.1:3000/api/sessions/{{ $node["HTTP Request"].json.session_id }}
# May need to loop this until status is "completed"
# Use n8n Loop node if available
Node 6: SSH - Verify File Created
Credentials: ai-dev-localhost
Command: cat /home/bam/workspace/test.txt
Test Workflow:
- Execute manually
- Check each node output
- Verify file created in /home/bam/workspace/
Step 4: Gitea Webhook Integration (30 min)
Goal: Trigger n8n workflow on git push
In Gitea (https://git.oky.sh):
- Create test repository:
test-project - Go to Settings → Webhooks → Add Webhook → Gitea
- Configure:
Target URL: https://n8n.oky.sh/webhook/gitea-push HTTP Method: POST Content Type: application/json Secret: [generate random string] Trigger On: Push events Active: ✓ - Test webhook
In n8n:
-
Replace Manual Trigger with Webhook Trigger
-
Configure:
Webhook URLs: Production: https://n8n.oky.sh/webhook/gitea-push HTTP Method: POST Authentication: Header Auth Name: X-Gitea-Signature Value: [your secret from Gitea] Response: Mode: Last Node Code: 200 -
Extract data:
Repository: {{ $json.repository.full_name }} Commit: {{ $json.commits[0].message }} Branch: {{ $json.ref }} -
Pass to OpenHands:
Task: "Build and test project {{ $json.repository.full_name }} on commit {{ $json.after }}" Workspace: "/home/bam/workspace/{{ $json.repository.name }}"
Test:
# In test-project repo
echo "Test" > README.md
git add .
git commit -m "Test webhook"
git push origin main
# Check n8n workflow executes
# Check OpenHands builds project
Step 5: Build Workflow with Retry Logic (1-2 hours)
Goal: Production-ready workflow with error handling
Enhanced Workflow:
[1] Webhook Trigger (Gitea push)
↓
[2] Extract Repo Info
↓
[3] Clone/Update Repository (SSH)
→ git clone or git pull
↓
[4] Create OpenHands Session
↓
[5] Send Build Task
→ Task: "Run npm install, npm test, npm build"
↓
[6] Poll Status (Loop)
→ Check every 10s
→ Timeout: 5 minutes
↓
[7] If Node - Build Success?
├─ YES → [8] Success Notification
│ └─ Update commit status ✅
│
└─ NO → [9] Get Error Details
↓
[10] Send Feedback to OpenHands
→ "Build failed with: {error}, please fix"
↓
[11] Retry Counter (max 3)
├─ < 3 → Back to [5]
└─ ≥ 3 → [12] Final Failure Notification
Key Components:
Clone Repository Node (SSH):
cd /home/bam/workspace
if [ -d "{{ $json.repo_name }}" ]; then
cd {{ $json.repo_name }} && git pull
else
git clone {{ $json.clone_url }}
fi
Build Task (to OpenHands):
{
"task": "Navigate to /home/bam/workspace/{{ $json.repo_name }} and run: npm install && npm test && npm build. Report any errors.",
"workspace": "/home/bam/workspace/{{ $json.repo_name }}",
"max_iterations": 20
}
Retry Logic (n8n Function Node):
// Get retry count from workflow static data
const retries = $workflow.staticData.retry_count || 0;
if (retries >= 3) {
return {
action: 'fail',
message: 'Max retries exceeded'
};
}
// Increment retry
$workflow.staticData.retry_count = retries + 1;
return {
action: 'retry',
attempt: retries + 1,
feedback: $json.error_message
};
Success Notification (HTTP to Gitea API):
POST https://git.oky.sh/api/v1/repos/{{ $json.repo }}/statuses/{{ $json.commit_sha }}
Authorization: token YOUR_GITEA_TOKEN
Body:
{
"state": "success",
"description": "Build passed",
"context": "openhands/build"
}
🧪 TESTING CHECKLIST
Integration Tests:
- OpenHands server starts and responds
- API creates sessions successfully
- API accepts and executes tasks
- Tasks complete and return results
- n8n can call all API endpoints
- Webhook receives Gitea events
- Repository clones correctly
- Build task executes
- Success path works end-to-end
- Failure triggers retry
- Max retries stops infinite loop
- Notifications sent correctly
Error Scenarios:
- Invalid API request
- OpenHands timeout
- Build failure (syntax error)
- Network issues
- Git clone failure
- Webhook auth failure
📋 TROUBLESHOOTING
OpenHands Server Won't Start:
# Check if port in use
sudo netstat -tulpn | grep 3000
# Check OpenHands logs
sudo journalctl -u openhands.service -n 50
# Try manual start to see errors
/home/bam/.local/bin/openhands serve
API Endpoints Not Found:
# Check OpenHands version
/home/bam/.local/bin/openhands --version
# May need to update
pipx upgrade openhands-ai
# Or reinstall
pipx uninstall openhands-ai
pipx install openhands-ai
n8n Cannot Reach OpenHands:
# Test from n8n container
docker exec -it n8n curl http://host.docker.internal:3000
# If fails, check if n8n has host.docker.internal access
# May need to add to docker-compose:
extra_hosts:
- "host.docker.internal:host-gateway"
Webhook Not Triggering:
# Check n8n webhook URL is accessible
curl https://n8n.oky.sh/webhook/gitea-push
# Check Gitea webhook logs:
# Gitea UI → Repository → Settings → Webhooks → Recent Deliveries
# Test with manual webhook trigger in Gitea UI
🎯 SUCCESS CRITERIA
Phase 2 Complete When:
- ✅ OpenHands server running persistently
- ✅ n8n can create sessions via API
- ✅ Simple test task executes successfully
- ✅ Gitea webhook triggers n8n workflow
- ✅ End-to-end: Push → Build → Success/Fail
Phase 3 Complete When:
- ✅ Retry logic working (max 3 attempts)
- ✅ Error feedback to OpenHands
- ✅ Commit status updates in Gitea
- ✅ Tested with real project build
📚 REFERENCE COMMANDS
Quick Status Check:
# All services status
cd /home/bam/services-stack && docker compose ps
# OpenHands server
sudo systemctl status openhands.service
# Check OpenHands API
curl http://localhost:3000/
# n8n workflows
curl -u admin:password https://n8n.oky.sh/api/v1/workflows
Restart Services:
# Restart all Docker services
cd /home/bam/services-stack
docker compose restart
# Restart OpenHands only
sudo systemctl restart openhands.service
# Restart n8n only
docker compose restart n8n
View Logs:
# OpenHands logs
sudo journalctl -u openhands.service -f
# n8n logs
docker logs -f n8n
# Caddy logs
docker logs -f caddy
# Gitea logs
docker logs -f gitea
🔐 CREDENTIALS REFERENCE
n8n Login:
- URL: https://n8n.oky.sh
- User: admin (owner account)
- Password: [set during setup]
Gitea Login:
- URL: https://git.oky.sh
- User: [admin account]
- Password: [set during setup]
API Keys:
- MiniMax:
/home/bam/openhands/.env - SSH Key:
/home/bam/.ssh/n8n_key
⏱️ ESTIMATED TIME BREAKDOWN
- Step 1: OpenHands Server Setup: 15 min
- Step 1.5: Backup LLM Configuration: 10 min
- Step 2: API Discovery: 15 min
- Step 3: n8n API Workflow: 45 min
- Step 4: Gitea Webhook: 30 min
- Step 5: Retry Logic: 1-2 hours
- Testing & Debugging: 30 min
Total: 3-4 hours
🚀 READY TO START?
Pre-flight Checklist:
- All services running (docker compose ps)
- Can access Gitea (https://git.oky.sh)
- Can access n8n (https://n8n.oky.sh)
- SSH to ai-dev-node working
- Fresh terminal session
First Command:
/home/bam/.local/bin/openhands serve
If starts successfully → proceed to Step 1 systemd service!
If error → investigate OpenHands CLI installation
📝 NOTES
- Port 3000: OpenHands serve uses port 3000 (not configurable in CLI v1.3.0)
- Note: This conflicts with Gitea's internal port 3000, but OK since Gitea exposed as 3333
- OpenHands API: http://localhost:3000 (localhost only)
- n8n will access via http://host.docker.internal:3000 from container
- API Mode vs Headless: API is more reliable for automation
- Persistence: systemd service ensures OpenHands survives reboots
- Security: OpenHands API on localhost only (127.0.0.1)
- Scaling: Can add more OpenHands instances later
- LLM Fallback: MiniMax M2 → DeepSeek V2 → OpenAI GPT-4o (if configured)
Good luck! 🎯