反模式:25 个破坏智能体体验的常见错误
以下是网站和 API 破坏智能体体验最常见的方式。大多数错误一旦你看到就会觉得显而易见——但在有人指出来之前,它们却隐形得难以察觉。
1. 仅限浏览器的认证流程
认证需要视觉浏览器交互,没有可编程的替代方案。点击“使用 Google 登录”,等待弹窗,解决验证码,查看邮箱获取验证码。人类可以做到这一点,但自主智能体做不到。
解决方法: 提供 OAuth 设备授权流程、带有作用域限制的 API 令牌,或 auth.md 作为可编程替代方案。
2. “出错了”错误
{ "error": "Something went wrong" }
没有错误码,没有分类,没有恢复指导。智能体卡住了。
解决方法: 返回结构化错误,包含类型、错误码、retryable 标志和恢复指导。
3. PDF 文档
产品文档是一个 200 页的 PDF。不可搜索,不可链接,智能体无法解析。信息在技术上存在,但实际上不可见。
解决方法: 将文档发布为 Markdown 或 HTML。添加一个 llms.txt 来总结关键页面。
4. 没有 Retry-After 的速率限制
HTTP/1.1 429 Too Many Requests
Content-Type: text/html
没有 Retry-After 头。没有任何关于何时重试的信息。智能体只能猜测。
解决方法: 始终包含 Retry-After 和一个结构化的 JSON 响应,包含速率限制详情。
5. 静默变更
一个 POST /contacts 端点,会发送欢迎邮件、创建 CRM 记录并扣款信用卡——这些都没有在任何地方文档化。智能体创建一个“联系人”,却意外地发送了三封邮件并扣了信用卡。
解决方法: 在端点描述和 MCP 工具元数据中记录所有副作用。使用 sideEffects 和 destructive 标志。
6. 杂烩端点
一个端点根据你发送的参数做五件不同的事。/api/do?action=create&target=contact&also_send_email=true&format=full——这迫使智能体去理解一个端点的无文档化分支逻辑。
解决方法: 一个动作,一个端点。create_contact、update_contact、delete_contact——而不是 /api/do。
7. 100 个工具没有分类
一个 MCP 服务器,将 100 个工具放在一个扁平列表中,没有任何组织。智能体必须读完所有 100 个描述才能找到它需要的那个。
解决方法: 将工具分组到逻辑类别中。使用一致的 verb_noun 命名。在你的 llms.txt 顶部提供摘要。
8. 漂亮的网站,无用的 API
精美的落地页,有动画、客户评价和定价卡片。但 API 文档是 2019 年的一个 Swagger 页面,一半的端点都缺失了。
解决方法: 对 API 文档和视觉设计投入同等精力。API 就是智能体的 UI。
9. 仅限 JavaScript 的网站
所有内容都在客户端渲染。服务器返回的 HTML 是一个空白的 <div id="root">。提取页面的智能体什么也得不到。
解决方法: 对关键内容进行服务端渲染,或至少提供一个全面的 llms.txt 来描述能力。
10. 认证迷宫
要获取 API 密钥:注册 → 验证邮箱 → 填写开发者申请 → 等待批准 → 创建项目 → 生成密钥 → 复制密钥 → 配置环境。每一步都需要浏览器。
解决方法: 支持设备授权流程、自助 API 密钥,或通过 auth.md 实现智能体原生认证。
11. 全局 API 密钥
一个 API 密钥可以做所有事。没有作用域,没有过期时间,无法将动作归因到特定的智能体或用户。一旦泄露,整个账户就完了。
解决方法: 有作用域、有时效的令牌。渐进式权限。每个令牌的审计追溯。
12. API 上的验证码
为阻止机器人而在 API 端点上加验证码。它们从定义上就阻止了智能体。如果你需要限速,就应该使用速率限制。
解决方法: 从 API 端点移除验证码。改用速率限制、IP 白名单或已认证请求配额。
13. 扁平的错误码
{ "error": "invalid_request" }
哪个字段是无效的?智能体应该做什么?这没有给智能体任何有用信息。
解决方法: { "error": { "type": "validation_error", "code": "EMAIL_REQUIRED", "field": "email", "message": "Email is required", "fix": "Add a valid email address to the request body" }}
14. 神秘的状态码
错误也返回 200 OK。部分失败也返回 200 OK。什么都是 200 OK。智能体无法判断操作是否成功。
解决方法: 使用正确的 HTTP 状态码。201 表示创建,400 表示验证错误,409 表示冲突,429 表示速率限制,500 表示服务器错误。始终如此。
15. 无文档化的分页
{ "results": [...50 items...] }
还有下一页吗?智能体如何获取?没有 has_more,没有 next_cursor,没有 Link 头。智能体不知道它是否获取了全部数据。
解决方法: 始终包含分页元数据:{ "data": [...], "meta": { "has_more": true, "next_cursor": "abc123" }}
16. 消失的状态
智能体创建了一条记录,但响应中没有 ID。或者智能体启动了一个工作流,但无法检查其状态。或者智能体执行了一个动作,但无法撤销。
解决方法: 每次创建都返回已创建的资源及其 ID。每个工作流都返回一个状态 URL。每个变更都包含撤销信息。
17. 不一致的命名
GET /contacts 返回 { "contacts": [...] },但 GET /deals 返回 { "data": [...] }。字段名在 snake_case 和 camelCase 之间交替。同一个字段在一个端点叫 id,在另一个端点叫 contact_id。
解决方法: 建立并强制执行命名约定。对所有响应使用相同的包络结构。保持一致。
18. 庞大臃肿的响应
GET /contact/123 返回 200 个字段,包括各含 50 个字段的嵌套对象。智能体只问了姓名和邮箱;却收到了联系人的整个生平加上 30 条关联记录。
解决方法: 支持字段选择:GET /contacts/123?fields=name,email。默认返回摘要,并附带指向展开资源的链接。
19. 无文档化的副作用
文档说 POST /deals 创建一个交易。但没提到的是:它还会向交易负责人发送邮件、创建预测条目并触发 Slack 通知。对人类是透明的(他们看到通知),对智能体是不可见的。
解决方法: 在端点/工具描述中记录所有副作用。更好的是:在动作定义中将副作用显式化。
20. 强制浏览器流程
“点击这里查看你的发票。”“在此链接下载你的报告。”“访问此页面接受条款。”每次智能体需要人类通过浏览器点击时,都是一次破坏自主性的交接。
解决方法: 为每个浏览器操作提供 API 等效功能。GET /invoices/123/pdf 而不是“点击下载”。POST /terms/accept 而不是“访问此页面”。
21. 未版本化的 API
https://api.example.com/contacts——没有版本前缀。当你更改响应格式时,每个智能体集成都会在没有警告的情况下崩溃。
解决方法: 始终为你的 API 添加版本:https://api.example.com/v1/contacts。对于小改动使用请求头版本管理。
22. 永久万能令牌
认证返回一个永不过期的单一令牌,拥有所有权限,且不能被作用域限制或轮换。一旦泄露,你就得撤销一切。
解决方法: 使用短期令牌配合刷新令牌。有作用域的访问。每个智能体的归属标识。
23. “联系客服”错误
{ "error": "Please contact support for assistance" }
智能体通常无法打开客服工单。即使可以,关于出了什么问题的相关信息也已经丢失了。
解决方法: 在响应中包含错误详情。如果需要人工介入,提供结构化的交接:{ "error": { "type": "account_locked", "action": "contact_support", "support_url": "https://...", "reference": "INC-12345" }}
24. 不一致的嵌套资源
GET /contacts/123 能正常工作,但 GET /contacts/123/deals 返回 404。有些联系人有嵌套交易,有些没有,且没有规律。
解决方法: 一致的资源嵌套。记录哪些子资源存在。使用链接:{ "contact": { "id": "123", "_links": { "deals": "/contacts/123/deals" }}}
25. 仅面向人类的设计评审
设计评审流程只考虑人类用户。没有面向智能体的可访问性评审。没有在类似智能体的条件下测试 API 响应。设计检查清单中没有 llms.txt。
解决方法: 将智能体体验添加到你的设计评审检查清单。在发布前用真实的智能体进行测试。
元反模式
所有反模式中最常见的一个:根本不曾考虑过智能体。 大多数智能体体验的失败,是因为在设计、开发或测试过程中,没有人将智能体视为一个用户角色。
解决方法不是技术性的,而是文化性的:在每次设计评审、每次 Sprint 演示和每次回顾中加上一个问题:“智能体能使用这个吗?”