RADZOR
ComponentsRecipesDocsContributeGitHub
Get Started
RADZOR

The universal component registry for LLM-driven development. Empowering developers to build better apps, faster.

Product
  • Components
  • Standard
Resources
  • Documentation
  • API Reference
  • AI Agent Integration
  • Pipeline Guide
  • MCP Server
Community
  • GitHub
  • X / Twitter
  • Discord

© 2026 Radzor Registry. All rights reserved.

Cookbook
Advancedchataimessaging

Chatbot with EscalationAI Workflow

A conversational chatbot that follows scripted flows, escalates to an LLM when stuck, validates all AI responses with guardrails, and notifies support on Slack when it can't resolve the issue.

Prerequisites

Environment variables

OPENAI_KEYSLACK_BOT_TOKEN
The chatbot flow definition is a JSON object describing nodes, transitions, and conditions. See the chatbot-flow manifest for the full schema.

Install

$npx radzor@latest recipe add chatbot-escalation

AI Prompt

“Run `npx radzor@latest add chatbot-flow llm-completion guardrails slack-bot` to install 4 Radzor components. Then read components/radzor/chatbot-flow/radzor.manifest.json, components/radzor/llm-completion/radzor.manifest.json, components/radzor/guardrails/radzor.manifest.json, components/radzor/slack-bot/radzor.manifest.json and each component's llm/integration.md. Wire them together to a conversational chatbot that follows scripted flows, escalates to an LLM when stuck, validates all AI responses with guardrails, and notifies support on Slack when it can't resolve the issue. Use the manifest's inputs (check envVar for required environment variables), outputs (check fields for object shapes), composability (check mapField for field extraction), and actions — don't invent custom interfaces.”

Paste this into Claude Code, Cursor, Windsurf, or any AI coding agent.

Pipeline

ChatbotFlow

Handles scripted conversation flow

→
↓
response / fallback

LLMCompletion

Generates AI response on fallback

→
↓
AI response

Guardrails

Validates AI response for safety

→
↓
validated response

SlackBot

Escalates unresolved issues to support

Scaffolded Code

chatbot-escalation-recipe.ts
// npx radzor@latest add chatbot-flow llm-completion guardrails slack-bot
import { ChatbotFlow }   from "./components/radzor/chatbot-flow"
import { LLMCompletion } from "./components/radzor/llm-completion"
import { Guardrails }    from "./components/radzor/guardrails"
import { SlackBot }      from "./components/radzor/slack-bot"

const bot = new ChatbotFlow({
  fallbackMessage: "Let me think about that...",
  maxHistory: 20,
  flow: {
    startNode: "greeting",
    nodes: {
      greeting: {
        message: "Hi! How can I help you today?",
        options: [
          { label: "Billing question", next: "billing" },
          { label: "Technical issue", next: "technical" },
          { label: "Something else", next: "freeform" },
        ],
      },
      billing: {
        message: "For billing, I can help with invoices, refunds, or subscription changes. What do you need?",
        options: [
          { label: "Get invoice", next: "invoice_help" },
          { label: "Request refund", next: "refund_help" },
        ],
      },
      technical: {
        message: "Let me connect you with our AI assistant for technical questions.",
        next: "freeform",
      },
      invoice_help: { message: "You can download invoices from Settings > Billing. Need anything else?" },
      refund_help: { message: "Refunds are processed within 5-7 days. I'll escalate this to our team." },
      freeform: { message: null }, // triggers fallback → LLM
    },
  },
})

const llm = new LLMCompletion({
  provider: "openai",
  apiKey: process.env.OPENAI_KEY!,
  model: "gpt-4o",
  systemPrompt: "You are a helpful customer support agent. Be concise and friendly.",
  maxTokens: 256,
})

const guard = new Guardrails({ enableBuiltinRules: true, maxOutputLength: 1000 })
const slack = new SlackBot({ botToken: process.env.SLACK_BOT_TOKEN! })

// Escalate to LLM when chatbot flow has no matching node
bot.on("onFallback", async (event) => {
  const history = bot.getHistory(event.sessionId)
  const context = history.map(m => `${m.role}: ${m.content}`).join("\n")

  const { content } = await llm.complete(`Conversation so far:\n${context}\n\nUser: ${event.message}\nAssistant:`)

  // Validate AI response
  const validation = guard.validateOutput(content)
  if (!validation.passed) {
    await slack.sendMessage("#support-escalations",
      `Guardrails blocked AI response for session ${event.sessionId}: ${validation.violations?.join(", ")}`
    )
    return { message: "I'll connect you with a human agent. One moment please." }
  }

  return { message: content }
})

// Notify support on flow completion (when issue needs human follow-up)
bot.on("onFlowComplete", async (event) => {
  if (event.nodeId === "refund_help") {
    const history = bot.getHistory(event.sessionId)
    await slack.sendMessage("#support-escalations",
      `Refund request from session ${event.sessionId}:\n${history.map(m => m.content).join("\n")}`
    )
  }
})

// Handle incoming messages
async function handleMessage(sessionId: string, message: string) {
  return bot.processMessage(sessionId, message)
}

Components used

ChatbotFlowHandles scripted conversation flow
View
LLMCompletionGenerates AI response on fallback
View
GuardrailsValidates AI response for safety
View
SlackBotEscalates unresolved issues to support
View

LLM tip

Pass all 4 radzor.manifest.json files to your agent at once. It will read the outputs of each step and match them against the inputs of the next — wiring the full pipeline without any extra instructions.

chatbot-flow/manifest.jsonllm-completion/manifest.jsonguardrails/manifest.jsonslack-bot/manifest.json