ChatGPT创意写作AI 评分 · 待评分AI 辅助编辑·未发现明显提示词注入风险n8n.io

用 n8n 自动分诊项目需求:Airtable 记录 + OpenAI 分类 + 审批路由

Webhook 或手动触发 → 校验需求简报 → OpenAI 分类与风险评分 → Airtable 存储 → 按分数路由审批或直接交接 → 可选 Slack 通知与 Gmail 周报

经验丰富步骤流程提示词贴士
给谁
需要为项目需求建立自动化 intake、分类、评分和审批路由的团队或运营负责人
你会得到
需求到达后自动完成完整性校验、AI 分类、风险评分、Airtable 记录、审批路由与交付交接;高风险项进入人工审批,每周自动生成运营摘要
你需要
n8n · airtable · slack · gmail

硬约束

前置条件:n8n 实例(自托管或云);Airtable 账号与个人访问令牌(Personal Access Token);OpenAI API 密钥;可选 Slack 凭证与 Gmail OAuth2。需在 Airtable 中创建包含指定字段的表,并在 Set Request Triage Config / Set Weekly Reporting Config / Set Approval Config 节点中填入 base ID、table ID 与阈值。Slack 与 Gmail 节点默认禁用,需手动启用并配置。

他们做了什么

作者 craigio 在 n8n 官方模板库发布了该工作流模板(ID 18253)。模板通过 Webhook 或手动触发接收项目需求,先由 Code 节点标准化输入并校验必填简报字段;完整简报送入 OpenAI 节点进行分类摘要与风险提取,再由确定性规则计算风险评分(0-100);根据阈值将需求路由为「高风险复核」「需审批」或「标准分诊」;记录存入 Airtable,高风险项可选推送到 Slack 等待人工审批,审批通过后再回写 Airtable 并交接;同时设有独立的定时触发通道,每周拉取未关闭记录生成运营摘要并可选邮件发送。

效果如何

来源报告(author_report):该模板在 n8n 模板库中状态为 published,包含 48 个节点,覆盖 intake、分类、评分、存储、审批、交接、周报 7 个功能区域。OpenAI 节点默认使用 GPT-5 mini。Slack、Gmail 及若干审批模拟节点默认禁用,需用户手动启用。

值得知道

1) 本站未实际导入运行(reproduction=not_tested),不保证各节点在当前 n8n 版本中的兼容性;2) Airtable 表字段必须严格按模板要求创建,否则节点会报错;3) OpenAI 输出经正则清理后 JSON.parse,若模型返回非 JSON 格式会导致流程中断;4) 审批 Webhook 路径为 /project-request-approval,需外部系统或人工 POST 决策;5) 手动执行时 Respond to Webhook 节点被跳过,测试审批流程需使用实际 Webhook 或单独触发审批分支;6) 高评分请求在 Airtable 中状态为 Approval Required / Pending,需等待独立审批事件,不会自动通过;7) 周报通道与 intake 完全隔离,使用独立的 Set Weekly Reporting Config,需单独配置 base/table ID。

n8n 工作流模板

结构已检查 · 未实际运行

下载后在 n8n 选择“Import from File”,或复制 JSON 后粘贴到编辑器。先配置自己的账号,再用测试数据运行;模板默认未启用。

配置与测试清单

需要绑定的凭证

  • 导入后按各需鉴权节点绑定你自己的凭证;本附件不含原作者密钥。

需要替换的配置

  • 源模板来自 n8n 公开库 #18253(约 48 个节点)。导入后先保持未启用,核对触发器、表达式与外部 API 端点。
  • Sticky Note 中的说明仅供参考;按自己的账号、表结构或频道 ID 替换占位配置。

测试输入与预期结果

  • 在测试环境手动执行一次主路径,确认每个需凭证的节点已连接且无鉴权错误。
  • 用一条合成/脱敏样例数据跑通,核对输出字段与下游写入目标,再考虑生产启用。

模板处理说明

  • 已移除原作者凭证绑定、webhookId 与执行数据,工作流设为未启用;节点、连线与原文提示词保持原样。未在 n8n 中实际运行。
  • 未改业务逻辑;运行前请自行核对密钥、配额与隐私合规。

模板获取日期: 2026-10-24

步骤

  1. 准备 Airtable 与凭证

    在 Airtable 中创建一个表,包含以下字段(Triage_Score 为数字型,其余为文本型):Request_ID, Request_Title, Request_Type, Requester, Requester_Email, Objective, Deliverables, Due_Date, Created_At, Status, Triage_Route, Triage_Score, Triage_Summary, Risk_Level, Recommended_Owner, Next_Action, Approval_Status, Assigned_Owner, Approver_Name。在 n8n 的 Set Request Triage Config 节点中填入你的 Airtable base ID、table ID、通知邮箱、Slack 频道 ID、风险阈值(high_risk_threshold 默认 70,approval_required_threshold 默认 45)。在 n8n Credentials 中添加 Airtable Personal Access Token、OpenAI API Key;如需启用 Slack/Gmail,则分别添加对应凭证。

  2. 接收并校验需求简报

    工作流通过 Webhook(POST /project-request-triage)或手动触发接收需求。Normalize Project Request 节点将输入字段统一标准化(支持 body 对象或直接字段)。Check Brief Completeness 节点检查必填项:requester_name、requester_email、request_title、objective、deliverables、due_date。若缺失,则返回 400 及澄清问题列表;若完整,则进入分类步骤。

    运行提示词 · 来源原文。Normalize Project Request 节点的 JS Code 字段

    const input = $input.first()?.json || {};
    
    const request = input.body && typeof input.body === 'object'
      ? input.body
      : input;
    
    const clean = (v) => String(v ?? '').trim();
    
    return [{
      json: {
        request_id: clean(request.request_id) || `REQ-${Date.now()}`,
        requester_name: clean(request.requester_name),
        requester_email: clean(request.requester_email),
        request_title: clean(request.request_title),
        objective: clean(request.objective),
        deliverables: clean(request.deliverables),
        due_date: clean(request.due_date),
        budget_status: clean(request.budget_status),
        required_systems: clean(request.required_systems),
        approvals_required: clean(request.approvals_required),
        business_impact: clean(request.business_impact),
        urgency: clean(request.urgency),
        data_sensitivity: clean(request.data_sensitivity),
        request_type_hint: clean(request.request_type_hint),
        request_source: input.body ? 'webhook' : 'manual',
        received_at: new Date().toISOString()
      }
    }];

    运行提示词 · 来源原文。Check Brief Completeness 节点的 JS Code 字段

    const j = $input.first().json || {};
    
    const required = [
      'requester_name',
      'requester_email',
      'request_title',
      'objective',
      'deliverables',
      'due_date'
    ];
    
    const missing = required.filter(k => !String(j[k] || '').trim());
    
    const questions = [];
    if (!j.objective) questions.push('What business outcome should this request achieve?');
    if (!j.deliverables) questions.push('What specific outputs or deliverables are required?');
    if (!j.due_date) questions.push('What is the required delivery date?');
    if (!j.required_systems) questions.push('Which systems, tools or data sources are involved?');
    if (!j.approvals_required) questions.push('Who needs to approve the work or final output?');
    if (!j.budget_status) questions.push('Is budget or commercial approval already confirmed?');
    
    return [{
      json: {
        ...j,
        brief_complete: missing.length === 0,
        missing_required_fields: missing,
        clarification_questions: questions
      }
    }];
  3. OpenAI 分类与风险评分

    完整简报进入 OpenAI Classify Request 节点。System 提示词要求模型仅依据提供的证据进行分类,返回固定 JSON 格式(request_type、delivery_route、summary、risks、dependencies、decision_needed、recommended_owner_type、complexity)。Parse Classification Result 节点解析并清理模型输出。Calculate Risk and Urgency 节点基于 urgency、business_impact、data_sensitivity、budget_status、ai_risks 数量、complexity、approvals_required 等维度进行确定性评分(0-100),并按阈值划分为 High Risk Review、Approval Required、Standard Triage 三路。

    运行提示词 · 来源原文。OpenAI Classify Request 节点的 System 提示词字段

    You are a project triage assistant. Classify the request using only the supplied evidence.
    
    Return valid JSON with:
    request_type: one of Automation, Content Production, Data/Reporting, Integration, AI/Agent, Consulting, Other
    delivery_route: short plain-English route
    summary: max 80 words
    risks: array of concise risks
    dependencies: array
    decision_needed: array
    recommended_owner_type: short role label
    complexity: Low, Medium or High
    
    Do not invent budget, deadlines, systems, approvals or owners.

    运行提示词 · 来源原文。OpenAI Classify Request 节点的 User 提示词字段(n8n 表达式,运行时替换变量)

    =Request title: {{$json.request_title}}
    Objective: {{$json.objective}}
    Deliverables: {{$json.deliverables}}
    Due date: {{$json.due_date}}
    Budget status: {{$json.budget_status}}
    Systems: {{$json.required_systems}}
    Approvals: {{$json.approvals_required}}
    Business impact: {{$json.business_impact}}
    Urgency: {{$json.urgency}}
    Data sensitivity: {{$json.data_sensitivity}}
    Request type hint: {{$json.request_type_hint}}
    
    Return only valid JSON.

    运行提示词 · 来源原文。Parse Classification Result 节点的 JS Code 字段

    const input = $input.first().json || {};
    const raw =
      input.output?.[0]?.content?.find(c => c.type === 'output_text')?.text ||
      input.output?.[0]?.content?.[0]?.text ||
      input.text ||
      '';
    
    if (!raw) throw new Error('No classification output returned.');
    
    const cleaned = String(raw).replace(/```json/gi,'').replace(/```/g,'').trim();
    let parsed;
    try { parsed = JSON.parse(cleaned); }
    catch { throw new Error('Classification output was not valid JSON.'); }
    
    const source = $('Check Brief Completeness').first().json;
    
    return [{
      json: {
        ...source,
        request_type: parsed.request_type || 'Other',
        delivery_route: parsed.delivery_route || '',
        triage_summary: parsed.summary || '',
        ai_risks: Array.isArray(parsed.risks) ? parsed.risks : [],
        dependencies: Array.isArray(parsed.dependencies) ? parsed.dependencies : [],
        decisions_needed: Array.isArray(parsed.decision_needed) ? parsed.decision_needed : [],
        recommended_owner_type: parsed.recommended_owner_type || 'Delivery Lead',
        complexity: parsed.complexity || 'Medium'
      }
    }];

    运行提示词 · 来源原文。Calculate Risk and Urgency 节点的 JS Code 字段

    const j = $input.first().json || {};
    
    let score = 0;
    const reasons = [];
    
    const urgency = String(j.urgency || '').toLowerCase();
    if (urgency === 'high') { score += 20; reasons.push('High urgency'); }
    else if (urgency === 'medium') score += 10;
    
    const impact = String(j.business_impact || '').toLowerCase();
    if (impact === 'high') { score += 20; reasons.push('High business impact'); }
    else if (impact === 'medium') score += 10;
    
    const sensitivity = String(j.data_sensitivity || '').toLowerCase();
    if (sensitivity.includes('sensitive') || sensitivity.includes('confidential')) {
      score += 20; reasons.push('Sensitive data involved');
    } else if (sensitivity.includes('internal')) {
      score += 5;
    }
    
    if (String(j.budget_status || '').toLowerCase().includes('unknown')) {
      score += 10; reasons.push('Budget not confirmed');
    }
    
    if ((j.ai_risks || []).length >= 3) {
      score += 10; reasons.push('Multiple delivery risks identified');
    }
    
    const complexity = String(j.complexity || '').toLowerCase();
    if (complexity === 'high') { score += 15; reasons.push('High complexity'); }
    else if (complexity === 'medium') score += 5;
    
    if (String(j.approvals_required || '').trim()) {
      score += 5;
    }
    
    score = Math.min(score, 100);
    
    const cfg = $('Set Request Triage Config').first().json || {};
    const high = Number(cfg.high_risk_threshold || 70);
    const approval = Number(cfg.approval_required_threshold || 45);
    
    let route;
    if (score >= high) route = 'High Risk Review';
    else if (score >= approval) route = 'Approval Required';
    else route = 'Standard Triage';
    
    return [{
      json: {
        ...j,
        triage_score: score,
        triage_risk_level: score >= high ? 'High' : score >= approval ? 'Medium' : 'Low',
        triage_route: route,
        score_reasons: reasons
      }
    }];
  4. 存储记录并按分数路由

    If Needs Approval 节点按 triage_score >= approval_required_threshold(默认 45)分支。若需审批,Store Triage Record in Airtable 创建记录,状态设为 Approval Required / Pending;Prepare Approval Request Data 组装审批消息,可选 Post Approval to Slack(默认禁用);若来自 Webhook,返回 202 Pending 响应。若无需审批,Store Standard Triage Record in Airtable 创建记录,状态为 In Triaging,直接进入 Assign Triage Owner。

    运行提示词 · 来源原文。Prepare Approval Request Data 节点的 JS Code 字段

    let ctx = {};
    try { ctx = $('Calculate Risk and Urgency').item.json || {}; } catch {}
    const rec = $input.item.json || {};
    const f = rec.fields || {};
    if (!ctx.request_id) {
      // Fallback: rebuild context from the Airtable record that was just created.
      ctx = { request_id: f.Request_ID, request_title: f.Request_Title, request_type: f.Request_Type,
        requester_name: f.Requester, requester_email: f.Requester_Email, objective: f.Objective,
        deliverables: f.Deliverables, due_date: f.Due_Date, triage_route: f.Triage_Route,
        triage_score: f.Triage_Score, triage_summary: f.Triage_Summary, triage_risk_level: f.Risk_Level,
        recommended_owner_type: f.Recommended_Owner };
    }
    const j = ctx;
    return { json: {
      ...j,
      airtable_record_id: rec.id || '',
      triage_status: 'Approval Required',
      approval_status: 'Pending',
      next_action: 'Await human approval',
      approval_reason: `Triage score ${j.triage_score}/100 (${j.triage_risk_level}). Route: ${j.triage_route}.`,
      approval_message:
        `Approval required for ${j.request_title}\n\n` +
        `Request ID: ${j.request_id}\n` +
        `Summary: ${j.triage_summary}\n` +
        `Risk: ${j.triage_risk_level} (${j.triage_score}/100)\n` +
        `Due: ${j.due_date}\n` +
        `Budget: ${j.budget_status}\n` +
        `Recommended owner: ${j.recommended_owner_type}\n\n` +
        `POST the decision to /webhook/project-request-approval with request_id, decision and approver_name.`
    }};
  5. 交付交接与状态回写

    Assign Triage Owner 将 recommended_owner_type 设为 assigned_owner,状态更新为 Assigned / In Progress。Prepare Handoff 构建结构化交接对象(含 request_id、title、objective、deliverables、due_date、request_type、delivery_route、owner、dependencies、decisions_needed、risks、next_action)。Patch Airtable Status 通过 HTTP PATCH 更新 Airtable 记录的 Status、Assigned_Owner、Next_Action、Approval_Status。若请求来自 Webhook,Send Triage Outcome 返回 JSON 响应;手动执行则进入 noOp 结束。

    运行提示词 · 来源原文。Assign Triage Owner 节点的 JS Code 字段

    let ctx = {};
    try { ctx = $('Calculate Risk and Urgency').item.json || {}; } catch {}
    const rec = $input.item.json || {};
    const f = rec.fields || {};
    if (!ctx.request_id) {
      // Fallback: rebuild context from the Airtable record that was just created.
      ctx = { request_id: f.Request_ID, request_title: f.Request_Title, request_type: f.Request_Type,
        requester_name: f.Requester, requester_email: f.Requester_Email, objective: f.Objective,
        deliverables: f.Deliverables, due_date: f.Due_Date, triage_route: f.Triage_Route,
        triage_score: f.Triage_Score, triage_summary: f.Triage_Summary, triage_risk_level: f.Risk_Level,
        recommended_owner_type: f.Recommended_Owner };
    }
    
    return { json: {
      ...ctx,
      airtable_record_id: rec.id || '',
      assigned_owner: ctx.recommended_owner_type || 'Delivery Lead',
      triage_status: 'Assigned / In Progress',
      next_action: 'Schedule delivery kick-off and confirm scope, dependencies and milestones'
    }};

    运行提示词 · 来源原文。Prepare Handoff 节点的 JS Code 字段

    const j = $input.item.json || {};
    return {
      json: {
        ...j,
        handoff_summary: {
          request_id: j.request_id,
          title: j.request_title,
          objective: j.objective,
          deliverables: j.deliverables,
          due_date: j.due_date,
          request_type: j.request_type,
          delivery_route: j.delivery_route,
          owner: j.assigned_owner,
          dependencies: j.dependencies || [],
          decisions_needed: j.decisions_needed || [],
          risks: j.ai_risks || [],
          next_action: j.next_action
        }
      }
    };
  6. 人工审批决策

    独立审批 Webhook(POST /project-request-approval)接收 request_id、decision(APPROVED/REJECTED/CHANGES_REQUESTED)、approver_name。Normalise Approval Decision 校验输入后,Find Pending Airtable Request 按 Request_ID 查询记录,Prepare Approval Update 根据决策更新状态:APPROVED → Assigned / In Progress 并分配负责人;REJECTED → Closed / Declined;CHANGES_REQUESTED → Approval Required 并提示需修改。Patch Airtable Approval Result 写入更新,Send Approval Outcome 返回结果。

    运行提示词 · 来源原文。Normalise Approval Decision 节点的 JS Code 字段

    const input = $input.first()?.json || {};
    const body = input.body && typeof input.body === 'object' ? input.body : input;
    const request_id = String(body.request_id || '').trim();
    const decision = String(body.decision || '').trim().toUpperCase();
    const approver_name = String(body.approver_name || '').trim();
    
    if (!request_id) throw new Error('request_id is required.');
    if (!['APPROVED','REJECTED','CHANGES_REQUESTED'].includes(decision)) {
      throw new Error('decision must be APPROVED, REJECTED or CHANGES_REQUESTED.');
    }
    
    return [{ json: {
      request_id,
      approval_decision: decision,
      approver_name,
      approval_received_at: new Date().toISOString()
    }}];

    运行提示词 · 来源原文。Prepare Approval Update 节点的 JS Code 字段

    const lookup = $input.first()?.json || {};
    const decision = $('Normalise Approval Decision').first().json || {};
    const record = Array.isArray(lookup.records) ? lookup.records[0] : null;
    if (!record?.id) throw new Error('No Airtable triage record found for request_id.');
    
    const existing = record.fields || {};
    const approved = decision.approval_decision === 'APPROVED';
    const rejected = decision.approval_decision === 'REJECTED';
    
    let status = 'Approval Required';
    let nextAction = 'Reviewer requested changes before approval';
    if (approved) {
      status = 'Assigned / In Progress';
      nextAction = 'Schedule delivery kick-off and confirm scope, dependencies and milestones';
    } else if (rejected) {
      status = 'Closed / Declined';
      nextAction = 'Review rejection reason before resubmitting';
    }
    
    return [{ json: {
      ...existing,
      airtable_record_id: record.id,
      request_id: decision.request_id,
      approval_decision: decision.approval_decision,
      approver_name: decision.approver_name,
      approval_received_at: decision.approval_received_at,
      triage_status: status,
      next_action: nextAction,
      assigned_owner: approved ? (existing.Assigned_Owner || existing.Recommended_Owner || 'Delivery Lead') : ''
    }}];
  7. 每周运营摘要

    Weekly Triage Summary Trigger 按设定时间(默认周五 15:00)触发。Set Weekly Reporting Config 配置 base/table ID 与通知邮箱。Fetch Open Triage Requests 通过 HTTP 查询 Airtable 中 Status ≠ Closed / Declined 的记录。Compile Weekly Summary 统计总数、各状态数量、blocked 数、无负责人数,并生成 Markdown 摘要。可选 Email Weekly Summary 通过 Gmail 发送(默认禁用)。该通道与需求 intake 完全隔离。

    运行提示词 · 来源原文。Compile Weekly Summary 节点的 JS Code 字段

    const data = $input.first().json || {};
    const records = Array.isArray(data.records) ? data.records : [];
    
    const rows = records.map(r => ({ id: r.id, ...(r.fields || {}) }));
    
    const counts = rows.reduce((acc, r) => {
      const status = String(r.Status || 'Unknown');
      acc[status] = (acc[status] || 0) + 1;
      return acc;
    }, {});
    
    const blocked = rows.filter(r =>
      /information required|on hold|approval/i.test(String(r.Status || ''))
    );
    
    const noOwner = rows.filter(r => !String(r.Assigned_Owner || '').trim());
    
    return [{
      json: {
        total_open: rows.length,
        status_counts: counts,
        blocked_count: blocked.length,
        unassigned_count: noOwner.length,
        blocked_requests: blocked.slice(0, 10),
        unassigned_requests: noOwner.slice(0, 10),
        generated_at: new Date().toISOString(),
        markdown_summary: [
          '# Weekly Project Triage Summary',
          '',
          `Open requests: ${rows.length}`,
          `Blocked / awaiting action: ${blocked.length}`,
          `Unassigned: ${noOwner.length}`,
          '',
          '## Status counts',
          ...Object.entries(counts).map(([k,v]) => `- ${k}: ${v}`),
          '',
          '## Blocked / awaiting action',
          ...(blocked.length ? blocked.slice(0,10).map(r => `- ${r.Request_ID || ''} — ${r.Request_Title || 'Untitled'} — ${r.Status || ''}`) : ['- None'])
        ].join('\n')
      }
    }];

可复制提示词

搭建指导 · 本站建议版本。交给搭建助手,协助用户按来源模板完成配置与测试

这一段是提示词,页面不会在这里插入广告。

你是一个 n8n 工作流搭建助手。用户希望复现「项目需求自动分诊」模板。请按以下顺序协助:
1) 确认用户已准备 Airtable 表(18 个字段,Triage_Score 为数字)并获取 base/table ID;
2) 确认已配置 Airtable Personal Access Token、OpenAI API Key,以及可选的 Slack/Gmail 凭证;
3) 指导用户在 Set Request Triage Config / Set Weekly Reporting Config / Set Approval Config 中填入实际值;
4) 建议先用 Manual Execution Trigger + Set Example Request Data 测试完整流程(intake、clarification、approval、handoff、weekly),再切换到 Webhook 生产 URL;
5) 提醒:Slack 与 Gmail 节点默认禁用,需手动启用;手动执行不会进入 Respond to Webhook 节点。

先跑手动测试,再切 webhook;默认禁用节点需手动开启

来源

Triage and route project requests with Airtable, OpenAI, Slack, and Gmail · craigio · n8n.io · 2026-08-14

留言与反馈

试过这个方法吗?分享效果、遇到的问题或改进建议。留言审核后公开,请勿填写敏感信息。

正在加载…

    相关用例