2026年3月31日Claude Code的源码意外泄露51.2万行TypeScript代码被公开这让一直以来蒙着神秘面纱的Agent Skills底层实现终于浮出水面。在此之前很多开发者对Skills的认知都停留在“高级工具”的层面认为它和Function Calling只是“封装程度不同”的同类功能。但当我深入研读源码中SkillTool.ts、Tool.ts等核心文件后发现两者的底层逻辑有着本质区别Function Calling是Agent的“手脚”负责执行具体的原子操作而Skills是Agent的“大脑手册”负责编排流程、注入指令甚至改变Agent的执行上下文。本文将从源码层面拆解Agent Skills的实现逻辑对比它与Function Calling的异同结合实际案例讲解两者的协作模式同时给出自定义Skill的实操建议帮助开发者真正理解Agent架构的核心设计摆脱“只懂API用法不懂底层原理”的局限。一、先搞懂基础Function Calling在源码里到底长什么样要理解Skills与Function Calling的差异首先要明确Function Calling的底层实现逻辑。在Claude Code泄露的源码中Function Calling的核心是“工具注册-模型调用-执行管线”的闭环每一步都有严格的定义和约束本质是“模型发指令、系统做执行”的标准化流程。1.1 工具的核心定义Tool接口与构建流程源码中所有工具都必须实现Tool.ts文件第362行定义的Tool接口这个接口规定了工具的核心字段缺一不可。我们可以通过一段简化的TypeScript代码直观看到接口的结构// Tool.ts:362 核心接口定义interfaceTool{name:string;// 工具名称唯一标识description:string;// 自然语言描述供模型理解功能inputSchema:Zod.Schema;// Zod schema用于校验输入参数call:(params:any,context:ExecutionContext)PromiseToolResult;// 执行函数核心业务逻辑checkPermissions?:(params:any,context:ExecutionContext)Promiseboolean;// 权限检查可选}从接口定义可以看出Function Calling的工具具有极强的结构化特征输入有明确的校验规则执行有固定的函数逻辑权限有可选的检查机制。这种设计保证了工具的可靠性和安全性避免模型调用时出现参数错误或越权操作。工具的构建过程通过buildTool()函数完成这个函数会合并工具的默认配置和用户自定义配置然后通过toolToAPISchema()函数将工具序列化为Claude API能识别的JSON Schema格式最终塞进请求中发给模型。也就是说模型看到的工具本质上是一段包含“名称-描述-参数规则”的结构化数据它只需要决定“是否调用这个工具”以及“传入什么参数”无需关心工具的底层实现。1.2 工具执行管线七步闭环严格可控当模型决定调用某个工具时会输出一个tool_use block系统拿到这个block后会进入services/tools/toolExecution.ts第599行的runToolUse()函数执行一套严格的七步管线确保工具执行的规范性和可追溯性。这七步流程如下每一步都不可或缺Zod验证通过inputSchema校验模型传入的参数确保参数格式、类型符合要求避免无效参数导致执行失败自定义校验执行用户自定义的校验逻辑比如参数的范围限制、业务规则校验等PreToolUse hooks执行工具调用前的钩子函数比如记录日志、初始化执行上下文等权限检查调用checkPermissions()方法验证当前上下文是否有权限执行该工具实际执行调用工具的call()方法执行核心业务逻辑比如调用Bash命令、读取文件等结果映射将call()方法的执行结果转换为模型能理解的格式tool_resultPostToolUse hooks执行工具调用后的钩子函数比如更新上下文、上报执行状态等。整个流程是一个干净的“请求-响应”循环模型发送工具调用请求系统按管线执行执行结果塞回对话历史模型再根据结果继续推理。这种闭环设计让Function Calling的每一步都可监控、可调试适合执行单步、原子化的操作。1.3 工具注册的小细节去重逻辑与优先级源码中还有一个容易被忽略的细节工具注册通过tools.ts里的assembleToolPool()函数完成它会合并内置工具和MCP工具按名称去重且内置工具优先级高于自定义工具。也就是说如果你在MCP服务器上定义了一个和内置工具同名的工具比如都叫“bash”系统会优先使用内置工具自定义工具会被忽略。这个去重逻辑看似简单却能避免工具冲突保证Agent执行的稳定性。比如内置的bash工具经过了严格的安全校验而自定义工具可能存在漏洞优先使用内置工具能降低安全风险。二、Skills的真面目不是高级工具是提示词注入器在研读源码之前我一直默认Skills是“封装了多个工具的高级工具”但types/command.ts第25行的类型定义直接打破了这个认知。源码中Skill的类型是PromptCommand它的type字段是“prompt”而不是“tool”——这意味着Skills本质上不是工具而是一个“披着工具外衣的提示词生成器”。2.1 Skill的核心定义没有执行逻辑只有提示词模板与Function Calling的Tool接口不同Skill没有call()方法没有inputSchema也没有结构化的输入输出定义。它的核心是getPromptForCommand()方法这个方法会读取SKILL.md文件返回展开后的Markdown内容。我们可以通过一段简化的代码看Skill的核心结构// types/command.ts:25 Skill类型定义typeSkillPromptCommand{type:prompt;// 关键标识区别于tool类型getPromptForCommand:(args:string[],context:ExecutionContext)Promisestring;// 生成提示词metadata?:SkillMetadata;// 元数据如路径、描述等};从这段定义可以看出Skill的核心功能只有一个生成提示词。它不执行任何业务逻辑也不直接操作工具而是通过一段预定义的Markdown模板告诉模型“该做什么、怎么做”。而SKILL.md文件就是这个提示词模板的载体里面可以包含动态变量、内联命令、流程描述等内容。2.2 桥梁SkillTool用Function Calling的壳包提示词注入的核Skills本身不能被模型直接调用它需要通过一个叫SkillTool的桥梁才能接入Function Calling的执行体系。SkillTool定义在tools/SkillTool/SkillTool.ts中它本身是一个标准的Tool接口实现拥有完整的Zod schema、call()方法和权限检查逻辑享有Function Calling的全部基础设施输入验证、权限检查、hooks、遥测等。但SkillTool的call()方法并没有执行任何业务逻辑它的核心作用是“上下文注入”。具体来说当模型调用SkillTool时传入的参数是“skill名称”和“可选参数”SkillTool会通过getPromptForCommand()方法读取对应SKILL.md文件的内容展开动态变量和内联命令然后将展开后的内容包装成一条UserMessage注入到模型的对话上下文的中。这是一个教科书级的适配器模式用Function Calling的标准化壳包裹了提示词注入的核心逻辑。通过这种设计Skills既能利用Function Calling的基础设施保证安全性和可靠性又能发挥提示词的灵活性实现复杂的流程编排。2.3 Skills的两种执行模式Inline与Fork适配不同场景源码中Skills有两种执行模式分别对应不同的使用场景这也是Skills与Function Calling的核心区别之一。两种模式的逻辑的都定义在SkillTool.ts第580-841行我们逐一拆解2.3.1 Inline模式注入剧本让模型自己演默认模式Inline模式是Skills的默认执行模式也是最能体现其设计哲学的模式。这种模式的核心是“将提示词注入主对话上下文让模型基于注入的指令自主调用工具完成流程”。整个流程分为三个关键步骤环环相扣第一步内容展开。getPromptForCommand()方法读取SKILL.md文件将里面的动态内容全部替换掉。SKILL.md中可以包含两种动态内容一是内联Shell命令比如!git status展开时会通过promptShellExecution.ts实际执行这条命令将输出结果塞回原位二是变量替换支持$ARGUMENTS完整参数、0索引参数和0索引参数和0索引参数和foo命名参数来自YAML frontmatter的arguments字段。举个例子如果SKILL.md中有这样一段内容“当前仓库状态!git status请检查 staged changes生成符合Conventional Commits规范的commit message”展开后会变成“当前仓库状态On branch main\nYour branch is up to date with ‘origin/main’.\nChanges to be committed:\n (use “git restore --staged …” to unstage)\n\tmodified: README.md请检查 staged changes生成符合Conventional Commits规范的commit message”。这一步其实和我们在CI/CD管线里用模板引擎渲染配置文件没有本质区别核心都是“动态替换占位符生成可执行的指令”。第二步消息注入。展开后的Markdown内容会被包装成一条UserMessage并且带上isMeta: true标记。这个标记的作用很关键用户在终端UI里看不到这条消息但模型在下一轮推理时能完整“看到”它。说白了这就相当于有人悄悄在你和Claude的对话中间插入了一段Claude能看见但你看不见的“指令书”。第三步上下文修改。SkillTool返回的结果中会带有一个contextModifier函数这个函数可以修改后续的执行上下文比如注入allowedTools白名单限制模型只能用特定工具、覆盖模型比如指定用Claude Opus、覆盖effort level执行强度。这意味着一个Skill不仅能告诉模型“做什么”还能改变模型“能用什么工具”和“用哪个版本的自己”。更强大的是Skill甚至可以在调用时注册hooks。比如一个代码格式化Skill可以附带一条规则“每次调用写文件工具后自动跑prettier”。这已经不只是注入提示词了而是在注入“行为拦截器”让模型的后续操作都遵循Skill定义的规则。2.3.2 Fork模式开一个分身只拿结果回来Fork模式与Inline模式完全不同它的核心是“启动子Agent在独立上下文里完成任务只返回最终结果”。当SKILL.md的YAML frontmatter里写了context: fork时SkillTool会调用runAgent()函数和Claude Code的多Agent协调系统共享基础设施启动一个子Agent然后把展开后的Skill内容扔给子Agent。子Agent会在独立的token预算和执行上下文里完整执行Skill定义的流程比如分析文件、生成报告、执行一系列工具调用等。整个执行过程对主对话完全透明主对话最终只拿到一个纯文本结果没有newMessages没有contextModifier也看不到子Agent的任何执行步骤。这种模式非常适合“只需要结果不需要过程”的场景比如“帮我分析这个日志文件找出错误原因并给出解决方案”。用Fork模式主对话不会被子Agent的执行过程干扰拿到的结果也更简洁。三、实例拆解一个/commit指令看清两者的协作关系理论讲得再多不如一个实际案例来得直观。我们以Claude Code中最常用的/commit指令为例拆解它的完整执行轨迹看看Skills和Function Calling是如何协作的理解两者的核心分工。当你在Claude Code的终端里敲下/commit整个执行过程分为四个步骤环环相扣清晰地体现了“Skill编排流程、Function Calling执行步骤”的协作模式步骤1模型调用SkillTool触发Skill执行你输入/commit后模型会首先调用SkillTool传入的参数是{ skill: “commit”, args: “” }。此时SkillTool作为桥梁会读取commit对应的SKILL.md文件这个文件的核心内容简化版如下--- name: commit description: 生成符合Conventional Commits规范的commit message并执行commit操作 arguments: [] --- # Commit流程 1. 执行git status查看当前仓库状态确认staged changes 2. 执行git diff --staged查看暂存文件的修改内容 3. 根据修改内容生成符合Conventional Commits规范的commit message格式类型(范围): 描述 4. 执行git commit -m commit message完成提交。 当前仓库状态!git status步骤2Skill展开内容注入主对话上下文SkillTool调用getPromptForCommand()方法展开SKILL.md中的动态内容执行!git status命令将输出结果替换到对应位置然后将展开后的内容包装成一条带有isMeta: true的UserMessage注入到主对话上下文。此时模型能“看到”这条注入的消息里面包含了完整的commit流程和当前仓库状态相当于拿到了一份“行动手册”。步骤3模型根据Skill指令依次调用Function Calling工具模型读取注入的指令后开始按流程执行每一步都调用对应的Function Calling工具调用Bash工具执行命令git status确认暂存的修改内容这是Function Calling的原子操作调用Bash工具执行命令git diff --staged查看具体的修改细节再次调用Function Calling根据前两步的执行结果生成符合规范的commit message比如feat(utils): 新增日期格式化函数调用Bash工具执行命令git commit -m feat(utils): 新增日期格式化函数完成提交最终的原子操作。步骤4执行完成返回结果所有Function Calling工具执行完成后结果会被塞回主对话历史模型再将最终的提交结果比如“提交成功commit hash: xxxxxxx”返回给用户。整个过程中Skill负责“定义流程、提供上下文”Function Calling负责“执行每一步具体操作”两者分工明确缺一不可。一句话总结两者的协作关系Skill是导演手里的剧本规定了“该怎么演”Function Calling是演员的动作负责“具体怎么干”。导演不亲自上台表演演员不自己写剧本两者配合才能完成一场完整的“演出”。四、深度对比Skills与Function Calling的异同点通过前面的源码拆解和实例分析我们已经能清晰区分Skills和Function Calling的核心差异。下面我们从“底层本质、执行逻辑、使用场景”等多个维度做一次全面的对比帮大家彻底理清两者的关系避免混淆。4.1 核心相同点共享Function Calling的基础设施虽然两者的核心逻辑不同但Skills依赖Function Calling的基础设施才能运行这是它们最核心的相同点都遵循Tool接口的规范Skills通过SkillTool间接遵循都能被模型识别和调用都享有输入验证、权限检查、hooks、遥测等基础设施保证执行的安全性和可追溯性最终都服务于Agent的任务执行都是Agent能力的延伸缺一不可。4.2 核心差异点从本质到使用场景的全面区别两者的差异贯穿“本质、结构、执行、场景”四个层面具体如下表所示清晰对比一目了然对比维度Function CallingAgent Skills底层本质结构化工具负责执行原子操作提示词生成器负责编排流程、注入指令核心结构有call()方法、inputSchema结构化输入输出无call()方法、无inputSchema核心是Markdown模板执行逻辑模型调用→七步管线执行→返回tool_result→塞回对话模型调用SkillTool→展开模板→注入上下文→模型自主调用工具执行模式只有单一步骤执行无多模式两种模式Inline注入主上下文、Fork启动子Agent上下文影响只返回执行结果不改变主上下文可通过contextModifier修改主上下文限制工具、切换模型等使用场景单步、原子化操作读文件、跑命令、调用API等多步、流程化任务代码审查、部署流程、commit规范检查等开发门槛需要写代码实现Tool接口、call()方法和输入校验无需写代码只需编写SKILL.md模板非程序员也能上手安全风险风险较低有严格的参数校验和权限控制风险较高第三方Skill可能藏恶意指令prompt injection4.3 关键补充不要混淆“Skill发现”与“工具注册”源码中还有一个容易混淆的点Skills的“发现机制”与Function Calling的“工具注册”是两个完全独立的逻辑。Function Calling的工具注册是“一次性加载、全局可用”而Skills的发现机制是“动态加载、按需可见”这也是Skills的一大设计亮点。首先Skills有严格的上下文预算控制。在tools/SkillTool/prompt.ts中定义了两个核心常量exportconstSKILL_BUDGET_CONTEXT_PERCENT0.01;// 上下文窗口的1%exportconstMAX_LISTING_DESC_CHARS250;// 每条Skill描述最多250字符formatCommandsWithinBudget()函数会根据这个预算控制Skill列表在prompt中的呈现方式先尝试完整描述超预算就截断bundled skills不截断再超就只保留名称。这确保了你往~/.claude/skills/里扔再多Skill也不会把模型的上下文窗口撑爆。其次Skills有动态可见性设计。在SKILL.md的YAML frontmatter里可以通过paths字段指定Skill的适用范围比如paths: [src/**/*.ts, tests/**]。只有当模型操作了匹配路径的文件比如编辑src目录下的TypeScript文件这个Skill才会出现在可用列表中如果模型在编辑Python文件这个Skill就会被隐藏不会干扰模型的决策。这种动态可见性设计让Skills变得更加“智能”避免了大量无关Skill的干扰也让模型的决策更加高效。而Function Calling的工具一旦注册成功就会全局可用没有这种动态适配的能力。五、实操指南怎么写自定义Skill避坑又高效理解了Skills的底层实现和与Function Calling的差异后最实用的问题就是如何编写自定义Skill结合源码中的设计逻辑和实际开发经验我总结了一套实操指南帮大家避坑同时最大化发挥Skills的优势。5.1 先明确什么时候用Skill什么时候用Function Calling很多开发者的误区是“滥用Skill”明明一个简单的原子操作非要写一个Skill反而增加了复杂度。正确的选择逻辑很简单记住一句话单步用Function Calling多步用Skill。优先用Function Calling的场景单步原子操作比如读文件readFile、写文件writeFile、跑Bash命令bash、调用第三方API比如调用天气API。这些操作不需要流程编排直接调用工具就能完成用Function Calling更高效、更安全。优先用Skill的场景多步流程化任务比如代码审查先读文件、再检查语法、再给出修改建议、部署流程先拉取代码、再构建、再部署、commit规范检查先查状态、再生成message、再提交。这些任务需要编排多个工具调用用Skill来定义流程能让模型自主完成减少人工干预。5.2 自定义Skill的核心步骤编写SKILL.md模板自定义Skill的核心就是编写SKILL.md文件它由“YAML frontmatter”和“Markdown指令内容”两部分组成无需写任何代码非程序员也能轻松上手。下面我们以“TypeScript代码格式化”为例一步步讲解如何编写。第一步编写YAML frontmatter元数据YAML frontmatter位于SKILL.md的开头用—包裹定义Skill的基本信息和配置核心字段如下---name:ts-format# Skill名称唯一标识调用时使用description:格式化TypeScript文件遵循prettier规范自动修复语法错误arguments:# 可选参数支持命名参数-name:file# 参数名称description:需要格式化的TypeScript文件路径required:true# 是否必填context:inline# 执行模式inline或fork默认inlinepaths:[src/**/*.ts]# 动态可见性只在操作TS文件时显示---这里有几个关键注意点name字段必须唯一不能和其他Skill或内置工具重名否则会被覆盖context字段根据场景选择需要影响主上下文比如限制工具用inline只需要结果用forkpaths字段尽量具体避免Skill在无关场景下显示干扰模型决策。第二步编写Markdown指令内容这部分是Skill的核心用来定义模型的行动流程支持动态变量、内联命令和流程描述。我们继续完善上面的ts-format Skill# TypeScript代码格式化流程 1. 检查传入的文件路径 $file 是否存在确保是TypeScript文件后缀为.ts或.tsx 2. 执行prettier --check $file检查文件格式是否符合规范 3. 如果存在格式错误执行prettier --write $file自动修复格式 4. 执行eslint $file --fix修复常见的语法错误 5. 输出格式化结果告知用户文件是否已修复。 当前文件信息!ls -l $file这段指令中我们用到了两个核心特性变量替换$file是我们在frontmatter中定义的参数模型会自动将用户传入的文件路径替换进去内联命令!ls -l $file会执行ls命令查看文件信息将结果注入到指令中让模型了解文件的基本情况。第三步测试与优化Skill编写完成后将SKILL.md文件放到~/.claude/skills/目录下用户级Skill然后在Claude Code中调用/ts-format filesrc/utils.ts测试Skill的执行效果。测试过程中重点关注两个点指令展开是否正确内联命令是否执行变量是否替换成功模型是否按流程执行是否依次调用prettier、eslint工具执行结果是否符合预期。如果模型没有按预期执行大概率是指令描述不够清晰此时可以优化Markdown内容比如增加更具体的步骤说明明确每个步骤需要调用的工具。5.3 避坑指南自定义Skill的3个关键注意事项结合源码中的安全设计和实际踩坑经验有3个关键注意事项一定要牢记避免出现安全问题或执行失败注意事项1警惕第三方Skill的安全风险源码分析显示Skills本质上是“全文当作指令执行”没有“数据 vs 指令”的边界。这意味着第三方Skill的SKILL.md文件中很容易藏恶意指令比如注入恶意Bash命令比普通的prompt injection更危险。因此从Skills Marketplace下载别人写的Skill时一定要逐行查看SKILL.md文件和它引用的所有脚本确认没有恶意指令后再放到自己的Skill目录中。注意事项2避免过度依赖Fork模式Fork模式虽然简洁只返回结果但它启动子Agent会消耗更多的token而且执行过程不透明不利于调试。如果不是“只需要结果”的场景尽量用Inline模式既能看到执行过程又能灵活修改上下文。注意事项3合理控制Skill的复杂度Skill的优势是“流程编排”但不要把它写成“万能脚本”。如果一个Skill的流程过于复杂比如包含十几个步骤调用十几个工具会增加模型的推理负担也容易出现执行偏差。此时可以将复杂流程拆分成多个小Skill逐一调用更高效、更易维护。六、延伸思考从源码看Agent架构的通用模式——MetaTool Pattern深入研读Claude Code的Skill系统后我发现它实现了一种在其他Agent框架中很少见的设计模式我暂且将其称为“MetaTool Pattern”元工具模式。这种模式的核心思路不仅适用于Claude Code也能为我们自己搭建Agent系统提供重要的参考。6.1 MetaTool Pattern的核心逻辑MetaTool Pattern的核心是定义一个“元工具”比如Claude Code中的SkillTool这个元工具的参数是“子工具名称”也就是Skill名称它不执行业务逻辑而是根据名称查找预定义的提示词模板SKILL.md展开模板将展开后的内容注入到模型的上下文中让模型基于这些注入的内容自主推理和行动。这个模式的优势非常明显完美平衡了“安全性”和“灵活性”可扩展性极强给Agent添加新能力只需要添加一个Markdown文件无需修改核心代码非程序员友好不写代码就能定义复杂工作流降低Agent的使用门槛上下文驱动模型拥有完整的决策自主权Skill给的是“建议”而不是“强制指令”更符合Agent的智能特性组合性好Skill可以调用其他Skill可以限制可用工具集可以切换模型版本灵活组合各种能力。6.2 为什么这个模式能成为Agent生态的通用标准2025年10月Anthropic首次推出Skills功能12月就将其发布为开放标准之后OpenAI Codex、Cursor、VS Code等工具陆续跟进支持同一格式。Skills能快速成为跨平台的开放标准核心原因就是MetaTool Pattern的设计足够简单、通用、安全。简单Skill的载体是Markdown YAML格式简单易于编写和解析任何能处理提示词的Agent都能支持通用不依赖特定的模型或框架无论是Claude、GPT还是其他大模型只要能处理工具调用和提示词就能使用Skills安全通过allowedTools白名单、权限检查等机制约束模型的工具调用范围降低安全风险解耦将“能力定义”Skill的Markdown模板和“能力执行”Function Calling的工具解耦让Agent的架构更灵活、更易维护。6.3 如何从零实现这套模式对于正在搭建Agent系统的开发者来说MetaTool Pattern非常值得借鉴。如果你想从零实现这套机制不需要复杂的代码Victor Dibia的实现教程给出了一个80行Python的最小实现核心思路如下简化版importyamlimportsubprocessfromtypingimportDict,List# 1. 定义Skill类读取SKILL.md并展开内容classSkill:def__init__(self,skill_path:str):withopen(skill_path,r)asf:# 分离YAML frontmatter和Markdown内容contentf.read().split(---,2)self.metadatayaml.safe_load(content[1])self.prompt_templatecontent[2]defexpand_prompt(self,args:Dict[str,str])-str:# 替换变量promptself.prompt_templateforkey,valueinargs.items():promptprompt.replace(f${key},value)# 执行内联命令importre command_patternr!(.*?)matchesre.findall(command_pattern,prompt)forcmdinmatches:resultsubprocess.check_output(cmd,shellTrue,textTrue)promptprompt.replace(f!{cmd},result)returnprompt# 2. 定义MetaTool对应SkillToolclassSkillTool:def__init__(self,skill_dir:str~/.claude/skills):self.skillsself.load_skills(skill_dir)defload_skills(self,skill_dir:str)-Dict[str,Skill]:# 加载目录下所有SKILL.md文件importos skill_diros.path.expanduser(skill_dir)skills{}forfilenameinos.listdir(skill_dir):iffilename.endswith(.md):skill_namefilename[:-3]skillSkill(os.path.join(skill_dir,filename))skills[skill_name]skillreturnskillsdefcall(self,skill_name:str,args:Dict[str,str])-Dict[str,str]:# 调用Skill展开提示词返回注入信息ifskill_namenotinself.skills:raiseValueError(fSkill{skill_name}not found)skillself.skills[skill_name]promptskill.expand_prompt(args)return{newMessages:[{role:user,content:prompt,isMeta:True}],contextModifier:None}# 3. 使用示例if__name____main__:skill_toolSkillTool()resultskill_tool.call(ts-format,{file:src/utils.ts})print(result[newMessages][0][content])这段代码虽然简单但已经实现了MetaTool Pattern的核心逻辑加载Skill、展开提示词、注入上下文。基于这个最小实现你可以逐步添加权限检查、hooks、动态可见性等功能搭建自己的Skill系统。七、总结Function Calling与Skills缺一不可的Agent双核心Claude Code的源码泄露让我们终于看清了Agent Skills的底层真面目——它不是高级工具而是一个聪明的提示词注入器通过MetaTool Pattern将提示词的灵活性与Function Calling的规范性完美结合。Function Calling给了Agent“动手”的能力让它能执行具体的原子操作是Agent的“手脚”而Skills给了Agent“思考”的框架让它能编排复杂流程、自主决策是Agent的“大脑手册”。两者相辅相成缺一不可共同构成了Agent的核心能力体系。对于开发者来说理解两者的底层实现和差异不仅能帮助我们更好地使用现有工具还能为我们搭建自己的Agent系统提供思路。无论是编写自定义Skill还是设计Agent架构记住一句话用Function Calling做执行用Skills做编排用MetaTool Pattern做衔接才能打造出灵活、安全、高效的AI Agent。