本指南将一步步教你如何把 退款与订单支持 模板接入你自己的应用。无需任何 AI 经验,你只需要复制代码,而不是编写 AI 逻辑。
它做什么
端到端处理退款请求:识别客户需求,套用你的退款政策,并自动草拟清晰的回复。
模板自带 2 个工作流和 2 个响应格式,它们已经可以协同工作:
- 工作流:
refund_triage_workflow、refund_decision_workflow - 响应格式:
refund_triage_response、refund_decision_response
想走完全无代码的路径? 直接跳到 第 6 步 - Go no-code。
你将构建什么
- 一个后端端点,用客户请求启动 退款与订单支持 工作流。
- 一个实时聊天界面,在生成过程中流式展示 AI 回复。
- 一个Webhook 接收器,接收流水线事件并把结果发回给客户。
Step 1 - Download and import the template
- 打开 退款与订单支持 模板页面,点击下载 JSON。
- 在 ModelRiver 项目中点击导入,粘贴或上传文件,确认预览后完成导入。所有内容以原子方式创建,不会覆盖任何已有数据。
- 了解更多:导入与导出指南。
Step 2 - Connect the AI providers
该模板运行在 OpenAI 和 Anthropic 上。导入前请先在项目的「提供商」部分完成连接。如果你使用其他提供商,也可以在导入后修改任意工作流。
Step 3 - Add the backend endpoint
你的后端通过调用 ModelRiver API 来启动工作流,需要项目 API 密钥(在「项目设置 → API 密钥」中创建)。响应中包含一次性 ws_token,你的前端用它来流式接收回复。
// Express.js - POST /api/ai/chatimport express from 'express';const app = express();app.use(express.json()); app.post('/api/ai/chat', async (req, res) => { const response = await fetch('https://api.modelriver.com/v1/ai/async', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.MR_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ workflow: 'refund_triage_workflow', messages: [{ role: 'user', content: req.body.message }], inputs: { customer_id: req.body.customer_id }, }), }); const data = await response.json(); // Return the one-time ws_token so the frontend can stream the reply. res.json({ ws_token: data.ws_token, channel_id: data.channel_id });}); app.listen(3000);也可以使用 CLI 在本地运行这个端点:modelriver listen 会把 ModelRiver 的 Webhook 转发到你的 localhost。
Step 4 - Stream the reply in your frontend
使用 ModelRiver 客户端 SDK 连接数据流。用后端返回的 ws_token 调用 connect() 后,AI 回复会实时到达,无需轮询。
import { useState } from 'react';import { useModelRiver } from '@modelriver/client/react'; export function TemplateChat() { const [input, setInput] = useState(''); const { connect, response, error, status } = useModelRiver({ baseUrl: 'wss://api.modelriver.com/socket', persist: true, }); const handleSend = async () => { // 1. Your backend starts the refund_triage_workflow workflow and returns a one-time ws_token. const res = await fetch('/api/ai/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: input }), }); const { ws_token, channel_id } = await res.json(); // 2. Connect to ModelRiver's stream. The reply arrives in real time. connect({ wsToken: ws_token, channelId: channel_id }); setInput(''); }; return ( <div> <input value={input} onChange={(e) => setInput(e.target.value)} disabled={status === 'loading'} placeholder="Type your request..." /> <button onClick={handleSend} disabled={!input || status === 'loading'}>Send</button> {status === 'loading' && <p>Working on it...</p>} {response && ( <div> <p>{response.content}</p> {response.data && <pre>{JSON.stringify(response.data, null, 2)}</pre>} </div> )} {error && <p>{error}</p>} </div> );}用 npm install @modelriver/client 安装 SDK。同一个 ws_token 可用于 React、Vue、原生 JS 和 Svelte。
Step 5 - Receive the pipeline event in your backend
AI 步骤完成后,ModelRiver 会把 task.ai_generated 事件投递到你项目中配置的 Webhook 地址。你的后端可以补充自己的数据(你的政策、订单详情或数据库查询),然后调用事件中的 callback_url,最终回复就会流式发送给客户。
签名通过 mr-signature 请求头校验(使用你的 Webhook 密钥对原始请求体计算 HMAC-SHA256)。
// Express.js - POST /webhooks/modelriverimport express from 'express';import crypto from 'node:crypto'; const app = express();app.use(express.json({ verify: (req, _res, buf) => { (req as any).rawBody = buf; } })); app.post('/webhooks/modelriver', async (req, res) => { // 1. Verify the HMAC signature. const signature = req.headers['mr-signature'] as string; const secret = process.env.MR_WEBHOOK_SECRET; const expected = crypto .createHmac('sha256', secret) .update((req as any).rawBody) .digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) { return res.status(401).send('Invalid signature'); } const event = req.body; // 2. The AI step finished. Enrich it with your own data (order, policy, ...). const enriched = { ...event.ai_response, checked_at: new Date().toISOString() }; await saveEvent(event.channel_id, enriched); // your database // 3. Send the enriched result back so the reply streams to the customer. if (event.callback_url && event.callback_required) { await fetch(event.callback_url, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.MR_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ data: enriched }), }); } res.status(200).send('ok');}); app.listen(3000);Step 6 - Go no-code
不想自己运行服务器?这些平台可以直接接收流水线事件、存储数据并回调,无需管理任何基础设施。
// Supabase Edge Function - webhooks/modelriver// Deploy with: supabase functions deploy webhooks-modelriverimport { serve } from 'https://deno.land/[email protected]/http/server.ts';import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; const supabase = createClient( Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!); serve(async (req) => { const event = await req.json(); // 1. Store the AI step result in Postgres. const { error } = await supabase.from('ai_content').insert({ channel_id: event.channel_id, payload: event.ai_response, status: 'ai_generated', }); if (error) return new Response(error.message, { status: 500 }); // 2. Send the result back so the reply streams to the customer. if (event.callback_url && event.callback_required) { await fetch(event.callback_url, { method: 'POST', headers: { Authorization: `Bearer ${Deno.env.get('MR_API_KEY')}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ data: event.ai_response }), }); } return new Response('ok');});Test it end to end
- 启动你的后端(或部署无代码函数),并在项目中配置
MR_API_KEY、MR_WEBHOOK_SECRET和 Webhook 地址。 - 打开前端,输入一条测试请求并点击发送。
- 确认回复实时到达,并且后端收到了
task.ai_generated事件。