AI友好的接口设计:几点来自实践的思考

📅 2026/7/9 8:11:09
AI友好的接口设计:几点来自实践的思考
一、前置认知人和 AI 的能力图谱是互补的人和 AI 擅长的事情是互补的不是重叠的。这个认知直接决定了接口设计的重点——你要弥补的是 AI 缺失的那一半而不是人类早已擅长的那一半。搞清楚这一点后面所有设计决策才有根基。1.1 你觉得很复杂的AI 可能觉得很简单用户说“帮我查一下华南区域过去一个月超 48 小时未处理的审批单按部门分组统计”如果让人操作需要打开报表系统、设时间范围、选区域、选状态、选业务类型、配聚合条件。如果系统没有现成的组合筛选入口还得导出数据手动处理。对 AI 来说这是一次结构化的意图解析而意图解析是 AI 的强项。AI 从自然语言中提取出结构化的查询参数后秒级完成查询和汇总。多条件的结构化组合查询是 AI 的舒适区——条件越多、组合越复杂AI 相对于人的效率优势越明显。再看多接口编排“查一下这个需求单关联的审批记录如果有待审批的帮我看一下审批意见”人需要先查需求单 → 找关联审批记录 → 切换系统 → 查详情每步都要手动完成。AI 直接串联多个接口调用完成整个流程。逻辑链条越长AI 越不怵——每一步都是确定的接口调用没有歧义且 AI 不会因步骤多而疲劳出错。1.2 你觉得很简单的AI 可能反复踩坑用户说“帮我看看 A 渠道的申请单”人听到A 渠道立刻知道指的是通过该渠道提交的申请单。但 AI 面对的歧义是A 渠道是提交渠道submit_channel还是来源系统source_system如果是提交渠道A 渠道对应的是该渠道下全部子渠道的 ID 集合还是只有某个特定子渠道用户说的是泛指的渠道还是某个具体的子渠道如A 渠道移动端前者应展开为所有子渠道后者只是单一 ID。人一秒完成的语义消歧AI 需要经历完整的实体解析流程——先判断维度归属再执行枚举匹配再处理候选项消歧才能最终确定查询参数。再看一个更典型的例子“截止目前各个部门的视频面试完成量”业务熟练的人一眼知道视频面试是一个面试形式名称。AI 面对的是一个三层消歧难题第一层词义归属。视频面试属于哪个维度用户说实际含义正确维度各部门视频面试完成量视频面试是面试形式名称面试形式interviewFormat各部门初面完成量初面是面试阶段面试阶段interviewStage各部门远程完成量远程是协作方式协作方式collaborationMode三句话结构几乎一模一样但视频面试、“初面”、远程分别归属三个完全不同的维度。人凭业务经验瞬间区分AI 必须逐个匹配枚举表才能确定。第二层标准名称不匹配。即使 AI 正确判断出视频面试是面试形式在系统的面试形式分类里也可能找不到精确匹配——实际对应的可能是线上视频面试或云端面试等标准名称。AI 需要做模糊匹配可能返回多个候选还需要暂停流程、向用户确认。第三层语义交叉。AI 必须理解视频面试是整体概念面试形式名而不是视频协作方式“面试”面试阶段的某一环节的组合。如果错误拆分查出的是两个维度的交叉结果与用户意图完全不同。人的操作流程进入报表系统 → 面试形式筛选框输入 → 从下拉候选中选择 → 完成。UI 的分类筛选框已经帮人分好了维度用户根本不需要思考这个词属于什么维度。这就是 UI 与 AI 最本质的差别UI 给用户提供了结构化的上下文每个维度有哪些选项AI 没有 UI接口必须主动将这些上下文结构化地提供出来。1.3 设计启示AI 的强项AI 的弱项多条件组合查询语义消歧词属于哪个维度多接口逻辑编排枚举猜测不知道合法值范围格式化输出与汇总分析隐式上下文推断字段名含义、参数关联关系强项不需要你费心设计弱项才是 AI 友好接口设计的核心。设计 AI 友好的接口本质上是在弥补 AI 缺失的视觉直觉——把人通过 UI 一眼获取的信息通过结构化的方式塞进 API 里。二、五个设计原则原则一返回值要自描述——AI 没有 UI返回值是它的全部视野UI 通过标签文字、下拉框选项、禁用态按钮传递上下文AI 只有接口返回值。接口不自描述AI 就只能猜。枚举字段永远同时返回编码和描述接口只返回status: UNDER_REVIEW或status: 3AI 回复用户时只能原样输出——用户完全看不懂。解决方案是同时返回可读描述// ❌ AI 不知道 UNDER_REVIEW / 3 代表什么{status:UNDER_REVIEW}{status:3}// ✅ AI 直接使用 statusDesc 向用户展示{status:UNDER_REVIEW,statusDesc:审核中}这不只是 AI 友好——前端展示同样受益是一次多方受益的改造。关联实体同时返回 ID 和可读名称消除 N1 问题接口只返回operatorId: 10086展示姓名还需再调一次查询接口。如果单次结果包含 N 条记录、每条的处理人各不相同就产生了经典的N1 查询问题——1 次主查询 N 次关联查询。// ❌ AI 需要额外 N 次调用才能展示姓名{operatorId:U10086}// ✅ 后端一次 batch 查询消除 N1{operatorId:U10086,operatorName:张三}返回可执行的操作列表而不只是当前状态接口只告诉 AI 当前是什么状态但 AI 下一步能做什么、能调哪些接口——完全不知道。// ❌ AI 只知道现在是什么状态不知道下一步能做什么{status:UNDER_REVIEW,statusDesc:审核中}// ✅ 当前状态 可执行操作清单{status:UNDER_REVIEW,statusDesc:审核中,availableActions:[{action:approve,desc:审批通过},{action:reject,desc:驳回申请},{action:transfer,desc:转交他人}]}这是HATEOASHypermedia As The Engine Of Application State思想在 AI 场景下的实践——REST 架构成熟度模型Richardson Maturity Model第 3 级定义的原则响应自身携带接下来能做什么的导航信息客户端不需要提前背下所有业务规则。就像浏览网页不需要背所有 URL页面上的链接和按钮告诉你下一步能去哪——availableActions对 AI 起的是同样的作用。人类 UI 里可见即可得通过下拉框和按钮实现AI 的UI就是接口返回值本身。原则二失败时给结构化诊断——AI 靠返回信息自我纠正AI 调接口出错是常态不是异常。和人不同——人会看日志、查文档、搜索引擎AI 只有接口返回的信息。错误响应不结构化AI 的自愈能力直接归零。一个优秀的结构化错误码设计示例error.code语义AI 的下一步动作SUCCESS成功进入结果处理INVALID_FORMAT输入格式错误客户端问题检查参数格式修正后重试UNRESOLVABLE_CONDITION有无法识别的条件需用户介入告知用户哪些条件系统不支持请求提供替代词MULTIPLE_CANDIDATES有多候选需用户确认展示候选列表给用户等待选择后重新发起查询VALIDATION_FAILED服务端参数校验失败读取错误详情针对性修正AI 靠error.code就能构建决策树判断需要等用户确认、“需要自行修正重试还是不可恢复”。如果所有错误都返回同一个码加一段自然语言描述AI 必须做文本理解来分类——增加了一层不确定性。这与 HTTP 状态码的设计哲学一致2xx/4xx/5xx 让客户端不需要解析响应体就能判断大类结果。面向 AI 的错误码应遵循同样的原则——机器可读的状态分类。// ✅ AI 可以精确自愈知道是哪个字段出了什么问题、应该怎么修{ok:false,error:{code:VALIDATION_FAILED,field:requestType,message:requestType 值 99 不合法,suggestion:合法值PROMOTE晋升评审, ADJUST薪资调整, TRANSFER岗位调动, LEAVE离职申请}}// ❌ AI 无从下手不知道哪里错了不知道怎么改{ok:false,message:参数错误}suggestion字段相当于人类在 UI 上看到的表单校验提示告诉 AI 怎么改才对一轮即可自愈。原则三参数语义化——命名贴业务不贴存储实现后端接口的参数命名往往反映的是存储层实现而非业务语义。看一个典型的抽象场景对比语义化命名AI 能直接理解存储层命名AI 需要外部映射才能理解departmentorgNodeCodeapprovalStatusflowStateCodesubmissionChannelsrcChannelTypeFlagreviewerassigneeIdLongrequestTypebizTypeCodeArr如果让 AI 直接使用存储层字段名它需要记住几十个字段的命名规律为什么部门字段叫orgNodeCode而不是department为什么业务类型字段要加Arr后缀为什么审批人字段包含Long类型提示这些命名是存储层的历史遗产AI 没有途径推断。结果是要么把这张映射表硬编码在 AI 工作流指令集Skill里要么在中间层写一个翻译模块——无论哪种方式都是在为历史债务买单。设计建议// ✅ 参数名贴近业务语义AI 可直接理解和填写{filters:{department:产品部,requestType:晋升评审,approvalStatus:审核中}}// ❌ 参数名暴露存储实现AI 必须靠外部映射才能正确填写{filters:{orgNodeCode:ORG_001,flowStateCode:1,bizTypeCodeArr:[0,1,2,...]}}如果由于历史原因接口必须保留内部参数格式至少在 CLI 层做一次翻译——让面向 AI 的命令参数保持语义化翻译工作由 CLI 层承担。这是 CLI 作为防腐层Anti-Corruption Layer的核心价值之一在不修改后端 API 的前提下为 AI 消费者提供语义化接口。原则四批量优先——消除 N1降低多轮调用成本AI 和人调接口的成本模型有本质差异。人操作系统网络请求是异步的等待响应的几百毫秒无感知整体是并行的用户体验。AI 调接口每次调用意味着一轮推理上下文的完整处理——读取返回值、判断成功与否、决策下一步。如果需要串行发起 N 次单独请求才能获取 N 条数据就是 N 轮串行推理开销同时也放大了每一步出错的概率。具体影响场景N1 问题批量化影响查 10 个审批单详情10 次串行调用支持批量输入后降为 1 次关联实体 ID→名称转换N 条数据 × 1 次转换接口后端 batch 反查后降为 0 次额外调用审批列表 聚合统计2 次分开调用一次查询同时返回列表和聚合结果设计建议查询接口支持批量输入如--request-id ID1,ID2,ID3,...。对后端来说是一次IN查询的改造对 AI 来说是数量级的调用开销节省。原则五写操作接口必须幂等——AI 的重试行为与人完全不同一个常被忽视的要点写操作接口的幂等性对 AI 消费者比对人类消费者重要得多。人操作 UI 时提交按钮通常有防重复点击保护即使误触人会感知到异常按钮灰掉、弹出提示并停止操作。AI 调用写操作接口时如果遭遇网络超时或响应解析异常AI 的标准决策是重试。如果接口不幂等重试就可能造成业务重复——重复提交审批、重复发送通知、重复触发下游工作流。AI 不像人那样能从 UI 反馈中感知到已成功它只能依赖接口返回值来判断是否需要重试。设计建议// 写操作接口使用 idempotencyKey 保证幂等POST/approval/submit{requestId:REQ20260422001,idempotencyKey:submit-REQ20260422001-operator-U1001// 调用方生成相同 key 只处理一次}// 接口响应中明确告知是否为重复请求{ok:true,isDuplicate:false,data:{...}}声明幂等语义后AI 可以安全重试失败的写操作而不需要先查询当前状态再决定是否重试——这简化了 AI 的决策逻辑同时避免了业务重复的风险。三、一句话总结设计 AI 友好的接口本质上是在把人通过 UI 一眼获取的信息结构化地塞进 API 里把人看下拉框获取的合法枚举放进xxxDesc和availableActions把人凭经验完成的 ID→名称转换在后端 batch 完成后随正文返回消除 N1把人看表单校验提示获取的修复建议放进结构化error.suggestion把人在 UI 里隐式感知的维度划分显式化为语义化参数名称把人点确认后浏览器的防重复提交转换为接口层的幂等性保证UI 帮人类用户完成了这些决策接口设计要为 AI 消费者完成同样的工作。四、结语不要等最佳实践AI 能力在月级别迭代。今天必须依赖大量手写枚举映射才能完成的语义消歧也许明天模型就能直接理解业务领域的概念体系。等行业沉淀出最佳实践再动手是一个糟糕的策略——等到的时候起点可能已经变了。而且AI 辅助实施本身就大幅降低了试错成本。接口改造、适配层实现、联调验证全程可由 AI 执行人只需做判断和验证——一次尝试的成本从开发者写几天代码降低到AI 写 人审小时级别。你以为复杂的事多接口编排、多维聚合统计AI 做起来很轻松你以为简单的事选个枚举、改个状态对 AI 来说可能格外困难。好的接口设计本质上是在弥合这个认知差。这些认知不难但需要你真正跑一遍才能深刻体会。最佳实践不是等出来的是边干边讨论出来的。