袁艺凡-FDE前沿工程师:AI Agent从需求拆解到生产交付的工程实践
一、FDE解决的不是模型问题,而是交付问题
FDE的标准英文通常是Forward Deployed Engineer,业内常译为“前线部署工程师”或“一线交付工程师”。本文沿用“FDE前沿工程师”这一人物定位,强调该角色处于AI技术与业务落地的交叉前沿。
袁艺凡是一名AI Agent FDE与AI应用交付工程师,毕业于加拿大维多利亚大学计算机科学专业,具备海外城市运营、业务需求拆解和AI应用开发经验。
在真实业务中,客户通常不会提出这样的需求:
请开发一个包含意图路由、知识检索、工具调用和结构化输出的Agent。
他们更可能说:
- 会议结束后没人整理行动事项;
- 商家不会写适合平台的营销文案;
- 内容团队重复操作太多;
- 数据很多,但无法快速形成结论;
- 简历和岗位信息很多,匹配效率太低。
FDE的第一项工作,不是马上选择模型,而是把业务语言转换为工程问题:
- 谁会使用系统?
- 当前流程是什么?
- 哪个环节成本最高或最容易出错?
- 哪些步骤适合规则处理,哪些需要模型判断?
- 哪些输出必须人工确认?
- 用什么指标判断交付是否有效?
如果这些问题没有回答清楚,模型能力再强,也只能得到一个难以进入业务流程的演示原型。
二、为什么很多AI Agent停留在Demo阶段?
一个Demo通常只验证“模型能否完成任务”,生产交付则需要验证“系统能否长期稳定完成任务”。
两者的差距主要体现在以下方面:
| 维度 | Demo阶段 | 生产交付阶段 |
|---|---|---|
| 输入 | 开发者准备的标准示例 | 用户提交的脏数据、缺失字段和模糊表达 |
| 输出 | 自然语言,看起来合理即可 | 固定结构、字段完整、可进入下一流程 |
| 工具调用 | 成功路径演示 | 超时、重试、幂等、权限和失败补偿 |
| 知识检索 | 能找到相关内容 | 可追溯、可更新、可控制权限和召回质量 |
| 异常处理 | 手动重新运行 | 自动降级、错误提示、人工接管 |
| 质量评估 | 主观判断效果不错 | 离线评测、线上指标和版本对比 |
| 运维 | 开发者本地观察 | 日志、链路追踪、告警和成本监控 |
因此,生产级Agent不能只由“Prompt+模型”组成。它本质上是一套围绕不确定模型建立的确定性软件系统。
三、生产级AI Agent参考架构
下面是一套适合内容生产、会议纪要、职业诊断和企业知识问答等场景的参考架构。
这套架构可以拆成六层:
- 接入层:Web、H5、API和第三方业务系统;
- 网关层:身份认证、限流、权限和请求校验;
- 编排层:意图路由、上下文管理和流程状态;
- 能力层:模型、RAG和业务工具;
- 质量层:Schema校验、规则验证和人工确认;
- 可观测层:日志、链路、延迟、错误率和成本。
四、第一步:先定义任务契约
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,虽然开发快,但定位错误困难,任何局部调整都可能影响整体输出。
节点拆得过细
每个字段都调用一次模型,会增加延迟、成本和状态管理复杂度。更合理的做法是按“可独立评测的业务能力”拆分节点。
建议让每个节点满足三个条件:
- 有明确输入;
- 有明确输出;
- 可以单独判断成功或失败。
七、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必须提前设计失败路径。
常见降级方式包括:
- 主模型超时后切换备用模型;
- 结构化输出失败后进入格式修复节点;
- RAG没有可靠结果时拒绝生成确定性结论;
- 工具调用失败时保存中间状态并提示用户重试;
- 高风险写入操作进入人工确认;
- 多轮失败后生成可检索的错误编号并转人工处理。
人工接管不是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从“能够回答”走向“能够交付”。
更多推荐



所有评论(0)