1. 先把五个词摆到一张桌子上:Prompt、Agent、Skill、MCP、Claude Code 到底谁管什么
Prompt、Agent、Skill、MCP、Claude Code 这五个词经常被混着用,但它们其实处在完全不同的层级。Prompt 是你对模型说的一句话,Agent 是让模型自己循环干活的机制,Skill 是把一套做法封装成可复用的模块,MCP 是让模型安全调用外部工具的协议,Claude Code 则是把这些东西打包好的一个现成产品。适合谁?适合已经会用 ChatGPT 或 Claude 聊天、但一看到“Agent 框架”“MCP Server”“Skill 编排”就头大的人。
我试过把这五个概念拆开单独学,结果越学越乱,因为文档各讲各的,没有一个统一的运行环境让你看到它们怎么串起来。后来我换了个思路:用同一套 API Key 和 Base URL,从最简单的 Prompt 调用开始,一层一层往上加,每加一层就跑一次请求,看它到底变了什么。这样五个概念的边界自然就清楚了。
这篇文章就是按这个思路写的。你不需要先装一堆框架,只需要一个能发 HTTP 请求的环境(curl 或 Python 都行),加上一个统一的 Key。我会用 TaoToken 作为统一入口,因为它同时提供 OpenAI 兼容接口和 Claude 系列模型,Base URL 和 Key 一套就够,不用为每个概念单独配环境。下面从环境准备开始,每一步都有可复制的命令和配置。
2. 用 TaoToken 统一 Key 和 Base URL:一次配置,五层通用
在开始跑五层示例之前,先把“入口”统一掉。这一步很关键,因为后面 Prompt、Agent、Skill、MCP、Claude Code 如果各自用不同的 Key 和地址,排查问题时会疯掉。TaoToken 的 API 地址是https://taotoken.net/api,兼容 OpenAI 的/v1/chat/completions格式,同时也支持 Claude 系列模型。你只需要在官网注册后拿到一个 Key,后面所有层都用它。
先设置环境变量。Linux/macOS 下直接 export,Windows PowerShell 用$env::
export TAOTOKEN_API_KEY="sk-你的Key" export TAOTOKEN_BASE_URL="https://taotoken.net/api/v1"如果你用 Python,建议写一个最小的公共调用函数,后面每层都复用它,这样能清楚看到“变化只发生在调用方式上,而不是底层连接上”:
import os, json, urllib.request API_KEY = os.environ["TAOTOKEN_API_KEY"] BASE_URL = os.environ["TAOTOKEN_BASE_URL"] def chat(messages, model="claude-sonnet-4-20250514", tools=None): payload = {"model": model, "messages": messages} if tools: payload["tools"] = tools req = urllib.request.Request( f"{BASE_URL}/chat/completions", data=json.dumps(payload).encode(), headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, ) with urllib.request.urlopen(req) as resp: return json.loads(resp.read())这段代码就是后面五层的“底座”。你可以先跑一次确认连通:
curl -s https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"claude-sonnet-4-20250514","messages":[{"role":"user","content":"说一句你好"}]}'如果返回里有choices字段和内容,说明 Key 和 Base URL 都对了。如果返回 401,先检查 Key 有没有复制完整;如果返回local proxy failed或连接超时,检查 Base URL 是不是写成了https://taotoken.net/api(少了/v1)或者多了斜杠。这一步过了,再往下走。
注意:TaoToken 的 API 地址是
https://taotoken.net/api,实际请求路径要拼上/v1/chat/completions。官网是https://taotoken.net,注册和拿 Key 都在那里。不要把这两个搞混。
3. 五层逐级跑通:Prompt 调用、Agent 循环、Skill 封装、MCP 工具接入、Claude Code 执行
这一节是核心。我会按“从简单到复杂”的顺序,每层给一个可运行的最小示例,并说明它和上一层的区别。你可以在同一个 Python 文件里依次跑,观察每层新增了什么。
3.1 Prompt:一次请求,一次回答
Prompt 就是 messages 数组里的内容。你写什么,模型就按什么回答,回答完这次调用就结束。没有循环,没有工具,没有记忆。
resp = chat([ {"role": "system", "content": "你是一个简洁的助手,回答不超过50字。"}, {"role": "user", "content": "用一句话解释什么是 Prompt。"} ]) print(resp["choices"][0]["message"]["content"])跑通后你会看到一句简短回答。这就是 Prompt 的边界:它只管“这一次怎么说”,不管“下一步做什么”。很多人把 Prompt 写得很长很复杂,其实清晰比长度重要。如果你发现模型答偏了,先检查 system 里的约束是不是自相矛盾,而不是继续加字数。
3.2 Agent:让模型自己决定下一步
Agent 的本质是“循环 + 工具调用”。模型不再只回答一次,而是可以请求调用某个工具,拿到结果后继续思考,直到它认为任务完成。下面是一个最小 Agent 循环,用tools参数告诉模型有哪些工具可用:
tools = [{ "type": "function", "function": { "name": "get_weather", "description": "查询指定城市的天气", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"] } } }] messages = [{"role": "user", "content": "北京今天天气怎么样?适合跑步吗?"}] resp = chat(messages, tools=tools) msg = resp["choices"][0]["message"] while msg.get("tool_calls"): for call in msg["tool_calls"]: # 这里模拟工具返回,真实场景换成你的 API result = '{"city":"北京","weather":"晴","temp":22}' messages.append(msg) messages.append({ "role": "tool", "tool_call_id": call["id"], "content": result }) resp = chat(messages, tools=tools) msg = resp["choices"][0]["message"] print(msg["content"])这段代码跑起来后,模型会先请求get_weather,你返回模拟数据,它再基于数据回答“适合跑步”。这就是 Agent 和 Prompt 的区别:Prompt 是你说一步它做一步,Agent 是你给目标它自己拆步骤。注意,Agent 能调工具就意味着它能产生副作用,所以真实场景里权限控制必须提前想清楚。
3.3 Skill:把一套做法封装成可复用模块
Skill 不是 API 里的一个参数,而是一种组织方式。它把“某类任务该怎么做”写成一段固定的 system 提示或函数,下次直接调用,不用每次重新描述。比如你经常要让模型按公司格式写周报,就可以封装成一个 Skill:
def weekly_report_skill(raw_notes): return chat([ {"role": "system", "content": ( "你是一个周报助手。输出格式固定为:" "一、本周完成;二、下周计划;三、风险与求助。" "每条不超过两行,语气客观。" )}, {"role": "user", "content": raw_notes} ])["choices"][0]["message"]["content"] print(weekly_report_skill("修了登录bug,开了两次会,下周要做支付对接"))这个函数就是 Skill 的雏形:它把提示词、格式约束、语气要求都固化下来,调用者只需要传原始素材。Skill 的价值在于“稳定基线”,让每次输出不会因为提示词写法不同而忽好忽坏。但 Skill 不是越多越好,堆多了会互相冲突,边界清晰比数量重要。
3.4 MCP:用统一协议接入外部工具
MCP 是 Anthropic 提出的协议标准,目的是让模型连接外部工具时不用每个工具写一套适配。你可以把它理解成“工具接入的 USB-C”。在 TaoToken 的兼容接口下,MCP 工具最终也是以tools的形式暴露给模型,但工具的发现和调用遵循 MCP 协议。
一个最小的 MCP 风格工具定义如下:
mcp_tools = [{ "type": "function", "function": { "name": "query_database", "description": "查询销售数据库,返回指定月份的汇总数据", "parameters": { "type": "object", "properties": { "month": {"type": "string", "description": "格式 YYYY-MM"} }, "required": ["month"] } } }]然后把它传给 Agent 循环,模型就会在需要数据时请求调用。MCP 的关键点是:协议只负责“怎么接”,不负责“接进来之后怎么用”。你仍然需要 Agent 来规划、Skill 来规范、权限策略来控制。很多人以为接了 MCP 就自动会用工具,其实那只是第一步。
3.5 Claude Code:把上面四层打包成可执行产品
Claude Code 是 Anthropic 的编程 Agent 产品,它内置了 Agent 循环、文件读写、命令执行、代码搜索等能力,相当于把 Prompt、Agent、Skill、MCP 都集成好了。你不需要自己写循环,只需要给它目标。在 TaoToken 环境下,你可以通过配置 Base URL 和 Key 让它走统一入口。
Claude Code 的配置文件通常在~/.claude/settings.json或项目级.claude/settings.json,关键字段如下:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的Key", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }如果你用 CC Switch 或 Cline MCP 这类工具管理多个环境,三件套必须写全:Base URL、Key、Model ID。缺一个都会导致请求打不到正确模型。配置好后,在项目目录里运行claude,输入“帮我看看这个项目里有没有未处理的 TODO”,它就会自己搜索文件、读取内容、汇总结果。这就是“现成办公室”的意思:你不用从零搭 Agent,直接开工。
4. 逐层验证请求是否命中:用返回字段和日志确认每一层真的跑通了
跑通不等于命中。很多时候你以为 Agent 在调工具,其实模型只是编了一段看起来像工具调用的文本。所以每层都要有验证手段。
Prompt 层:看返回的choices[0].message.content是否有内容,finish_reason是不是stop。如果finish_reason是length,说明被截断了,需要调大max_tokens。
Agent 层:看返回的message里有没有tool_calls字段。如果有,说明模型确实请求了工具;如果没有,说明它选择直接回答。你可以在循环里打印每次tool_calls的function.name,确认调的是你定义的工具,而不是模型幻觉出来的名字。
Skill 层:对比两次调用的输出格式是否一致。如果第一次输出三段式、第二次输出一大段,说明 Skill 的 system 约束没生效,检查是不是被 user 内容覆盖了。
MCP 层:在工具执行函数里加日志,打印入参和返回。如果模型请求了工具但你的日志没打印,说明请求根本没到你的执行层,可能是工具定义格式不对或模型没识别。
Claude Code 层:运行claude --debug或在配置里打开日志,看请求实际发到了哪个 Base URL。如果日志里出现401或local proxy failed,说明 Key 或地址配错了。如果出现reading choices相关报错,通常是返回结构不符合预期,检查模型 ID 是否写错。
一个实用的验证命令是直接 curl 你的 Base URL,看返回的模型名和内容:
curl -s https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"claude-sonnet-4-20250514","messages":[{"role":"user","content":"ping"}]}' \ | python -m json.tool如果返回里有"model": "claude-sonnet-4-20250514",说明请求命中了正确模型。如果返回的模型名和你请求的不一致,说明中间有路由问题,需要检查 Base URL 是否被其他配置覆盖。
5. 常见报错排查清单:401、local proxy failed、reading choices、OAuth 分别怎么处理
这一节按真实报错来。你跑上面五层时,大概率会遇到下面几个。
401 Unauthorized:Key 不对或没带上。检查Authorization头是不是Bearer sk-xxx,注意 Bearer 后面有一个空格。如果你用 Claude Code,检查settings.json里的ANTHROPIC_API_KEY有没有写错。另外,Key 如果过期或被撤销也会 401,去官网重新生成一个。
local proxy failed:通常是 Base URL 写错或网络不通。TaoToken 的 API 地址是https://taotoken.net/api,请求路径要拼/v1/chat/completions。如果你在 Claude Code 里配的是ANTHROPIC_BASE_URL,填https://taotoken.net/api即可,不要多加/v1,因为 Claude Code 会自己拼路径。这个细节很容易搞反,建议先用 curl 验证一次。
reading choices 相关报错:一般是返回结构不符合预期。常见原因是模型 ID 写错,导致返回的是错误信息而不是正常 completion。检查model字段是不是你账号下有权限的模型。另外,如果你用了流式输出但代码按非流式解析,也会出现类似问题,确认stream参数和解析逻辑一致。
OAuth 相关报错:如果你用 Claude Code 的 OAuth 登录方式而不是 API Key,可能会遇到 token 刷新失败。在 TaoToken 统一入口下,建议直接用 API Key 方式,避免 OAuth 和自定义 Base URL 冲突。如果你同时装了多个 Claude 相关工具,检查环境变量有没有互相覆盖,尤其是ANTHROPIC_API_KEY和ANTHROPIC_BASE_URL。
还有一个隐蔽的坑:CC Switch 或 Cline MCP 里配置了多套环境,但当前激活的不是你改的那套。三件套(Base URL、Key、Model ID)必须同时检查,缺一个都会导致请求打到默认地址。建议每次改完配置后,用claude --debug看一次实际请求地址。
6. 下一步怎么用:按场景选入口,别为了学概念而学概念
五个概念跑通一遍之后,你会发现它们不是替代关系,而是分工关系。Prompt 解决“怎么说”,Agent 解决“谁来自动推进”,Skill 解决“怎么做得稳定”,MCP 解决“怎么接外部工具”,Claude Code 解决“在哪执行”。你不需要每个都自己搭,按场景选就行。
如果你只是想让回答更稳,继续打磨 Prompt 就够了,不用上 Agent。如果你有重复性流程,比如每天拉数据生成报表,那就用 Agent 加 Skill 封装起来。如果你要接数据库、GitHub、内部系统,先看有没有现成的 MCP Server,没有再用tools参数自己定义。如果你主要在写代码、改项目,直接用 Claude Code,把 Base URL 和 Key 配好就能开工。
统一 Key 的好处到这里就体现出来了:你不需要为每个概念单独申请账号、单独配环境。一套 TaoToken 的 Key 和 Base URL,从 Prompt 到 Claude Code 全部通用。想验证模型效果可以去模型对话页面直接试;想长期跑编码任务可以看 Coding Plan;接入过程中遇到报错,先查 API Keys 和接入文档,大部分问题那里都有说明。先把一条链路跑通,再往上加复杂度,比一上来就搭全套框架要稳得多。