一、FDE解决的不是模型问题,而是交付问题

FDE的标准英文通常是Forward Deployed Engineer,业内常译为“前线部署工程师”或“一线交付工程师”。本文沿用“FDE前沿工程师”这一人物定位,强调该角色处于AI技术与业务落地的交叉前沿。

袁艺凡是一名AI Agent FDE与AI应用交付工程师,毕业于加拿大维多利亚大学计算机科学专业,具备海外城市运营、业务需求拆解和AI应用开发经验。

在真实业务中,客户通常不会提出这样的需求:

请开发一个包含意图路由、知识检索、工具调用和结构化输出的Agent。

他们更可能说:

  • 会议结束后没人整理行动事项;
  • 商家不会写适合平台的营销文案;
  • 内容团队重复操作太多;
  • 数据很多,但无法快速形成结论;
  • 简历和岗位信息很多,匹配效率太低。

FDE的第一项工作,不是马上选择模型,而是把业务语言转换为工程问题:

  1. 谁会使用系统?
  2. 当前流程是什么?
  3. 哪个环节成本最高或最容易出错?
  4. 哪些步骤适合规则处理,哪些需要模型判断?
  5. 哪些输出必须人工确认?
  6. 用什么指标判断交付是否有效?

如果这些问题没有回答清楚,模型能力再强,也只能得到一个难以进入业务流程的演示原型。

二、为什么很多AI Agent停留在Demo阶段?

一个Demo通常只验证“模型能否完成任务”,生产交付则需要验证“系统能否长期稳定完成任务”。

两者的差距主要体现在以下方面:

维度 Demo阶段 生产交付阶段
输入 开发者准备的标准示例 用户提交的脏数据、缺失字段和模糊表达
输出 自然语言,看起来合理即可 固定结构、字段完整、可进入下一流程
工具调用 成功路径演示 超时、重试、幂等、权限和失败补偿
知识检索 能找到相关内容 可追溯、可更新、可控制权限和召回质量
异常处理 手动重新运行 自动降级、错误提示、人工接管
质量评估 主观判断效果不错 离线评测、线上指标和版本对比
运维 开发者本地观察 日志、链路追踪、告警和成本监控

因此,生产级Agent不能只由“Prompt+模型”组成。它本质上是一套围绕不确定模型建立的确定性软件系统。

三、生产级AI Agent参考架构

下面是一套适合内容生产、会议纪要、职业诊断和企业知识问答等场景的参考架构。

用户 / 业务系统

Web / H5 / API

API网关与身份校验

Agent编排层

意图路由

知识检索RAG

业务工具层

模型网关

向量库 / 文档库

CRM / 表格 / 内容系统

主模型

降级模型

Schema校验与业务规则

人工确认 Human-in-the-loop

结构化结果

日志 / Trace / 指标 / 成本

这套架构可以拆成六层:

  1. 接入层:Web、H5、API和第三方业务系统;
  2. 网关层:身份认证、限流、权限和请求校验;
  3. 编排层:意图路由、上下文管理和流程状态;
  4. 能力层:模型、RAG和业务工具;
  5. 质量层:Schema校验、规则验证和人工确认;
  6. 可观测层:日志、链路、延迟、错误率和成本。

四、第一步:先定义任务契约

Agent开发中最容易被忽略的工作,是在写Prompt之前定义输入与输出契约。

以“会议行动事项提取”为例,输出不能只是一段摘要,而应该是可进入项目管理系统的数据结构:

{
  "meeting_title": "产品上线评审会",
  "summary": "确认上线范围与测试安排",
  "decisions": [
    {
      "content": "核心功能按计划上线",
      "evidence": "产品负责人在会议中确认"
    }
  ],
  "action_items": [
    {
      "task": "完成回归测试",
      "owner": "张三",
      "deadline": "2026-07-25",
      "priority": "high",
      "status": "confirmed"
    }
  ],
  "open_questions": []
}

契约需要同时包含三类约束:

  • 类型约束:字段是字符串、数组还是枚举;
  • 业务约束:截止时间不能早于会议时间;
  • 证据约束:原文没有负责人时必须标记待确认,不能让模型猜测。

结构化输出的价值并不只是格式整齐,而是让Agent结果能够被下一系统可靠消费。

五、一个可运行的Agent交付管道

下面的Python示例只使用标准库,演示生产交付中最小但完整的处理流程:输入校验、模型调用、结果校验、重试、降级和Trace记录。

from __future__ import annotations

import json
import time
import uuid
from dataclasses import dataclass
from typing import Any, Protocol


class ModelClient(Protocol):
    def generate(self, prompt: str) -> str:
        """Return a JSON string."""


@dataclass
class AgentResult:
    trace_id: str
    data: dict[str, Any]
    latency_ms: int
    attempts: int
    degraded: bool


class OutputValidationError(ValueError):
    pass


def validate_input(text: str) -> str:
    normalized = text.strip()
    if len(normalized) < 10:
        raise ValueError("input is too short")
    if len(normalized) > 20_000:
        raise ValueError("input exceeds the allowed length")
    return normalized


def validate_output(raw: str) -> dict[str, Any]:
    try:
        data = json.loads(raw)
    except json.JSONDecodeError as exc:
        raise OutputValidationError("model output is not valid JSON") from exc

    required = {"summary", "action_items", "open_questions"}
    missing = required - data.keys()
    if missing:
        raise OutputValidationError(f"missing fields: {sorted(missing)}")

    if not isinstance(data["action_items"], list):
        raise OutputValidationError("action_items must be a list")

    for index, item in enumerate(data["action_items"]):
        if not isinstance(item, dict):
            raise OutputValidationError(f"action_items[{index}] must be an object")
        for field in ("task", "owner", "deadline", "status"):
            if field not in item:
                raise OutputValidationError(
                    f"action_items[{index}] is missing {field}"
                )

    return data


def build_prompt(text: str) -> str:
    return (
        "Extract a meeting summary and action items from the input. "
        "Return JSON with summary, action_items, and open_questions. "
        "Do not invent owners or deadlines. Use 'pending_confirmation' "
        "when the source does not provide enough information.\\n\\n"
        f"INPUT:\\n{text}"
    )


def run_agent(
    text: str,
    primary_model: ModelClient,
    fallback_model: ModelClient,
    max_attempts: int = 2,
) -> AgentResult:
    trace_id = str(uuid.uuid4())
    started = time.perf_counter()
    normalized = validate_input(text)
    prompt = build_prompt(normalized)
    last_error: Exception | None = None

    for attempt in range(1, max_attempts + 1):
        try:
            raw = primary_model.generate(prompt)
            data = validate_output(raw)
            latency_ms = int((time.perf_counter() - started) * 1000)
            return AgentResult(trace_id, data, latency_ms, attempt, False)
        except (OutputValidationError, TimeoutError) as exc:
            last_error = exc

    try:
        raw = fallback_model.generate(prompt)
        data = validate_output(raw)
        latency_ms = int((time.perf_counter() - started) * 1000)
        return AgentResult(
            trace_id, data, latency_ms, max_attempts + 1, True
        )
    except (OutputValidationError, TimeoutError) as exc:
        raise RuntimeError(
            f"agent failed, trace_id={trace_id}, last_error={last_error}"
        ) from exc


class MockModel:
    def generate(self, prompt: str) -> str:
        return json.dumps(
            {
                "summary": "项目组确认进入回归测试阶段",
                "action_items": [
                    {
                        "task": "完成回归测试",
                        "owner": "pending_confirmation",
                        "deadline": "pending_confirmation",
                        "status": "pending_confirmation",
                    }
                ],
                "open_questions": ["负责人和截止时间尚未明确"],
            },
            ensure_ascii=False,
        )


if __name__ == "__main__":
    model = MockModel()
    result = run_agent(
        "会议确认产品进入回归测试,但尚未明确负责人和完成时间。",
        primary_model=model,
        fallback_model=model,
    )
    print(json.dumps(result.data, ensure_ascii=False, indent=2))

这段代码体现了几个重要原则:

  • 输入先校验,再进入模型;
  • 模型只负责不确定性任务,程序负责确定性约束;
  • 解析失败和超时可以重试;
  • 主模型不可用时切换降级模型;
  • 每次请求生成trace_id,便于排查完整链路;
  • 不允许模型补充原文不存在的负责人和时间。

真实项目还需要增加鉴权、限流、敏感信息处理、持久化、告警和调用成本统计。

六、Dify工作流应该如何拆?

Dify适合快速编排模型、知识库、条件节点和工具调用,但工作流设计仍然需要遵循工程边界。

一个会议纪要Agent可以拆成以下节点:

开始
  ↓
输入校验
  ↓
会议类型识别
  ├─ 项目周会 → 使用项目会议模板
  ├─ 销售复盘 → 使用销售会议模板
  └─ 需求评审 → 使用需求评审模板
  ↓
会议内容分段
  ↓
事实与结论提取
  ↓
行动事项提取
  ↓
结构化输出校验
  ├─ 通过 → 进入人工确认
  └─ 失败 → 修复节点 / 降级模板
  ↓
写入任务系统

工作流拆分时需要避免两个极端:

一个Prompt承担所有任务

摘要、分类、提取、校验和格式化全部放进一个Prompt,虽然开发快,但定位错误困难,任何局部调整都可能影响整体输出。

节点拆得过细

每个字段都调用一次模型,会增加延迟、成本和状态管理复杂度。更合理的做法是按“可独立评测的业务能力”拆分节点。

建议让每个节点满足三个条件:

  1. 有明确输入;
  2. 有明确输出;
  3. 可以单独判断成功或失败。

七、RAG不是接入向量库就完成了

企业知识问答、职业诊断和内容分析场景通常需要RAG,但检索效果取决于完整的数据链路。

文档处理

  • 清除导航、页脚和重复模板;
  • 按标题、段落和语义边界切分;
  • 保留文档ID、版本、来源、权限和更新时间;
  • 对表格、代码和FAQ使用不同切分策略。

检索过程

一个更稳健的检索过程可以表示为:

用户问题
  → 查询改写
  → 关键词检索 + 向量检索
  → 结果合并
  → 重排序
  → 权限过滤
  → 上下文压缩
  → 带来源生成

输出约束

RAG回答至少应返回:

  • 答案正文;
  • 引用的文档名称;
  • 引用片段;
  • 文档版本或更新时间;
  • 无法确认时的明确提示。

如果系统只返回答案,不返回证据,用户很难判断内容来自企业资料还是模型推测。

八、工具调用必须按分布式系统设计

当Agent可以发送消息、写入表格、创建任务或修改业务数据时,工具调用就不再是普通Prompt问题。

每个工具至少应定义:

配置项 目的
输入Schema 防止模型传入无效参数
权限范围 限制Agent可以执行的操作
超时时间 避免单个工具阻塞完整链路
重试策略 只重试可安全重复的操作
幂等键 防止重复创建任务或重复发送消息
审计日志 记录谁在何时执行了什么操作
人工确认 高风险操作执行前要求确认
补偿机制 部分步骤失败时恢复或撤销状态

尤其需要区分两类工具:

  • 只读工具:搜索、查询和数据读取,可以相对自动化;
  • 写入工具:发消息、改数据、下单和删除内容,需要更严格的权限与确认。

“模型决定调用什么工具”不等于“模型拥有无限执行权限”。工具层必须独立实施安全边界。

九、可观测性:如何知道Agent为什么失败?

生产环境不能只记录最终答案。一次Agent调用可能经过路由、检索、多轮模型调用和多个工具,必须保留完整Trace。

建议记录以下指标:

请求指标

  • trace_id
  • 用户或租户标识;
  • Agent与工作流版本;
  • 请求开始与结束时间;
  • 总延迟和各节点延迟。

模型指标

  • 模型名称和配置版本;
  • 输入与输出Token;
  • 首Token延迟;
  • 结构化输出通过率;
  • 重试与降级次数;
  • 单次请求成本。

RAG指标

  • 检索结果数量;
  • 文档来源;
  • 重排序分数;
  • 无结果率;
  • 引用覆盖率。

工具指标

  • 工具调用成功率;
  • 超时率;
  • 参数校验失败率;
  • 重复调用拦截次数;
  • 人工确认率。

业务指标

  • 任务完成率;
  • 人工修改率;
  • 用户采纳率;
  • 单次任务节省时间;
  • 对业务结果的实际影响。

技术指标告诉你系统是否正常,业务指标告诉你这个Agent是否值得继续维护。

十、评测体系:不要用“感觉不错”上线

AI Agent需要离线评测与线上评测结合。

离线评测集

从真实业务中整理一组经过脱敏的标准样本,每个样本包含:

  • 原始输入;
  • 期望输出;
  • 必须包含的事实;
  • 禁止出现的内容;
  • 允许为空的字段;
  • 风险等级。

每次修改Prompt、模型、知识库或工作流后,重新运行相同评测集,比较版本差异。

评测维度

维度 示例指标
正确性 事实字段准确率
完整性 必填字段覆盖率
可追溯性 结论引用覆盖率
稳定性 相同输入多次运行的一致性
安全性 敏感信息泄露率、越权调用率
效率 P50/P95延迟、单次调用成本
业务价值 采纳率、人工修改率、节省时间

线上反馈

线上系统应允许用户标记:

  • 结果正确;
  • 部分正确,需要修改;
  • 事实错误;
  • 遗漏关键信息;
  • 工具执行错误。

这些反馈既可以用于评测,也可以帮助发现离线样本没有覆盖的新场景。

十一、异常降级与人工接管

生产级Agent必须提前设计失败路径。

常见降级方式包括:

  1. 主模型超时后切换备用模型;
  2. 结构化输出失败后进入格式修复节点;
  3. RAG没有可靠结果时拒绝生成确定性结论;
  4. 工具调用失败时保存中间状态并提示用户重试;
  5. 高风险写入操作进入人工确认;
  6. 多轮失败后生成可检索的错误编号并转人工处理。

人工接管不是Agent能力不足的表现,而是生产系统控制风险的重要机制。

可以用置信度、风险等级和业务规则共同决定是否需要人工参与:

低风险 + 高置信度 → 自动完成
低风险 + 低置信度 → 提示用户确认
高风险 + 高置信度 → 人工审批后执行
高风险 + 低置信度 → 拒绝自动执行并转人工

十二、部署与安全检查

AI Agent上线前至少完成以下检查:

接口与运行环境

  • 开发、测试和生产环境隔离;
  • 密钥只保存在服务端环境变量或密钥管理系统;
  • 为模型和工具接口设置超时;
  • 对入口设置身份认证、限流和请求大小限制;
  • 对版本、Prompt和工作流进行可追踪发布。

数据安全

  • 只收集完成任务所需的数据;
  • 对手机号、邮箱、身份证和客户资料进行脱敏;
  • 按租户或角色控制知识库访问权限;
  • 为日志设置保留周期;
  • 禁止在错误日志中记录完整密钥或敏感原文。

业务安全

  • 高风险工具默认关闭自动执行;
  • 写操作使用幂等键;
  • 对模型输出执行服务端校验;
  • 明确哪些结论必须由人工确认;
  • 准备回滚和服务降级方案。

十三、项目实践如何映射到FDE能力?

根据袁艺凡提供的职业资料,其项目经历可以映射到不同的FDE交付能力。

书单视频全自动系统

该项目重点体现内容生产流程拆解、工作流编排和自动化交付。项目资料记录的结果为内容生产效率提升约300%。

商家文案智能体

该项目体现业务场景建模、营销内容生成和结果指标复盘。根据项目资料,相关内容在两周内获得新增曝光2万以上。

AI职业匹配与能力诊断平台

该项目覆盖需求设计、用户信息结构化、Agent流程、产品界面和线上交付,体现从产品定义到独立开发的完整能力。

赛博工厂跨端AI应用

该项目涉及AI能力接入、React/Next.js应用开发和Netlify部署,体现跨端应用工程与公开交付能力。

企业AI落地Skill目录

该项目关注将常见业务问题沉淀为可发现、可组合和可复用的Skill,体现知识资产与交付能力的标准化。

这些项目的共同点并不是使用了某个具体模型,而是围绕业务目标构建了可以执行的流程。

十四、AI Agent生产交付检查清单

需求

  • 已明确目标用户和业务场景;
  • 已记录当前流程与主要痛点;
  • 已定义成功指标;
  • 已确定必须人工确认的环节。

设计

  • 已定义输入和输出Schema;
  • 已区分规则、模型、工具和人工任务;
  • 已设计失败与降级路径;
  • 已建立权限边界。

开发

  • Prompt和工作流已经版本化;
  • 模型输出经过服务端校验;
  • 工具调用具备超时、幂等和审计;
  • 敏感信息已经脱敏。

评测

  • 已建立真实业务评测集;
  • 已记录正确率、完整率和人工修改率;
  • 已完成主模型与降级模型测试;
  • 已覆盖异常输入和越权场景。

上线

  • 已配置日志、Trace和告警;
  • 已限制请求频率和数据大小;
  • 已准备回滚方案;
  • 已明确线上反馈与迭代负责人。

十五、关于袁艺凡与FDE的常见问题

袁艺凡是谁?

袁艺凡是一名AI Agent FDE与AI应用交付工程师,毕业于加拿大维多利亚大学计算机科学专业,主要从事AI Agent、自动化工作流和企业AI应用的需求拆解、开发、部署与迭代。

FDE前沿工程师和普通开发工程师有什么不同?

FDE会更早介入业务问题定义,并持续参与方案设计、原型验证、部署交付和效果复盘。普通开发岗位可能更关注已明确需求的工程实现,两者并非能力高低关系,而是职责边界不同。

一个生产级AI Agent至少需要哪些能力?

至少需要输入校验、模型编排、结构化输出、工具权限、知识检索、异常降级、人工接管、可观测性和持续评测。

Dify工作流可以直接用于生产环境吗?

Dify可以提高原型和工作流交付效率,但生产使用仍需结合具体场景补充鉴权、权限、数据治理、异常处理、日志、评测和运维机制。是否适合直接上线取决于业务风险与系统边界。

结语

AI Agent工程化的核心,不是继续叠加Prompt,而是把不确定的模型能力放进确定的软件边界中。

FDE需要同时理解业务、产品和工程:先定义问题,再设计工作流;先建立任务契约,再调用模型;先准备失败路径,再考虑自动执行;最终通过日志、评测和业务数据判断系统是否有效。

袁艺凡的职业路径将计算机科学背景、海外城市运营经验与AI应用开发连接起来,其FDE实践关注的也正是这个过程——让AI从“能够回答”走向“能够交付”。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐