☰
Postman API秒变Codex智能体Skill:OpenAPI+Skill实战指南
2026/10/10 12:03:27 网站建设 项目流程

把Postman里调试好的API集合,直接变成智能体Codex能调用的Skill,这件事我前前后后折腾了小两周。最开始的想法特别朴素:后端服务有一堆接口,我平时都是靠Postman保存请求、切环境、测参数,墙上的工作流已经很熟练了。可一旦想让Codex接管这些API,它就像个手动党,不给它一份“说明书”,它永远只会乱猜URL、拼错请求头。后来我找到一条还算顺的路:用Postman作为API资产入口,把接口整理成OpenAPI描述,再包一层Skill外壳,让Codex看一眼就能自己调用。今天就把这套思路和完整实操步骤写出来,适合那些已经用Postman管接口、又想把自己的服务能力开放给AI智能体的人。

1. 这个项目到底要做什么:从Postman里的API到Codex的Skill,一步打通

1.1 为什么说Postman是最好的API素材源

我见过很多团队搞“智能体接入内部API”,第一步就卡在素材整理上:有的让智能体直接读后端代码,结果代码里藏着十几个环境变量,读半天也不知道线上地址是什么;有的让AI助手对着文档网站硬啃,文档更新不及时,模型就被带偏。可Postman不一样,绝大多数开发者的日常接口联调、测试、场景编排,都是在Postman里完成的。集合(Collection)里已经有了完整的请求方法、路径、请求头、请求体示例、参数说明,甚至连环境变量、鉴权方式都是现成的。

我的经验是:与其从零写一份给智能体看的API说明书,不如直接把Postman里已经调通的请求“翻译”成标准格式。所有接口是否可用、是否鉴权、返回结构长什么样,Postman集合已经用最真实的方式记录下来了。你甚至不需要额外去问后端同事,“这里为什么要有这个Header”,你翻一下当时调试成功的请求就知道了。

1.2 Codex Skill是什么:一段让智能体学会“按说明书办事”的封装

聊Codex Skill之前,先澄清一个概念:在AI编程智能体的语境里,Skill并不是一个高深的东西。它更像是一份“岗位培训手册”,把某个特定领域要怎么做、有哪些工具、哪些边界约束,以结构化文件的形式告诉智能体。让智能体在遇到对应场景时,不是凭空发挥,而是按手册去调用能力。

打个比方:Skill就像是给新员工的一本《客户系统操作手册》,里面有目标、有流程、有你能用的API清单,也有哪些操作不能碰。Codex读到SKILL.md之后,会把这些信息当作上下文的一部分,遇到相关任务就知道“该去调用哪个接口、怎么组装请求”。而我们要做的,就是把Postman里的API能力,精心打包成这么一份手册。这样Codex就不再只是一个纯粹写代码的助手,它能直接操作真实的业务系统,完成查询、创建、修改数据等任务。

1.3 思路拆解:API能力 → OpenAPI描述 → Skill外壳

整个项目其实就是一条流水线,我会反复用到三个层次:

  • 第一层是API能力本身:以Postman集合为源头,既有请求细节,也有调试验证记录。
  • 第二层是API描述:用OpenAPI规范(也就是Swagger规范)把每个接口的路径、参数、响应模型、鉴权方式统一描述出来。这是目前绝大多数智能体、代码生成工具、接口平台都能识别的“通用语言”。
  • 第三层是Skill外壳:在OpenAPI描述外面,再补上SKILL.md这样的技能说明文件,告诉Codex什么时候该用这套API、怎么编排请求、有哪些坑要避开。

用一句话概括就是:把Postman里的接口资产,先翻译成机器可读的OpenAPI文件,再裹上智能体需要的“使用说明书”。后面的所有内容,都是围绕这条流水线展开的。

2. 动手前先搞清楚的核心机制

2.1 OpenAPI规范:Postman和智能体之间的通用语言

没有OpenAPI之前,一个接口要传递给另一个系统,最常见的方式是复制一份“接口文档Word”,或者截个Postman的请求截图。可这些对智能体来说都不够结构化,模型要么理解不了截图里的文字,要么得靠猜测去解析参数。OpenAPI解决了这个问题,它用一套固定的YAML或JSON结构描述API,机器和人(包括大模型)都能读。

具体来说,OpenAPI文件会包含这几块关键信息:

  • openapi:版本号,比如3.0.3。
  • info:接口服务的标题、版本、描述。
  • servers:可用的服务地址,也就是baseUrl。
  • paths:每个路径的HTTP方法、操作ID、参数、请求体、响应结构。
  • components:复用的安全方案、响应模型、参数模型。

只要有了这样一份文件,Codex或者其他智能体就能推断出“查订单用GET /orders”,“创建订单用POST /orders”,并且清楚该往body里塞什么字段。我一直觉得,OpenAPI就是接口界的“书架分类标签”,它让本来散落各处的接口信息有了一套统一的索引规则。

我实际操作时,不会手写OpenAPI,而是从Postman导出。Postman本身支持导出Collection v2.1,也支持直接导出OpenAPI 3.0格式文件。导出后再用编辑器扫一眼,该补的描述补上,基本就够了。

2.2 Skill文件结构:SKILL.md + 接口定义 + 运行脚本

上一篇内容已经提到,Skill不能只是一个OpenAPI文件,还要有足够的上下文。我最终采用的目录结构是这样:

~/.codex/skills/company-erp-api/ ├── SKILL.md ├── openapi.yaml ├── config.json └── scripts/ └── api_wrapper.py

这里每个文件的职责非常清晰:

  • SKILL.md是技能的入口,用自然语言描述“这个技能能做什么、什么场景下调用、有哪些注意事项”,Codex会优先读取它。
  • openapi.yaml是接口的机器可读定义,Codex根据它来拼接请求。
  • config.json存放动态配置,比如服务器地址、环境标识、超时时间,这些信息不该写死在Skill描述里。
  • scripts/api_wrapper.py是一个轻量封装,把OpenAPI定义和实际HTTP调用连接起来,处理认证注入、错误码转换等逻辑。

我见过一些人只放一个SKILL.md,把接口信息全写在里面,短小的工具还行,但只要是超过三五个接口的服务,智能体就开始懵,因为它无法从长篇大论的描述里稳定提取参数。所以我的建议是:SKILL.md负责“决策”,OpenAPI负责“细节”,脚本负责“执行”,三者各干各的。

2.3 认证、参数、分页这些老问题怎么在Skill里体现

用Postman测接口的时候,认证经常是“Pre-request Script”里动态算出来的,或者直接放在环境变量里。到了Skill里,这个问题必须重新设计,因为智能体不能像人一样手动在Postman里换Token。

我在实际项目中把认证方式分成三类处理:

  • 静态Token:直接存在config.json里,Skill加载时读取并注入请求头。
  • 动态Token:需要先调用登录接口获取,这时我会在api_wrapper.py里写一个缓存Token的逻辑,过期后自动重新获取。
  • 签名认证:比如某些内部系统要求每个请求加上时间戳和签名,这类逻辑不适合让智能体思考,我会把签名算法封装到脚本里,只给智能体一个“无感调用”的接口。

参数和分页也一样。OpenAPI里可以定义page、page_size、limit这些参数,可智能体不一定知道“第一页从哪里取”。经验是在SKILL.md里明确写一句话:“列表接口默认请求第一页,如需更多数据请通过分页参数递增页码。”这样Codex就不会傻乎乎把所有结果一次性拉完。

3. 实操:把Postman集合变成Codex能用的Skill

3.1 第一步:在Postman里把接口调通并导出OpenAPI

这一步看起来基础,却是整个流程的命根子。我建议在Postman里建一个独立的Collection,专门放需要开放给智能体的接口,每个请求都要保证“当前环境”下调试通过。检查项包含:URL路径正确、请求方法正确、请求头里有必要的Content-Type、鉴权信息能通过、Body示例能跑通。

准备工作做完后,导出操作如下:

  1. 选中目标Collection,点击右侧的“...”菜单。
  2. 选择“Export Collection”。
  3. 在导出格式里选择“OpenAPI 3.0”或“OpenAPI 2.0”,我建议直接选3.0。
  4. 导出后会得到一个JSON文件,建议再把内容转成YAML方便阅读,很多工具如swagger-cli可以直接转换。

导出之后一定不要直接用,先检查几个地方:

  • servers里的地址是否是你真正要用的,Postman经常会把环境变量里的URL带出来,但可能有格式残留。
  • operationId是否唯一,Codex调用接口时往往靠operationId区分操作,缺失或重复都会造成混乱。
  • 请求体示例是否存在,OpenAPI里没有example的话,智能体就得靠字段名猜值,概率不高。

提示:Postman导出OpenAPI,本质上是把Collection里的请求、参数、示例组织成统一描述。如果发现导出的文件结构不完整,大多数原因是Postman集合本身缺少请求示例或参数描述,并不是导出功能有问题。

下面是我导出后简化过的示例:

openapi: 3.0.3 info: title: Company ERP API version: 1.0.0 servers: - url: https://api.example.local/v1 paths: /orders/{order_id}: get: operationId: getOrderDetail parameters: - name: order_id in: path required: true schema: type: string responses: '200': description: 获取订单详情成功

3.2 第二步:搭建Skill目录和SKILL.md

拿到OpenAPI文件后,我才会正式创建Skill目录。目录名不要用中文,也不要用空格,Codex读取文件路径时,纯净的短横线命名最稳。我用的命名规则是服务名-功能域名,比如erp-orders-api。

在目录下新建SKILL.md,里面用结构化、带明确触发条件的方式描述技能。参考格式如下:

--- name: erp-orders-api description: 提供订单查询、创建、更新能力。当用户需要查询订单详情、批量拉取订单列表、创建新订单时使用。 --- # ERP订单管理API技能 ## 适用场景 - 用户询问“某个订单现在什么状态” - 用户要求“查最近一周的订单” - 用户需要“创建一个新订单” ## 关键约定 - 查询订单列表时,默认按创建时间倒序 - 调用创建订单接口前,必须先确认商品SKU是否存在 - 所有接口都需要在请求头注入 Access-Token,脚本会自动完成 - 订单金额为整数,单位是分,不要转成元 ## 接口入口 完整接口定义请读取 openapi.yaml,不要自行修改接口路径。

这里我特别注重“关键约定”这个板块。智能体有了这些约定,才不会做出特别反直觉的操作。比如订单金额单位是分,这要是不写清楚,模型完全可能把100元当成100传递,导致数据错误。

3.3 第三步:把openapi.yaml和工具描述对接起来

光有SKILL.md还不够,因为Codex虽然知道有这些接口,但具体怎么拼请求、怎么处理响应,还得靠openapi.yaml配合config.json和脚本。

config.json我一般这样写:

{ "base_url": "https://api.example.local/v1", "access_token": "这里是动态占位符", "token_endpoint": "/auth/login", "timeout_seconds": 15 }

脚本部分,api_wrapper.py的核心逻辑非常简单:读取OpenAPI文件里的paths信息,根据方法名拼接URL,注入Token,发HTTP请求,返回解析后的JSON。这里我给出一个简化版本:

import json import requests import yaml CONFIG_PATH = "config.json" OPENAPI_PATH = "openapi.yaml" with open(CONFIG_PATH, "r", encoding="utf-8") as f: config = json.load(f) with open(OPENAPI_PATH, "r", encoding="utf-8") as f: spec = yaml.safe_load(f) TOKEN = None def _ensure_token(): global TOKEN if TOKEN: return TOKEN resp = requests.post(config["base_url"] + config["token_endpoint"]) TOKEN = resp.json()["access_token"] return TOKEN def call_operation(operation_id: str, params: dict = None, body: dict = None): for path, methods in spec["paths"].items(): for method, detail in methods.items(): if detail.get("operationId") == operation_id: url = config["base_url"] + path headers = {"Accept": "application/json", "Authorization": f"Bearer {_ensure_token()}"} resp = requests.request( method.upper(), url, headers=headers, params=params, json=body, timeout=config["timeout_seconds"], ) resp.raise_for_status() return resp.json() raise ValueError(f"operation {operation_id} not found")

这里我只做了一件核心的事情:把“该怎么调接口”的重复劳动从智能体手里拿掉。Codex不需要自己写requests请求,只需要确认调用哪个操作、传什么参数。对模型来说,少一点低层次的编码,多一点高层次的意图理解,可靠性会高很多。

如果你不想写代码,也可以不建脚本,直接在SKILL.md里写明“用Python的requests库调用openapi.yaml中的接口”,让Codex自己生成代码。但是那样每次都会浪费一些上下文token,而且可能每次生成的调用方式都不一样。我推荐至少封装一个稳定版本。

3.4 第四步:在Codex里测试调用

Skill目录和文件都准备好之后,我建议先在Codex里做一组冒烟测试,不要直接上生产。

我一般会连续测试这几个场景:

  1. 让Codex直接描述这个Skill是干什么的,看它能不能准确读出来。
  2. 让它根据SKILL.md里的“适用场景”触发某个查询接口。
  3. 让它主动读取openapi.yaml,并描述某个接口需要哪些参数。
  4. 让它创建一个资源再查回来,验证写操作链路。

测试时如果Codex完全没反应,先检查Skill目录是否放到了正确的加载路径。有些版本是从某个配置目录读取,有些版本需要你在对话开头显式提到这个Skill名称。我在实际测试环境里,只要在对话中说出“使用erp-orders-api技能”就能触发,但每个环境不太一样,这一点我会在第4节展开。

还有一个很重要的测试点:要让Codex知道“不需要让用户手动输入Token”。因为我们的目标是让API能力被智能体透明地使用,而不是每次都要用户提供密钥。把Token藏在脚本和配置里,既方便又安全。

4. 踩过的坑和常见问题实录

4.1 OpenAPI导出的兼容性问题

Postman导出的OpenAPI文件,我遇到最多的两个问题:一是路径参数和请求体字段描述为空,二是响应定义过于简单。空描述会导致智能体在调用时不知道参数含义,只能靠猜。

解决办法很简单:导出后,我会花半小时人工过一遍OpenAPI文件,把每个参数的description补全,把响应的example加上。千万别嫌麻烦,这一步的投入,能帮你节省后面排查“为什么智能体传了错误类型参数”的时间。

另外,Postman的“Collection v2.1”格式和“OpenAPI”格式不是一回事。你要是选了Collection v2.1,会发现Codex根本读不出标准的paths结构。一定要在导出时正确选择OpenAPI格式。

4.2 认证信息差点被写进Skill文件

第一次做的时候,我图方便直接把Token写进了SKILL.md,结果Codex在回答用户问题时,直接把Token也当作示例输出给了用户。虽然那是测试环境的Token,但也吓得我立刻改成了脚本注入的方式。

现在的原则是:所有密钥、Token、签名算法,一律不进入SKILL.md正文。config.json只保留占位符或者运行时加载的本地密钥;签名算法放在脚本里;SKILL.md只描述“系统会自动完成认证”。这样做还有另一个好处——哪怕你把SKILL.md直接公开分享,也不会泄密。

4.3 智能体“自作主张”传错参数

当接口参数比较多时,Codex有时会脑补出一些不存在的字段,或者把日期字符串格式传错。比如我有个接口约定日期是YYYY-MM-DD,但Codex却传了2025/01/01。这不是模型蠢,而是OpenAPI文件里缺少明确的格式约束。

解决方法是给OpenAPI参数加上format和example,并且在SKILL.md里再强调一次格式约定。比如:

parameters: - name: start_date in: query required: true description: 开始日期,格式为 YYYY-MM-DD example: "2025-04-01"

有了双重保险,Codex几乎不会再改格式。如果还是传错,就在SKILL.md的“关键约定”里再加一条更醒目的规则。

4.4 权限边界与技能失效排查

给智能体开放API能力,最让人担心的是它会顺手做掉一些不该做的操作。比如,我只是让它查询订单,它却自己调用了删除接口。要避免这个问题,我通常会这么做:

  • 在OpenAPI文件里,只保留智能体允许调用的路径,不需要的路径直接删掉,而不是靠描述去劝它别用。
  • 在SKILL.md里写清楚“本技能只允许查询操作,禁止更新和删除”。
  • 在脚本层做白名单校验,call_operation里维护一个允许调用的operation_id列表,不在列表里的直接拒绝。

如果Codex明明该用Skill却完全没反应,先不要怀疑模型,按下面几步排查:

  1. 检查Skill目录是否在正确路径,文件名是否用了特殊字符。
  2. 检查SKILL.md的name字段是否唯一,两个Skill重复描述会互相干扰。
  3. 在对话里手动提到技能名,看能否被触发。
  4. 查看OpenAPI文件是否能被正确解析,可以用python -c "import yaml; yaml.safe_load(open('openapi.yaml'))"验证。

5. 我的最终心得与后续扩展

5.1 什么场景最适合用这套方案

我自己试下来,这套“Postman导出OpenAPI + Skill外壳”的组合,最适用的场景是:你有一批已经稳定运行的HTTP接口,并且希望智能体在业务中能像人一样去操作它们。比如内部订单查询、用户数据同步、内容发布、指标查看等。这些API通常已经有Postman集合管理,接口数量在几个到几十个之间,用Skill方式整理并接入,性价比很高。

反过来,如果接口还在频繁变动,或者压根没有稳定环境,那我建议先别接智能体。Skill文件里的示例和约定,一旦接口变更,就会变成误导信息。接口不稳定的时候,维护成本比收益高。

5.2 后续还可以这样扩展

对于这套方案,我不会停在单个Skill上。后面可以考虑几个方向:

  • 多个Skill统一管理:把不同业务域的Skill组织成独立目录,然后用一个总索引文件,让Codex知道“查订单用订单技能,查库存用库存技能”。
  • 从Postman到Git的自动化流程:Postman集合可以通过API或命令行工具同步更新,OpenAPI文件纳入Git仓库,技能更新走代码评审流程。
  • 增加测试用例:在每个Skill里放一个sample_tests.sh,Codex在修改Skill相关代码后,可以自动跑一遍接口冒烟测试,确保可用性。

最后分享一个实际操作中的小技巧:SKILL.md的描述不要写得太“全”。很多人在写技能时,巴不得把所有情况都列一遍,结果描述过长,反而模糊了核心触发词。我发现最适合的长度是150到300字之间,把最核心的“何时用、怎么用、别做什么”讲清楚就行。剩下的细节,交给OpenAPI和脚本去兜底。这个度,跟我前面说的“SKILL.md负责决策,不要负责执行细节”是完全一致的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询