Skip to content

Fix: N8nWorkflowTool.run() uses non-existent /api/v1/workflows/{id}/execute endpoint (always 405) #22

@MervinPraison

Description

@MervinPraison

Overview

N8nWorkflowTool.run() calls POST /api/v1/workflows/{id}/execute to execute n8n workflows. This endpoint does not exist on n8n's Public API and always returns HTTP 405 Method Not Allowed, making the tool fundamentally non-functional against a real n8n instance.

Reproduction

Setup

docker run -d --name n8n -p 5678:5678 docker.n8n.io/n8nio/n8n
# Complete owner setup, create API key with workflow:* scopes
export N8N_API_KEY="..."
export N8N_URL="http://localhost:5678"

Test

from praisonai_tools.n8n import N8nWorkflowTool

tool = N8nWorkflowTool()
# list workflows works (GET /api/v1/workflows is a real endpoint)
wfs = tool.list_workflows()
wf_id = wfs["data"][0]["id"]

# But execute fails
result = tool.run(workflow_id=wf_id, input_data={"query": "test"}, wait_for_completion=False)
# ERROR: n8n API error: 405 - {"message":"POST method not allowed"}
# Returns: {'error': 'HTTP 405: {"message":"POST method not allowed"}'}

Root cause

Reading praisonai_tools/n8n/n8n_workflow.py:~95:

response = self._client.post(
    f"{self.n8n_url}/api/v1/workflows/{workflow_id}/execute",  # ← does not exist
    json=input_data,
    ...
)

n8n's Public API reference lists only these workflow operations: CREATE, READ, LIST, UPDATE, DELETE, ACTIVATE, DEACTIVATE, TRANSFER. There is no execution endpoint in the public API.

See: https://docs.n8n.io/api/api-reference/

The correct way to trigger an n8n workflow externally is:

  1. Make sure the workflow starts with a Webhook trigger node
  2. POST to the webhook URL: http://<n8n>/webhook/<path>

Affected File

File Purpose
/Users/praison/PraisonAI-tools/praisonai_tools/n8n/n8n_workflow.py N8nWorkflowTool

Proposed Fix

Option A — Webhook execution (recommended)

Change N8nWorkflowTool.run() to fetch the workflow, find its webhook trigger, and POST to the webhook URL:

def run(self, workflow_id: str, input_data: dict = None, **kw):
    # 1. Fetch workflow definition
    wf = self._get_workflow(workflow_id)
    
    # 2. Find Webhook trigger
    webhook_node = next(
        (n for n in wf["nodes"] if n["type"] == "n8n-nodes-base.webhook"),
        None,
    )
    if not webhook_node:
        return {"error": "Workflow has no Webhook trigger node. Add one to enable external execution."}
    
    path = webhook_node["parameters"]["path"]
    method = webhook_node["parameters"].get("httpMethod", "POST")
    
    # 3. Ensure workflow is active
    if not wf.get("active"):
        self._activate_workflow(workflow_id)
    
    # 4. POST to webhook URL (no API key needed — webhooks are public)
    webhook_url = f"{self.n8n_url}/webhook/{path}"
    response = httpx.request(method, webhook_url, json=input_data or {}, timeout=self.timeout)
    response.raise_for_status()
    return response.json()

Option B — Support both patterns

Accept either workflow_id (requires webhook trigger) or webhook_url (direct invocation):

def run(self, workflow_id: str = None, webhook_url: str = None, input_data: dict = None, ...):
    if webhook_url:
        target_url = webhook_url
    elif workflow_id:
        target_url = self._resolve_webhook_url(workflow_id)
    else:
        return {"error": "Provide workflow_id or webhook_url"}
    ...

Documentation Updates

  • Add note to docs/n8n_integration.md clarifying that workflows must have a Webhook trigger
  • Update docstring of n8n_workflow tool
  • Update tests to reflect webhook-based execution

Acceptance Criteria

  • N8nWorkflowTool.run() successfully triggers a workflow with Webhook trigger against live n8n
  • Returns meaningful error when workflow lacks a Webhook trigger
  • n8n_list_workflows continues to work (already correct)
  • Unit tests updated — no longer mock the /execute endpoint
  • Integration test covers live webhook trigger (skipped unless N8N_API_KEY + N8N_URL set)
  • Agent example n8n_integration_example.py verified end-to-end

Testing Commands

cd /Users/praison/PraisonAI-tools
pytest tests/test_n8n_integration.py -v

# Live integration (requires running n8n + API key + workflow with webhook trigger)
export N8N_URL="http://localhost:5678"
export N8N_API_KEY="..."
python -c "
from praisonai_tools.n8n import n8n_workflow
print(n8n_workflow(workflow_id='<your-id>', input_data={'query':'test'}))
"

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclaudeAuto-trigger Claude analysis

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions