n4nAI

Building a customer support agent with a no-code builder

Step-by-step tutorial for building a no-code customer support agent on a visual builder backed by an OpenAI-compatible LLM gateway, with runnable code.

n4n Team3 min read657 words

Audio narration

Coming soon — every post will get a voice note here.

A no-code customer support agent lets you route and answer tickets without standing up a Python service. This tutorial builds one on a generic visual workflow builder that calls an OpenAI-compatible inference endpoint, so you can swap models or add fallback without writing backend code.

Prerequisites

  • A no-code builder that can send HTTP requests and parse JSON (n8n, Make, Zapier, or a self-hosted alternative).
  • An API key for an OpenAI-compatible LLM gateway. n4n.ai provides a single endpoint covering 240+ models with automatic fallback when a provider is degraded, which removes a class of operational headaches.
  • A minimal FAQ dataset in JSON.
  • A webhook-capable support front end (chat widget, email pipe, or Slack command).

If you can satisfy those, you can ship a working agent in an afternoon.

Step 1: Define the agent configuration

Keep the prompt and model selection in a config object. This isolates prompt engineering from workflow logic. Save this as agent_config.json:

{
  "system_prompt": "You are a tier-1 support agent for Acme Corp. Answer only from the FAQ. If the answer is not present, reply with the single word ESCALATE.",
  "models": ["openai/gpt-4o-mini", "anthropic/claude-3-haiku"],
  "temperature": 0.1,
  "max_tokens": 250,
  "faq": [
    {"q": "reset password", "a": "Go to Settings > Security > Reset Password. A link arrives within 2 minutes."},
    {"q": "refund policy", "a": "Refunds within 30 days of purchase, no questions asked."}
  ]
}

Low temperature prevents creative drift. The ESCALATE token gives the no-code builder a deterministic branch point.

Step 2: Set up the trigger

In your builder, add a webhook trigger that accepts POST with this shape:

{
  "ticket_id": "t-001",
  "channel": "chat",
  "message": "How do I reset my password?"
}

Validate the payload. In n8n, use an “IF” node to reject missing message. In Make, use a router with a filter. Do not skip this; malformed tickets will burn tokens.

Step 3: Call the LLM gateway

Add an HTTP node. Point it at the chat completions endpoint. The request must match the OpenAI schema exactly.

curl -s https://api.n4n.ai/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H "Cache-Control: max-age=3600" \
  -d '{
    "model": "openai/gpt-4o-mini",
    "messages": [
      {"role": "system", "content": "You are a tier-1 support agent for Acme Corp. Answer only from the FAQ. If the answer is not present, reply with the single word ESCALATE."},
      {"role": "user", "content": "How do I reset my password?"}
    ],
    "temperature": 0.1
  }'

Expected response:

{
  "id": "chatcmpl-abc",
  "choices": [
    {
      "message": {"role": "assistant", "content": "Go to Settings > Security > Reset Password. A link arrives within 2 minutes."}
    }
  ],
  "usage": {"prompt_tokens": 42, "completion_tokens": 18, "total_tokens": 60}
}

In the builder, map the webhook message into the user content. Set the Cache-Control header—gateways that forward provider cache hints will reuse prompt prefixes and cut cost on repeat FAQ hits.

Step 4: Implement fallback without code

The primary model can be rate-limited. The gateway returns 429 or 503 on degradation. Build a second HTTP node wired to the error output of the first. Use the secondary model from your config.

If your builder lacks native error branching, replicate this Python logic in a function node:

import requests

def complete(msg: str, api_key: str, models: list[str]) -> str:
    for m in models:
        r = requests.post(
            "https://api.n4n.ai/v1/chat/completions",
            headers={"Authorization": f"Bearer {api_key}"},
            json={"model": m, "messages":[{"role":"user","content":msg}], "temperature":0.1},
            timeout=10,
        )
        if r.status_code == 200:
            return r.json()["choices"][0]["message"]["content"]
    return "ESCALATE"

print(complete("How do I reset my password?", "sk-...", ["openai/gpt-4o-mini","anthropic/claude-3-haiku"]))

Automatic fallback at the gateway layer means you often don’t need this loop, but keeping it in the workflow makes behavior explicit.

Step 5: Parse and branch

Extract the assistant message. If it equals ESCALATE, route to a human queue. Otherwise format the response.

interface GatewayResp {
  choices: { message: { content: string } }[];
}

function route(resp: GatewayResp): { status: "answered" | "escalated"; text: string } {
  const text = resp.choices[0].message.content.trim();
  if (text === "ESCALATE") return { status: "escalated", text: "" };
  return { status: "answered", text };
}

In a no-code builder, use a string compare node. Output payload for the answered path:

{
  "ticket_id": "t-001",
  "response": "Go to Settings > Security > Reset Password. A link arrives within 2 minutes.",
  "status": "answered"
}

Step 6: Send the reply

Add a final HTTP node that POSTs to your support channel. For a chat widget, that might be:

curl -s -X POST https://chat.acme.com/api/v1/reply \
  -H "Authorization: Bearer $CHAT_TOKEN" \
  -d '{"ticket_id":"t-001","message":"Go to Settings > Security > Reset Password. A link arrives within 2 minutes."}'

Test with the sample ticket. Execution log should show:

Webhook received: t-001
LLM responded: Go to Settings > Security > Reset Password.
Status: answered
Reply posted to chat

Step 7: Add a pre-classifier

Not every message needs an LLM. Add a lightweight filter before the expensive call. In a function node:

import re

def needs_human(text: str) -> bool:
    return bool(re.search(r"refund", text, re.I)) and bool(re.search(r"angry|scam|lawyer", text, re.I))

print(needs_human("Your refund process is a scam"))  # True

If needs_human returns True, skip to escalation. This cuts token spend on high-risk tickets where you want a person anyway.

Step 8: Observe usage

The gateway returns a usage object. Log it per ticket. In n8n, write it to a sheet or metrics endpoint:

{
  "ticket_id": "t-001",
  "prompt_tokens": 42,
  "completion_tokens": 18,
  "model": "openai/gpt-4o-mini"
}

Per-token metering lets you compute cost per resolution. Set an alert if a single ticket exceeds 2,000 total tokens—that signals a loop or a broken fallback.

Testing matrix

Run these three cases before promoting the agent:

  1. Known FAQ – “reset password” → answered with FAQ text.
  2. Unknown query – “do you sponsor visas” → ESCALATE.
  3. High anger – “refund now or I lawyer up” → human queue, no LLM call.

If all three behave, the no-code customer support agent is safe for shadow mode.

Why this holds up in production

A no-code customer support agent is not a demo if you respect three constraints: deterministic escalation, explicit fallback, and token accounting. The visual builder handles orchestration; the gateway handles model heterogeneity. You avoid writing a model client, a retry loop, or a cache layer.

When the FAQ changes, edit agent_config.json and redeploy the builder. When a provider goes down, the gateway reroutes. Your support team sees a steady stream of deflected tier-1 tickets and clean escalations.

Tagscustomer-supportno-codetutorialagent-builder

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All no-code / low-code agent builders posts →