Add fixed workflow with explicit agent start step
The original workflow was missing POST /api/conversations/{id}/start
which caused conversations to hang in STARTING state forever.
This fixed version:
- Explicitly starts the agent loop after creation
- Better retry logic (15 retries = 4 min timeout)
- Clearer node names with numbering
- Improved result analysis
This commit is contained in:
parent
e58778a4bb
commit
d74c1a4726
|
|
@ -0,0 +1,302 @@
|
||||||
|
{
|
||||||
|
"name": "OpenHands API Test - Fixed",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"id": "manual-trigger",
|
||||||
|
"name": "Manual Trigger",
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [240, 300]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"url": "http://172.18.0.1:3000/api/conversations",
|
||||||
|
"method": "POST",
|
||||||
|
"sendBody": true,
|
||||||
|
"bodyParameters": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "initial_user_msg",
|
||||||
|
"value": "Create a file named hello.txt with content: Hello from n8n! This is a test."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"response": {
|
||||||
|
"response": {
|
||||||
|
"responseFormat": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": "create-conversation",
|
||||||
|
"name": "1. Create Conversation",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 4.2,
|
||||||
|
"position": [460, 300]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"url": "=http://172.18.0.1:3000/api/conversations/{{ $json.conversation_id }}/start",
|
||||||
|
"method": "POST",
|
||||||
|
"sendBody": true,
|
||||||
|
"specifyBody": "json",
|
||||||
|
"jsonBody": "={}",
|
||||||
|
"options": {
|
||||||
|
"response": {
|
||||||
|
"response": {
|
||||||
|
"responseFormat": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": "start-conversation",
|
||||||
|
"name": "2. Start Agent Loop",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 4.2,
|
||||||
|
"position": [680, 300]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"amount": 10,
|
||||||
|
"unit": "seconds"
|
||||||
|
},
|
||||||
|
"id": "wait-10s",
|
||||||
|
"name": "3. Wait 10s",
|
||||||
|
"type": "n8n-nodes-base.wait",
|
||||||
|
"typeVersion": 1.1,
|
||||||
|
"position": [900, 300],
|
||||||
|
"webhookId": "wait-10s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"url": "=http://172.18.0.1:3000/api/conversations/{{ $('1. Create Conversation').item.json.conversation_id }}",
|
||||||
|
"method": "GET",
|
||||||
|
"options": {
|
||||||
|
"response": {
|
||||||
|
"response": {
|
||||||
|
"responseFormat": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": "get-status",
|
||||||
|
"name": "4. Check Status",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 4.2,
|
||||||
|
"position": [1120, 300]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"conditions": {
|
||||||
|
"options": {
|
||||||
|
"combineOperation": "any"
|
||||||
|
},
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"id": "status-running",
|
||||||
|
"leftValue": "={{ $json.status }}",
|
||||||
|
"rightValue": "RUNNING",
|
||||||
|
"operator": {
|
||||||
|
"type": "string",
|
||||||
|
"operation": "equals"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "status-stopped",
|
||||||
|
"leftValue": "={{ $json.status }}",
|
||||||
|
"rightValue": "STOPPED",
|
||||||
|
"operator": {
|
||||||
|
"type": "string",
|
||||||
|
"operation": "equals"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "status-awaiting",
|
||||||
|
"leftValue": "={{ $json.status }}",
|
||||||
|
"rightValue": "AWAITING_USER_INPUT",
|
||||||
|
"operator": {
|
||||||
|
"type": "string",
|
||||||
|
"operation": "equals"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "check-ready",
|
||||||
|
"name": "5. Is Ready?",
|
||||||
|
"type": "n8n-nodes-base.if",
|
||||||
|
"typeVersion": 2,
|
||||||
|
"position": [1340, 300]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"amount": 15,
|
||||||
|
"unit": "seconds"
|
||||||
|
},
|
||||||
|
"id": "wait-retry",
|
||||||
|
"name": "Wait 15s Retry",
|
||||||
|
"type": "n8n-nodes-base.wait",
|
||||||
|
"typeVersion": 1.1,
|
||||||
|
"position": [1560, 180],
|
||||||
|
"webhookId": "wait-retry"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"jsCode": "// Retry counter with max retries\nconst retries = $workflow.staticData.retries || 0;\nconst maxRetries = 15; // 15 * 15s = ~4 minutes\n\nif (retries >= maxRetries) {\n throw new Error('Timeout: Agent did not start within 4 minutes');\n}\n\n$workflow.staticData.retries = retries + 1;\n\nconst convId = $('1. Create Conversation').item.json.conversation_id;\n\nreturn {\n conversation_id: convId,\n retry_count: retries + 1\n};"
|
||||||
|
},
|
||||||
|
"id": "retry-counter",
|
||||||
|
"name": "Retry Counter",
|
||||||
|
"type": "n8n-nodes-base.code",
|
||||||
|
"typeVersion": 2,
|
||||||
|
"position": [1780, 180]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"url": "=http://172.18.0.1:3000/api/conversations/{{ $('1. Create Conversation').item.json.conversation_id }}/events",
|
||||||
|
"method": "GET",
|
||||||
|
"options": {
|
||||||
|
"response": {
|
||||||
|
"response": {
|
||||||
|
"responseFormat": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": "get-events",
|
||||||
|
"name": "6. Get Events",
|
||||||
|
"type": "n8n-nodes-base.httpRequest",
|
||||||
|
"typeVersion": 4.2,
|
||||||
|
"position": [1560, 420]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"jsCode": "// Extract conversation results\nconst events = $input.item.json.events || [];\nconst convId = $('1. Create Conversation').item.json.conversation_id;\nconst status = $('4. Check Status').item.json.status;\n\n// Check for file creation\nconst fileCreated = events.some(e => \n e.message?.includes('hello.txt') || \n e.observation?.includes('hello.txt')\n);\n\n// Get last few events\nconst recentEvents = events.slice(-5).map(e => ({\n timestamp: e.timestamp,\n source: e.source,\n observation: e.observation,\n message: e.message?.substring(0, 100)\n}));\n\nreturn {\n conversation_id: convId,\n status: status,\n total_events: events.length,\n file_created: fileCreated,\n recent_events: recentEvents,\n success: fileCreated && (status === 'STOPPED' || status === 'AWAITING_USER_INPUT')\n};"
|
||||||
|
},
|
||||||
|
"id": "analyze-results",
|
||||||
|
"name": "7. Analyze Results",
|
||||||
|
"type": "n8n-nodes-base.code",
|
||||||
|
"typeVersion": 2,
|
||||||
|
"position": [1780, 420]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"Manual Trigger": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "1. Create Conversation",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"1. Create Conversation": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "2. Start Agent Loop",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"2. Start Agent Loop": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "3. Wait 10s",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"3. Wait 10s": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "4. Check Status",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"4. Check Status": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "5. Is Ready?",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"5. Is Ready?": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "6. Get Events",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Wait 15s Retry",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Wait 15s Retry": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Retry Counter",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Retry Counter": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "4. Check Status",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"6. Get Events": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "7. Analyze Results",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {},
|
||||||
|
"settings": {
|
||||||
|
"executionOrder": "v1"
|
||||||
|
},
|
||||||
|
"staticData": null,
|
||||||
|
"tags": [],
|
||||||
|
"triggerCount": 0,
|
||||||
|
"updatedAt": "2025-11-29T20:30:00.000Z",
|
||||||
|
"versionId": "1"
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue