1. 为什么通用模型写不出能过审的专业报告
你大概遇到过这种场景:让模型写一份设备巡检报告,它洋洋洒洒写了一大篇,格式漂亮、语气专业,但拿给现场工程师一看,字段名对不上、检查项漏了三条、判定标准用的是另一套国标。问题不在模型不够聪明,而在于它不知道你们公司"怎么做这件事"。
通用大模型的能力来自预训练语料,它见过海量文本,所以"什么都会一点"。但企业要的不是通才,是懂自己行业的专家。从通用到专业,中间隔着四层东西:
第一层是角色约束。用 System Prompt 告诉它"你是一个资深合规审查员",能改变语气和视角,但传递不了大量知识,写出来的东西仍然"像那么回事但经不起专业审查"。
第二层是知识注入。把产品手册、法规条文、历史工单喂进去做检索增强,模型能引用正确的事实了。但 RAG 只解决"知道什么",它不告诉你先查哪条、后查哪条、什么情况下该升级人工。
第三层是流程封装。这就是 Skills 要干的事——把领域专家脑子里的工作流固化下来:先确认上下文,再按优先级逐层检查,最后按固定格式输出。Skill 定义的是"按什么流程做"。
第四层是工具连接。MCP 让 Agent 能真的去读文件、查数据库、调接口,把"能做什么"补齐。
这四层叠起来,Agent 才从"会聊天"变成"能交付"。我试过只加 RAG 不加 Skill,结果模型检索到一堆正确资料,却按自己的随机顺序拼凑,输出结构每次都不一样,根本没法进生产流程。后来把审查流程写成 SKILL.md,输出才稳定下来。
这篇就按这个思路走:先讲清楚 Skill 的结构和写法,再讲知识系统怎么组织,然后落到 MCP 工具链和统一 API 通道的配置上,最后给你一套可复制的验证动作。全程围绕一个目标——让 Agent 具备可交付的领域专业能力。
适合谁看:正在做 AI 应用落地、被"输出不稳定"折磨过的开发者;想把内部专家经验沉淀成可复用资产的团队;以及刚接触 Agent 编排、想搞清楚 Skills 和 RAG 到底怎么配合的人。
2. Skills 定义模板与知识系统接入前置准备
在动手写 Skill 之前,得先把两件事想清楚:Skill 长什么样,以及模型调用通道怎么统一。
2.1 Skill 的三层信息架构
Anthropic 定义的 Skill 标准格式,核心是"渐进式披露"——不要一次性把所有信息塞进上下文,而是按需加载。一个 Skill 分三层:
元数据层放在 SKILL.md 开头的 YAML frontmatter 里,只有 name 和 description 两个必填字段。name 用小写连字符,不超过 64 字符;description 不超过 200 字符,要写清楚"这个 Skill 干什么、什么时候用"。这一层的作用是让 Agent 在众多 Skill 里做发现和选择,体量必须小。
指令层是 SKILL.md 的 Markdown 正文,包含工作流程、指南、示例。这一层在 Skill 被激活时注入上下文,通常几百到几千字。它是真正指导 Agent 干活的部分。
参考层是额外的文件,比如 REFERENCE.md、templates/ 目录下的模板、examples/ 下的样例。这一层不主动加载,Agent 需要时再去读,体量可以任意大。
这个设计的妙处在于:你有 50 个 Skill,元数据层加起来可能才几千 token,Agent 能轻松扫一遍选出该用哪个;只有被选中的那个 Skill 才把指令层展开。如果全量注入,上下文早爆了。
2.2 知识系统的四种类型
知识系统不是简单地把文档丢进向量库。按用途分,至少有四类,处理方式完全不同:
文档库放产品文档、技术手册,用于 RAG 检索,特点是量大、更新慢、需要分块和向量化。FAQ 库放常见问题和标准答案,用于快速匹配,特点是结构化程度高、可以直接做精确检索。案例库放历史案例和解决方案,用于参考学习,特点是带上下文和结论,检索时要保留完整案例而不是碎片。规则库放业务规则和约束条件,用于决策依据,特点是必须精确、不能有歧义,通常不适合向量检索,更适合结构化存储后精确查询。
把这四类混在一起丢进一个向量库,检索质量会很难看。规则类内容被语义相似度一搅和,可能召回一堆"看起来相关但判定标准完全不同"的条文。我的做法是规则库单独走结构化查询,文档库和案例库走向量检索,FAQ 库走关键词加语义混合检索。
2.3 统一模型通道:为什么需要 TaoToken
Skill 和知识系统都准备好了,最后要落到模型调用上。这里有个现实问题:你可能同时用 Claude 做代码审查、用 GPT 做文档总结、用国产模型做客服问答,每家一个 Key、一套计费、一套限流,管理成本很高。
TaoToken 提供的是统一的 Key 和 API 通道,把多家模型的调用收敛到一个入口。你只需要在官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 注册拿到 Key,后面所有 Skill 的模型调用都走同一个 Base URL。这样切换模型不用改代码,只改 Model ID 就行。
对 Skills 系统来说这点很关键:Skill 定义里通常不写死模型,而是声明"这个任务需要强推理"或"这个任务要快",由调度层根据当前可用的模型通道去选。统一通道让这种动态选择变得可行。
前置准备清单:一个 TaoToken 账号和 API Key;本地 Python 3.9+ 环境;一个放 Skill 的目录;以及你想注入的领域资料(先准备 10 到 20 份高质量文档就够跑通流程,不用一上来就全量导入)。
3. 可复制的 Skill 配置与知识库接入步骤
这一节是核心,给你能直接抄的配置。先建目录结构,再写 SKILL.md,然后配模型通道,最后接知识库。
3.1 目录结构
skills/ ├── contract-reviewer/ │ ├── SKILL.md │ ├── REFERENCE.md │ ├── templates/ │ │ └── review-report.md │ └── examples/ │ └── sample-review.md ├── sql-optimizer/ │ ├── SKILL.md │ └── examples/ └── README.md每个 Skill 一个目录,SKILL.md 是入口,其余按需组织。README.md 做索引,列出所有 Skill 的 name 和 description,方便人工维护。
3.2 SKILL.md 完整模板
下面这份是合同合规审查 Skill,你可以照着改字段:
--- name: contract-reviewer description: 合同合规审查助手,按风险等级逐条检查条款,输出结构化审查报告。当用户要求审查合同、检查合规性或识别风险条款时使用。 --- # Contract Reviewer - 合同合规审查专家 ## 工作流程 ### Step 1: 确认审查上下文 - 确认合同类型(采购/销售/服务/劳动) - 确认适用法规范围 - 询问审查重点(全面/仅风险/仅合规) ### Step 2: 逐层审查 按以下优先级逐层检查: 1. **合规性**(P0) - 主体资格是否明确 - 必备条款是否齐全 - 是否违反强制性规定 2. **风险条款**(P1) - 违约责任是否对等 - 争议解决条款是否明确 - 知识产权归属是否清晰 3. **商业条款**(P2) - 付款条件是否合理 - 交付标准是否可量化 - 保密期限是否适当 ### Step 3: 输出报告 使用 templates/review-report.md 的格式输出。 ## Guidelines - P0 问题必须给出具体修改建议 - 每个风险点要说明"为什么有风险" - 引用具体条款编号,不要笼统描述 - 对合理的条款也要标注"已确认无风险" ## Examples - 用户说"帮我看看这份合同" → 激活本 Skill,走完整流程 - 用户说"只查合规问题" → 激活本 Skill,聚焦 P0注意 frontmatter 里 description 的写法:它同时承担"功能说明"和"触发条件"两个职责。Agent 靠这句话判断该不该激活这个 Skill,所以"当用户要求……时使用"这半句不能省。
3.3 模型通道配置
Skill 写好了,得让 Agent 能调模型。统一走 TaoToken 的 API 通道,配置如下:
import os from openai import OpenAI client = OpenAI( base_url="https://taotoken.net/api", api_key=os.environ["TAOTOKEN_API_KEY"], ) def call_model(messages, model_id="claude-sonnet-4-20250514"): resp = client.chat.completions.create( model=model_id, messages=messages, temperature=0.2, ) return resp.choices[0].message.content把 Key 放进环境变量,不要硬编码。Base URL 固定为https://taotoken.net/api,Model ID 按你实际要用的模型填。切换模型只改model_id参数,其余代码不动。
如果你用的是 Claude Code 这类工具,配置方式类似,在 settings 里指定 Base URL 和 Key 即可。核心三件套永远是:Base URL、API Key、Model ID,缺一不可。
3.4 知识库接入
知识库用向量检索实现,这里给一个最小可跑的版本:
import chromadb from openai import OpenAI client = OpenAI( base_url="https://taotoken.net/api", api_key=os.environ["TAOTOKEN_API_KEY"], ) chroma = chromadb.PersistentClient(path="./kb") collection = chroma.get_or_create_collection("domain_docs") def embed(text): resp = client.embeddings.create( model="text-embedding-3-small", input=text, ) return resp.data[0].embedding def add_document(doc_id, text, metadata): collection.add( ids=[doc_id], embeddings=[embed(text)], documents=[text], metadatas=[metadata], ) def search(query, top_k=5): results = collection.query( query_embeddings=[embed(query)], n_results=top_k, ) return results["documents"][0]分块策略上,文档库按 500 到 800 字切,保留标题层级作为 metadata;案例库整篇存,不要切碎,因为案例的结论依赖完整上下文;规则库不进向量库,单独用 SQLite 或 JSON 存,按条款编号精确查询。
3.5 把 Skill 和知识库串起来
调度逻辑是这样的:用户提问后,先用元数据层做 Skill 匹配,激活对应 Skill 拿到指令层,然后按 Skill 流程决定要不要检索知识库、检索哪一类,最后把 Skill 指令、检索结果、用户问题一起组装成 prompt 发给模型。
def run_agent(user_query): skill_name = match_skill(user_query) skill_content = load_skill(skill_name) kb_context = "" if needs_knowledge(skill_name): docs = search(user_query, top_k=5) kb_context = "\n\n".join(docs) messages = [ {"role": "system", "content": skill_content}, {"role": "user", "content": f"参考资料:\n{kb_context}\n\n问题:{user_query}"}, ] return call_model(messages)这套结构跑通后,你会发现输出稳定性明显提升——因为流程被 Skill 固定住了,知识被 RAG 补全了,模型只负责在框架内填充内容。
4. 验证请求与成功结果对照
配置写完不算完,得验证每一环都通了。按下面顺序逐项测。
4.1 验证模型通道
先确认 Key 和 Base URL 能通:
resp = client.chat.completions.create( model="claude-sonnet-4-20250514", messages=[{"role": "user", "content": "回复 OK 两个字母"}], ) print(resp.choices[0].message.content)预期输出是OK。如果这一步就报错,先别往下走,去看第 5 节的排错。
4.2 验证 Skill 加载
skill = load_skill("contract-reviewer") print(skill[:200])预期能看到 frontmatter 和正文开头。如果打印出来是空字符串,说明路径不对或文件名不是 SKILL.md。
4.3 验证知识库检索
docs = search("违约责任怎么约定", top_k=3) for d in docs: print(d[:100])预期返回 3 段和违约责任相关的文档片段。如果返回空列表,检查是否已经 add_document 过数据。
4.4 端到端验证
result = run_agent("帮我审查这份采购合同,重点看违约责任") print(result)成功的结果应该具备这些特征:输出结构符合 SKILL.md 里定义的报告格式;引用了知识库里的具体条款;风险点按 P0/P1/P2 分级;每个风险点有"为什么"的说明。
如果输出格式对但内容空泛,说明知识库没检索到有效内容;如果内容有料但格式乱,说明 Skill 指令层没被正确注入。对照这两点定位问题。
4.5 成功结果样例
一份合格的输出长这样:
## 审查报告 ### P0 合规性问题 | 条款 | 问题 | 建议 | |------|------|------| | 第 3.2 条 | 未明确争议解决机构 | 补充仲裁委员会名称 | ### P1 风险条款 | 条款 | 问题 | 建议 | |------|------|------| | 第 5.1 条 | 违约责任单方承担 | 改为对等约定 | ### 审查统计 - P0: 1 个 - P1: 1 个 - P2: 0 个格式稳定、分级清晰、建议具体,这才算 Skill 真正生效。
5. 常见报错排查:401、local proxy failed 与 choices 解析失败
这一节列几个我踩过的坑,对照报错找原因。
5.1 401 Unauthorized
最常见。原因通常是 Key 没读到或写错了。检查三处:环境变量TAOTOKEN_API_KEY是否真的导出(echo $TAOTOKEN_API_KEY看有没有值);Key 字符串有没有多余空格或换行;Base URL 是不是写成了带路径的完整地址。注意 Base URL 用https://taotoken.net/api,不要自己拼/v1/chat/completions,SDK 会自动补。
5.2 local proxy failed / connection refused
这个报错说明请求根本没发出去。检查本机网络是否能访问外网、有没有配置了失效的代理环境变量(HTTP_PROXY、HTTPS_PROXY)。如果之前设过代理,先unset掉再试。另外确认防火墙没拦 Python 进程的出站请求。
5.3 reading 'choices' 报错
典型报错是TypeError: 'NoneType' object is not subscriptable或KeyError: 'choices'。这通常意味着返回体结构和你预期的不一样。先打印原始响应:
resp = client.chat.completions.create(...) print(resp)如果返回的是错误对象而不是正常响应,说明请求被拒了,往上找 401 或 429。如果返回正常但没有 choices,检查 Model ID 是否拼错——模型名不对时有些网关会返回空结构而不是明确报错。
5.4 OAuth 相关报错
如果你用的是 Claude Code 这类带 OAuth 流程的工具,报OAuth token expired或invalid_grant,说明登录态失效了。重新走一遍授权流程,或者在配置里改用 API Key 方式而不是 OAuth。用统一 API 通道时,直接配 Base URL + Key 最省事,绕开 OAuth 的坑。
5.5 Skill 没被激活
现象是 Agent 回答得很泛,完全没按 SKILL.md 的流程走。原因多半在 description 写得不够明确,Agent 匹配不到。把 description 改成"当用户要求 X、Y、Z 时使用"这种带触发条件的写法,匹配率会明显上升。另外确认元数据层的 name 和目录名一致,有些加载器靠目录名索引。
5.6 知识库检索结果不相关
检索出来的文档和问题八竿子打不着。先检查分块大小,切得太碎会丢上下文,切得太大语义被稀释。然后看 embedding 模型是否和入库时一致——入库用 A 模型、查询用 B 模型,向量空间对不上,结果必然乱。最后考虑加一层 rerank,先召回 20 条再精排到 5 条。
排查顺序建议固定下来:先验通道(4.1),再验 Skill(4.2),再验知识库(4.3),最后端到端(4.4)。哪一步断了一眼就能看出来,比盲目改代码高效得多。
6. 从能跑到能交付:把专业能力沉淀成资产
跑通一个 Skill 只是起点。真正有价值的是把团队里的专家经验持续沉淀成可复用的 Skill 和知识库,让每一次项目交付都比上一次更省力。
几个实操建议。Skill 要小步迭代,别一上来写几百行,先写最小流程跑通,再根据实际输出补 Guidelines。每补一条 Guideline,最好对应一个真实踩过的坑,这样 Skill 才是有血有肉的,不是凭空想象的规范。
知识库要建立更新机制。文档类内容每周增量同步一次,规则类内容变更时人工确认后更新,案例类内容项目结束后归档。三类内容更新频率不同,别用一套流程硬套。
模型通道保持统一。所有 Skill 的模型调用都走同一个 Base URL,切换模型只改 Model ID。这样你可以在不同任务上试不同模型——强推理任务用 Claude,快速响应任务用轻量模型——而不用维护多套配置。需要 Key 的话去 https://taotoken.net/api-keys 拿,接入细节看 https://taotoken.net/doc ,想直接体验模型效果可以到 https://taotoken.net/chat 试。
如果你打算长期做 Agent 开发,建议把 Coding Plan 用起来,它在多轮编码和 Agent 编排场景下更省心,具体在 https://taotoken.net/coding-plan 看。
最后一句实在话:Skills 系统的价值不在技术多复杂,而在你有没有把领域里那些"老师傅才知道的门道"写进去。技术框架是壳,领域知识才是核。壳可以照抄,核只能自己攒。