
前阵子我们团队接手了一个挺磨人的任务给市场部搭一套 AI 营销助手。最开始大家都觉得简单接个大模型 API再写点 Prompt 就能上线。可真把需求捋完发现完全不是这么回事——市场部要的不是一个能聊天的窗口而是能反复调用、按流程走、还不许出错的营销能力集合。于是就有了内部代号叫 Marketingskills 的项目核心就一句话把 AI 代理Agent的营销能力拆成一套可编排、可复用、可评测的技能库。这篇文章不打算写概念科普而是把我们踩过的坑、定过的协议、写过的代码骨架原原本本拿出来复盘一遍。适合谁看正在搭 Agent 系统的工程师、营销技术负责人、以及想把大模型真正落到业务流里的同学。看完你会明白技能库到底在解决什么问题底层怎么抽象怎么从零搭一版能跑起来的骨架以及上线前最容易被忽略的质量闭环。1. 营销Agent的能力荒光有聪明大脑没有成体系的技能1.1 通用大模型在营销场景里的尴尬先还原一下真实场景。市场部每天要产出的东西极其固定活动文案、产品卖点提炼、人群包划分、竞品分析、投放渠道建议、发布前合规检查……这些任务看似不同底层却有大量共性。拿大模型直接对话去做你会发现三个问题第一产出不稳定。同一个需求上午问和下午问语气、结构、信息密度很可能都不一样。营销物料是要过审、要对外发布的不确定的输出等于没法用。第二业务上下文接连不上。模型不知道你们品牌的调性、这个季度的主推产品、上一轮投放的数据表现每次都要口头喂一遍。第三没法嵌入流程。文案写完了要给谁审人群包算出来怎么同步给投放系统这些动作如果全靠对话就永远停留在聊天工具的层面。所以我们的结论很明确市场部需要的不是更聪明的对话而是一套可被系统调用的营销技能。每个技能负责一件确定的、边界清晰的事Agent 负责理解需求、调度这些技能、汇总结果。1.2 什么是技能为什么需要用库来组织在 Marketingskills 里我们对技能的定义很窄一个技能就是 Agent 可调用的一个原子能力它封装了三样东西——执行逻辑可能是模型推理、代码计算、外部接口调用、输入输出协议参数长什么样、结果长什么样、校验规则产出是否合规、格式是否达标。为什么要用库来统一组织因为营销任务的高度复用性。一场大促战役从预热到复盘文案生成、话题词推荐、人群包拆分、素材合规检查这些技能会被反复组合、反复调用。如果每个场景都临时写一段 Prompt等于每次都在重复造轮子而且没人维护。把技能统一收口到库里才能做到三件事一处迭代、处处生效新增能力只需要往库里注册每个技能的调用情况能被统计和复盘。1.3 我们给自己定的三条设计红线动手之前我们给技能库定了三条红线后面所有设计决策都围着它们转确定性优先同一个技能在相同输入下要尽量给出稳定的输出结构宁可牺牲一点花哨也不能让下游解析崩溃。可观测性每一步技能调用都要有日志、有输入输出快照、有耗时和成本记录。营销业务对为什么得出这个结论非常较真不可观测的方案上不了线。可回滚技能要版本化。新版本效果不好能一键切回旧版本而不是把整个系统跟着一起带崩。这三条红线直接决定了后面的协议设计和编排架构。说白了技能库本质上不是把 Prompt 存起来而是用工程化的方式管理 Agent 的能力边界。2. 底层抽象先行技能注册表、协议与上下文契约2.1 技能画像每个技能都有独立身份证我们把每个技能描述成一张画像存进注册表。核心字段如下字段作用例子name技能唯一标识platform_copywritingdescription给路由/规划器看的自然语言说明生成种草文案适合活动预热不适合公告input_schema输入参数的契约定义产品卖点、目标平台、语气风格output_schema输出结果的契约定义标题、正文、话题标签version版本号支持灰度与回滚1.2.0tags技能标签便于检索内容、文案、营销战役owner负责维护的角色或小组内容中台这里有个容易忽略的点description 不只是给人看的它是给 Agent 看的。在轻量路由场景里Agent 就是靠读这些描述来决定调哪个技能的。描述写得含糊路由就乱。我们后来规定描述里必须写清楚适合什么、不适合什么比如适合产品介绍和活动预热不适合官方公告与法律声明这样模型才不容易误调用。2.2 协议先行把技能当成函数来约束写技能库最忌讳的就是先写代码后补文档。我们吃过亏一开始某个技能返回的hashtags是字符串另一个技能需要的是列表下游解析直接炸了。后来定死一条规矩任何技能进库之前必须先把 input_schema 和 output_schema 定义好再写执行逻辑。协议用类 JSON Schema 的结构描述简单直接{ title: 种草文案生成技能, input_schema: { required: { product_info: {type: string, desc: 产品核心卖点50字以内}, platform: {type: string, desc: 目标内容平台如某生活方式社区}, tone: {type: string, desc: 语气风格如活泼/专业/治愈} } }, output_schema: { required: { title: {type: string}, content: {type: string}, hashtags: {type: array, items: {type: string}} } } }协议先定的好处很明显路由规划时可以提前判断参数够不够调用时可以快速校验下游系统对接时有明确的类型保证。我们内部把这种模式叫函数式技能——每个技能都像是一个有类型签名的函数Agent 是调用方而不是让模型自由发挥。2.3 上下文契约防止技能之间的信息污染技能库的第二个关键抽象是上下文对象。营销任务往往需要多个技能接力前一个技能的结果要传给后一个用。但如果所有技能都能读写全部上下文很快就会乱套文案技能可能误改人群包的参数合规检查技能又不知道从哪读到了一条过期数据。我们的做法是给每个技能声明访问白名单spec SkillSpec( nameplatform_copywriting, access[campaign.brand, campaign.product, user_profile.preferences], read_only[campaign.brand, campaign.product], write[user_profile.preferences] )技能只能读自己声明要读的字段只能写自己声明要写的字段其余一律隔离。这个机制像极了多人协作时各管一摊的权限管理看着不起眼但真能挡住绝大多数上下文污染。实际运行中中间结果统一放在intermediates区技能之间通过intermediates.技能名.字段名引用谁写的、哪一步写的一目了然。3. 两次编排轻量路由与重型工作流的取舍3.1 轻量路由几十个技能时的默认方案技能少的时候编排不需要复杂引擎。我们第一版做的就是检索 调用的轻量路由用户丢过来一句自然语言需求规划器先提取关键意图再到注册表里搜技能描述把命中的技能按相关度排序然后逐个填参数、执行、汇总。class SkillRegistry: def __init__(self): self._skills {} def register(self, skill: Skill): self._skills[skill.spec.name] skill def search(self, query: str, top_k: int 5): # 生产环境建议接向量检索这里用描述关键词粗筛示意 scores {} for name, skill in self._skills.items(): desc skill.spec.description.lower() score sum(1 for token in query.lower().split() if token in desc) scores[name] score return sorted(scores.items(), keylambda x: x[1], reverseTrue)[:top_k]轻量路由适合技能数量在二十个以内、且技能之间依赖关系很浅的场景。我们的第一版大概就是这么撑起来的。但很快发现营销战役从来不是一个技能打天下要做一次完整的 Campaign先得分析人群再定内容策略然后生成素材最后还要合规审核。这个链路是固定的靠自然语言搜索来碰运气完全不靠谱。3.2 重型编排用工作流把营销战役固化下来于是我们加了第二层工作流编排。工作流本质上是一个有向无环图节点是技能边是数据依赖。我们用最朴素的方式定义了一个工作流描述结构把市场部怎么做一场活动这件事固化成了标准流程。拿一个新品上市推广的典型流程举例受众分析技能读取用户画像库产出目标人群特征内容策略技能结合人群特征和产品卖点产出内容主题方向文案生成技能把主题方向转成各平台文案合规检查技能逐条校验文案中的违禁词与绝对化用语人工审批节点推送预览给运营同学确认后才算完成这里最大的变化是步骤再也不是模型临场发挥而是组织沉淀下来的运营方法论。调研过几个成熟团队后我们的判断是轻量路由适合探索期重型工作流适合规模化复用。两者不是替代关系而是配合关系——重流程里的每个节点照样可以是一个轻量路由去动态选技能。3.3 人工审批节点让 Agent 只做草稿不直接生效这是我们从上线第一天就坚持的设计涉及对外发布、预算分配、用户沟通的技能必须挂人工审批节点。Agent 可以产出建议、可以生成草稿、可以给出理由但没有权限把内容直接发出去。一套工作流执行到审批节点时会把所有中间结果打包成一张决策卡交给对应角色确认。确认后继续往下走驳回则回到上一步修订。不要觉得这样不够智能——恰恰相反敢承认 Agent 的边界才敢把更多环节交给他。实际跑下来人工审批消耗的时间比我们想象中少得多因为前置技能已经把 80% 的脏活干完了人只需要做判断题。失败重试也有讲究。我们的策略是网络超时最多重试两次采用退避间隔校验失败则重新整理参数再试一次连续失败直接转人工处理不无限循环。这套规则的代码实现很简单但放在技能库的调度层里能让整体稳定性上一个台阶。4. 从零到手搓一版可运行的营销技能库骨架4.1 目录结构与核心数据模型说再多概念不如直接看代码。这是我们可以跑通的最小骨架也推荐你从这份结构开始迭代marketingskills/ ├── skills/ # 业务技能实现 │ ├── copywriting.py │ ├── audience_split.py │ └── compliance_check.py ├── registry.py # 技能注册表 ├── context.py # 任务上下文 ├── planner.py # 路由/规划器 ├── workflows/ # 固化的工作流定义 │ └── new_product_launch.py └── main.py # 入口调度核心数据模型就两个类SkillSpec负责描述Skill负责执行。用装饰器把技能和执行函数绑定起来from dataclasses import dataclass, field from typing import Callable dataclass class SkillSpec: name: str description: str input_schema: dict output_schema: dict version: str 1.0.0 tags: list[str] field(default_factorylist) access: list[str] field(default_factorylist) read_only: list[str] field(default_factorylist) write: list[str] field(default_factorylist) class Skill: def __init__(self, spec: SkillSpec, execute: Callable): self.spec spec self.execute execute def __call__(self, **kwargs): validate(kwargs, self.spec.input_schema) # 输入校验 result self.execute(**kwargs) validate(result, self.spec.output_schema) # 输出校验 return resultvalidate函数按 schema 里的required逐个检查字段和类型不合格直接抛异常。这一步把模型返回的结果不可控的问题在进入下游之前就拦截住了。4.2 两个真实技能种草文案与合规检查第一个技能是文案生成。它内部会调用大模型但对外层的表现就是一个确定函数def create_copywriting_skill(): spec SkillSpec( nameplatform_copywriting, description生成指定内容平台的种草文案。适合产品介绍、活动预热不适合公告与法律声明, input_schema{ required: { product_info: {type: string}, platform: {type: string}, tone: {type: string} } }, output_schema{ required: { title: {type: string}, content: {type: string}, hashtags: {type: array} } }, tags[content, copywriting] ) def execute(product_info, platform, tone): # 生产环境在这里调用大模型并传入上下文中的品牌调性 # 这里展示的是封装后的伪实现 return { title: f{product_info}{platform}上的种草标题, content: f围绕{product_info}展开的详细内容语气{tone}, hashtags: [#实测, #种草] } return Skill(spec, execute)第二个是合规检查。这个技能不调大模型纯粹用规则引擎做兜底避免模型幻觉漏掉违禁词def create_compliance_check_skill(): spec SkillSpec( namecompliance_check, description检查营销文案中的绝对化用语和广告法违禁词, input_schema{required: {content: {type: string}}}, output_schema{required: {pass: {type: boolean}, flags: {type: array}}}, tags[compliance, review] ) def execute(content): banned_words [绝对, 第一, 顶级, 国家级] # 示例词表可配置化 flags [{type: 广告法, keyword: w} for w in banned_words if w in content] return {pass: len(flags) 0, flags: flags} return Skill(spec, execute)写这块的时候有个心得能用规则解决的就不要让模型发挥。合规检查这种容错率极低的环节规则引擎 词表先兜底模型再去做语义层面的判断组合起来才让人放心。4.3 注册与调度从自然语言到可执行计划技能写好后统一进注册表主程序负责组装调用链def main(): registry SkillRegistry() registry.register(create_copywriting_skill()) registry.register(create_compliance_check_skill()) # 工作流先写文案再合规检查 def new_product_launch(product_info, platform, tone): copywriting_skill registry.get(platform_copywriting) compliance_skill registry.get(compliance_check) draft copywriting_skill(product_infoproduct_info, platformplatform, tonetone) check compliance_skill(contentdraft[content]) draft[compliance] check return draft result new_product_launch( product_info新一代智能保温杯24小时长效保温, platform某生活方式社区, tone治愈系 ) print(result)至于参数从哪来工程上建议用一个专门的参数抽取模型去做填充而不是让技能自己猜。我们后来还加了一道invoke_with_retry包装器统一处理超时、重试和转人工def invoke_with_retry(skill, params, max_retries2): for attempt in range(max_retries 1): try: return skill(**params) except SchemaError as e: log_warning(f参数校验失败第{attempt 1}次重试: {e}) params repair_params(params, skill.spec.input_schema) except TimeoutError: sleep(2 ** attempt) raise HumanHandoffRequired(连续失败转人工处理)到这里一套能跑的技能库已经成型有注册、有协议、有调度、有重试。它的核心思想是用工程约束把模型的不确定性关进笼子里而不是指望模型突然变可靠。5. 质量闭环评测、记忆沉淀与三个翻车经验5.1 评测基线没有数据别说技能库好用技能库最大的风险是感觉好用但不敢上线。所以我们从第一天就建了一套评测基线把所有典型营销任务固化成测试集评测指标基准线说明技能调用成功率≥ 98%参数校验、超时、异常导致的失败占比低于 2%端到端任务完成率≥ 85%从自然语言到技能链全部执行完成并产出结果人工验收通过率≥ 80%内容类产出抽样由运营侧复核是否可用P50 单技能时延≤ 8 秒包含模型推理与后置校验成本增幅≤ 5%相对纯对话调用技能库引入的额外成本每周跑一轮版本升级前后对比。有这套基线兜底我们才敢在真业务里逐步放量。也建议你把评测集跟业务方一起维护因为技能到底好不好这件事最终要由用它的人说了算。5.2 记忆沉淀从短对话到长期知识的三级结构技能库不能是失忆的。我们的记忆分为三级会话级记忆单次任务内的上下文比如这场战役里刚生成的人群包 ID。项目级记忆某个营销战役的品牌信息、目标人群、历史素材库。技能执行中通过上下文对象读写战役结束归档。组织级记忆跨项目的品牌调性、合规规范、历史优秀案例。这部分独立维护任何技能在生成内容前都可作为参考。这套三级结构的价值在文案技能上体现得最明显。没有项目级记忆同一款产品的文案每次都是重新摸索有了之后第二版明显比第一版更贴合品牌调性因为它真的记得上次哪些表述被运营点赞了。5.3 最容易翻车的三个坑与应对方案第一个坑是技能描述写得太宽泛。路由模型靠 description 做匹配写得太泛遇上一个模糊需求时就乱选。应对办法描述里必须写适合什么、不适合什么并在评测集里专门加边界用例。第二个坑是上下文被塞爆。之前某个阶段我们把所有知识一股脑塞给技能导致模型越聊越糊涂。后来严格执行白名单访问技能只读自己声明字段问题基本绝迹。第三个坑是输出格式不稳定。模型偶尔会少给字段、多给字段、或者把数组返回成字符串。现在全靠输出后的 schema 强校验不合格就修复参数重试再不行转人工绝不让坏数据流到下游。这三个坑我估计绝大多数做 Agent 的团队都会踩一遍早点看到这篇文章至少能少熬两个夜。最后说点个人感受做了大半年技能库我最大的体会是真正难的从来不是写某个技能而是定义技能之间的边界。边界清楚编排自然顺边界模糊再强的模型也救不回来。所以后来团队里定了一条规矩宁可每个技能做小一点、单一一点也不要试图做一个什么都干的万能技能——万能往往意味着失控。如果你正好也在搭营销 Agent建议从最小骨架起步先固化两三个高频技能把协议、上下文、评测基线跑顺再慢慢扩充。技能库这东西像滚雪球前期的抽象工作做好了后面每加一个技能都是增量收益。希望这份复盘能让你少走点弯路。