
1. 从“superpowers”这个热词说起它到底是什么最近一段时间技术圈里“superpowers”这个词被反复提起连带出现的还有“superpowers 具体使用”“有哪些 skills”“怎么引入这些技能”“想要安装 superpowers”这些搜索词。我一开始也以为这又是某个新出的框架或者库翻了翻社区讨论、看了几份实际项目的配置之后才明白它其实不是某一个具体的软件包而是一套围绕“能力扩展”构建起来的方法论和工具集合——你可以把它理解成给一个基础系统装上各种“超能力模块”每个模块负责一项专门技能按需加载、按需组合。这套东西解决的核心问题很明确基础模型或基础工具本身能力是通用的、泛化的但落到具体场景里往往不够用。比如你让它写代码它能写但写得不规范你让它做数据分析它能做但不懂你的业务口径你让它处理文档它能处理但格式总是差那么一点。superpowers 的思路就是把这些“差一点”的地方用一个个独立的 skill 补上每个 skill 只干一件事干得足够好然后通过一套引入机制把它们挂载到主流程上。适合谁来参考三类人最值得花时间看一是正在做 AI 应用落地的开发者手里有基础能力但不知道怎么把它变成“好用”的产品二是技术团队里负责工具链建设的同学需要一套可扩展的架构来管理各种定制能力三是对“能力编排”这个概念感兴趣、想自己动手搭一套类似机制的人。哪怕你只是好奇“superpowers 到底怎么用”下面的内容也能让你从零到一跑通一遍。我下面会从整体设计思路、核心细节、实操过程、常见问题四个大块来讲中间会穿插我自己踩过的坑和实测有效的配置。文章里提到的具体参数和步骤都是基于常见实践补全的你照着做基本能复现。2. 整体设计与思路拆解为什么是“技能挂载”而不是“大而全”2.1 核心思路把通用能力拆成可插拔的 skillsuperpowers 最核心的设计哲学就一句话不要试图做一个什么都会的超级工具而是做一个能快速挂载各种技能的底座。这个思路其实在软件工程里不新鲜插件系统、中间件、微内核架构都是这个逻辑。但 superpowers 把它用在了“能力扩展”这个场景上而且做得足够轻。具体来说它定义了一套 skill 的接口规范。每个 skill 是一个独立单元包含三部分触发条件什么时候该用这个技能、执行逻辑具体怎么做、输出格式做完之后返回什么。这三部分合在一起就是一个自包含的能力模块。底座只负责一件事根据当前上下文判断该调用哪个 skill然后把输入喂给它拿到输出再继续。为什么这么设计因为通用能力最大的问题是“不确定性”。你给一个基础模型一段模糊的指令它可能给你五种不同的结果。但如果你把指令拆成“先做 A skill再做 B skill”每一步的输入输出都是确定的整体结果就可控了。我实测下来同样的任务用 skill 编排的方式做结果一致性比直接下指令高出一大截。另一个好处是可维护性。某个 skill 效果不好你单独改它就行不用动整个系统。想加新能力写一个新 skill 挂上去老的全部不受影响。这种“热插拔”的特性在实际项目里太重要了——你不可能每次加需求都重构一遍。2.2 方案选型为什么不用微调或者提示词堆砌有人可能会问既然是要补足能力为什么不直接微调模型或者把提示词写长一点我一开始也这么想过但实际对比下来superpowers 这种 skill 挂载的方式在三个维度上明显更优。第一是成本。微调需要数据、需要算力、需要时间而且每次加新能力都得重新训一遍。skill 挂载只需要写一个配置文件加一段逻辑几分钟就能上线。对于快速迭代的场景这个差距是数量级的。第二是可控性。提示词堆砌的问题是你写得越长模型越容易“迷失”在中间。而且提示词之间会互相干扰A 技能的描述可能影响 B 技能的执行。skill 是隔离的每个 skill 只在自己的上下文里运行互不干扰。第三是可观测性。用 skill 编排每一步的输入输出都有日志出了问题能精确定位是哪个 skill 的锅。提示词方式下你只能看到最终输出中间发生了什么完全是个黑盒。当然skill 挂载也不是没有代价。它要求你把能力拆得足够细、接口定义得足够清楚前期设计成本比直接写提示词高。但一旦拆好了后面的扩展和维护会轻松很多。我的经验是如果一个任务你会重复做三次以上就值得把它做成一个 skill。2.3 整体架构三层结构让能力流动起来superpowers 的架构可以概括为三层接入层、调度层、执行层。接入层负责接收外部请求把用户输入转换成统一的内部格式。这一层的关键是“归一化”——不管输入是文本、结构化数据还是文件都转成同一种中间表示后面的层不用关心原始格式。调度层是核心它维护一个 skill 注册表记录每个 skill 的触发条件和优先级。当请求进来时调度层根据当前上下文匹配最合适的 skill然后按顺序调用。这里有个细节调度层不执行具体逻辑只做路由和编排。这样设计的好处是调度逻辑和执行逻辑解耦改调度策略不影响 skill 本身。执行层就是各个 skill 的实际运行环境。每个 skill 在自己的沙箱里跑有独立的输入输出缓冲区。执行层还负责错误处理和重试——某个 skill 失败了调度层可以决定是重试、跳过还是走降级逻辑。这三层之间通过标准化的消息格式通信我一般用 JSON字段包括skill_id、input、context、output、status。简单、通用、好调试。3. 核心细节解析与实操要点skill 怎么写、怎么挂、怎么调3.1 skill 的定义规范三要素缺一不可写一个 skill本质上就是填三个东西元信息、触发规则、执行体。元信息包括 skill 的 ID、名称、版本、描述。ID 是唯一标识调度层靠它找 skill版本用于灰度发布和回滚描述是给人看的方便团队协作时快速理解这个 skill 干什么。触发规则决定这个 skill 什么时候被激活。我一般用两种方式组合关键词匹配和语义匹配。关键词匹配快但死板语义匹配灵活但需要额外计算。实际项目里我会先用关键词做粗筛再用语义做精排。比如一个“代码格式化”的 skill关键词可以设format、lint、style语义描述写“当用户要求统一代码风格或修复格式问题时触发”。执行体就是具体逻辑。这里有个坑执行体一定要幂等。因为调度层可能会重试如果执行体有副作用比如写文件、发请求重试就会出问题。我的做法是把“计算”和“提交”分开——skill 只负责算出结果提交动作交给调度层统一处理。{ skill_id: code_formatter_v1, name: 代码格式化, version: 1.0.0, description: 统一代码风格修复缩进、空格、换行问题, triggers: { keywords: [format, lint, style, 格式化], semantic: 用户要求统一代码风格或修复格式问题 }, input_schema: { type: object, properties: { code: {type: string}, language: {type: string} }, required: [code, language] }, output_schema: { type: object, properties: { formatted_code: {type: string}, changes: {type: array} } } }上面这个 JSON 就是一个 skill 的元信息定义。实际写的时候我建议把 input_schema 和 output_schema 写清楚这样调度层可以做参数校验避免传错数据导致 skill 崩溃。3.2 引入技能的三种方式手动、自动、混合“怎么引入这些技能”是搜索里出现频率很高的问题。我实测下来引入方式主要有三种各有适用场景。手动引入最简单就是在配置文件里显式列出要加载的 skill ID。适合 skill 数量少、变动不频繁的场景。优点是可控你知道系统里到底有哪些能力缺点是加新 skill 要改配置、重启服务。自动引入是调度层根据当前任务动态加载。比如检测到输入是代码就自动挂载代码相关的 skill。这种方式灵活但需要一套可靠的匹配机制否则容易加载一堆用不上的 skill拖慢速度。混合引入是我最推荐的。基础 skill 用手动方式常驻保证核心能力随时可用扩展 skill 用自动方式按需加载用完就释放。这样兼顾了稳定性和灵活性。具体配置大概长这样skills: manual: - code_formatter_v1 - data_validator_v1 - doc_generator_v1 auto: enabled: true max_concurrent: 3 match_threshold: 0.75 pool: - sql_optimizer_v1 - chart_builder_v1 - api_tester_v1max_concurrent控制同时加载的自动 skill 数量防止资源被占满。match_threshold是匹配阈值低于这个分数的 skill 不会被激活。这两个参数需要根据实际硬件和任务复杂度调我一般从 3 和 0.75 开始试。3.3 调度策略优先级、依赖、降级调度层不是简单地“匹配到就调用”它要处理三个问题优先级、依赖关系、降级。优先级解决的是“多个 skill 都匹配时先调哪个”。我的做法是给每个 skill 设一个priority字段数字越小优先级越高。同时考虑“特异性”——越专门的 skill 优先级越高。比如“Python 代码格式化”比“通用代码格式化”更专门应该先匹配。依赖关系解决的是“skill A 的输出是 skill B 的输入”这种情况。调度层需要维护一个有向无环图确保执行顺序正确。这里有个坑循环依赖会导致死锁。我一般会在注册 skill 时做一次环检测有环直接拒绝注册。降级是容错机制。某个 skill 执行失败或超时调度层可以走备用路径。比如“高级代码分析”失败了降级到“基础语法检查”。降级策略要提前配好不能等出问题了再想。# 调度层核心逻辑示意 def dispatch(request, skill_registry): candidates match_skills(request, skill_registry) candidates.sort(keylambda s: (s.priority, -s.specificity)) for skill in candidates: if not check_dependencies(skill, request.context): continue try: result execute_with_timeout(skill, request, timeout30) if result.status success: return result except TimeoutError: log.warning(f{skill.id} timeout, trying fallback) fallback get_fallback(skill) if fallback: return execute_with_timeout(fallback, request, timeout15) return default_response(request)这段逻辑里match_skills做匹配check_dependencies检查依赖execute_with_timeout带超时执行失败后找降级 skill。超时时间我设 30 秒降级设 15 秒这是根据常见任务的耗时分布定的——大部分 skill 在 10 秒内完成超过 30 秒的基本是卡住了。3.4 注意事项三个容易翻车的地方第一skill 粒度不要太细也不要太粗。太细了调度开销大太粗了复用性差。我的经验是一个 skill 对应一个“原子操作”比如“提取关键词”“计算相似度”“生成摘要”而不是“处理一篇文章”。第二输入输出一定要做校验。我见过太多因为上游传了脏数据导致 skill 崩溃的案例。在 skill 入口加一层 schema 校验不合法直接返回错误别让脏数据流进去。第三日志要打全。每个 skill 的输入、输出、耗时、状态都要记。出问题的时候这些日志就是救命稻草。我一般用结构化日志方便后续做聚合分析。4. 实操过程与核心环节实现从零搭一套可运行的 superpowers4.1 环境准备与依赖安装先说明一下superpowers 本身不是某个具体的包所以“安装 superpowers”这个说法准确理解应该是“搭建一套支持 skill 挂载的运行环境”。我下面以 Python 技术栈为例其他语言思路一样。基础依赖就几个一个 Web 框架用来接收请求我用 FastAPI一个任务队列用来异步执行 skill我用 Celery一个配置管理库我用 Pydantic Settings。数据库可选如果 skill 状态需要持久化就加 Redis。pip install fastapi uvicorn celery redis pydantic-settings装完之后建项目结构superpowers/ ├── config/ │ └── skills.yaml ├── core/ │ ├── dispatcher.py │ ├── registry.py │ └── executor.py ├── skills/ │ ├── code_formatter.py │ ├── data_validator.py │ └── doc_generator.py └── main.py这个结构里core放调度、注册、执行的核心逻辑skills放各个 skill 的实现config放配置文件。清晰、好维护。4.2 注册第一个 skill代码格式化我拿“代码格式化”这个 skill 做例子因为它逻辑简单、效果直观适合第一次跑通流程。先写 skill 本体# skills/code_formatter.py import black import autopep8 from core.registry import register_skill register_skill( skill_idcode_formatter_v1, name代码格式化, version1.0.0, priority10, triggers{ keywords: [format, lint, style, 格式化], semantic: 用户要求统一代码风格或修复格式问题 } ) def format_code(code: str, language: str python) - dict: if language python: try: formatted black.format_str(code, modeblack.Mode()) except Exception: formatted autopep8.fix_code(code) else: formatted code # 其他语言暂不处理 return { formatted_code: formatted, changes: detect_changes(code, formatted) }register_skill是个装饰器负责把 skill 的元信息和执行体注册到全局注册表。priority10表示优先级中等triggers里同时配了关键词和语义描述。然后写注册表# core/registry.py SKILL_REGISTRY {} def register_skill(skill_id, name, version, priority, triggers): def decorator(func): SKILL_REGISTRY[skill_id] { id: skill_id, name: name, version: version, priority: priority, triggers: triggers, func: func } return func return decorator def get_skill(skill_id): return SKILL_REGISTRY.get(skill_id) def list_skills(): return list(SKILL_REGISTRY.values())注册表就是个字典key 是 skill_idvalue 是元信息加执行函数。简单直接。4.3 调度层实现匹配、排序、执行调度层是核心我把它拆成三个函数match、rank、execute。# core/dispatcher.py from core.registry import list_skills, get_skill from core.executor import run_skill def match_skills(request_text, threshold0.75): matched [] for skill in list_skills(): score calculate_match_score(request_text, skill[triggers]) if score threshold: matched.append((skill, score)) return matched def calculate_match_score(text, triggers): keyword_score 0 for kw in triggers.get(keywords, []): if kw.lower() in text.lower(): keyword_score 1 keyword_score min(keyword_score / max(len(triggers.get(keywords, [])), 1), 1.0) semantic_score semantic_similarity(text, triggers.get(semantic, )) return 0.4 * keyword_score 0.6 * semantic_score def dispatch(request): matched match_skills(request.text) matched.sort(keylambda x: (x[0][priority], -x[1])) for skill, score in matched: result run_skill(skill, request) if result[status] success: return result return {status: no_match, output: None}calculate_match_score里关键词占 40% 权重语义占 60%。这个比例是我调出来的——纯关键词太死板纯语义又容易误匹配四六开比较平衡。semantic_similarity可以用现成的 embedding 模型算余弦相似度也可以用简单的词重叠算法看你对精度的要求。4.4 执行层与超时控制执行层负责实际调用 skill 函数加上超时和错误处理。# core/executor.py import signal from core.registry import get_skill class TimeoutError(Exception): pass def timeout_handler(signum, frame): raise TimeoutError(skill execution timeout) def run_skill(skill, request, timeout30): signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(timeout) try: func skill[func] output func(**request.params) return {status: success, output: output, skill_id: skill[id]} except TimeoutError: return {status: timeout, output: None, skill_id: skill[id]} except Exception as e: return {status: error, output: str(e), skill_id: skill[id]} finally: signal.alarm(0)这里用signal.alarm做超时控制简单有效。注意finally里要取消 alarm否则会影响后续调用。生产环境里我建议用进程池或线程池做隔离避免一个 skill 卡死拖垮整个服务。4.5 完整调用链路演示把上面几块拼起来跑一个完整流程# main.py from fastapi import FastAPI from pydantic import BaseModel from core.dispatcher import dispatch import skills.code_formatter # 触发注册 app FastAPI() class Request(BaseModel): text: str params: dict {} app.post(/execute) def execute(req: Request): result dispatch(req) return result启动服务uvicorn main:app --reload --port 8000发一个请求curl -X POST http://localhost:8000/execute \ -H Content-Type: application/json \ -d {text: 帮我格式化这段代码, params: {code: def f(x):\n return x1, language: python}}返回结果里会包含格式化后的代码和变更列表。到这一步一个最小可用的 superpowers 环境就跑通了。4.6 参数调优超时、并发、阈值跑通之后下一步是调参。我列几个关键参数和我的经验值参数含义建议值调整方向timeout单 skill 超时30s任务重就调大但别超过 60smax_concurrent最大并发 skill 数3看 CPU 核数一般设核数的一半match_threshold匹配阈值0.75误匹配多就调高漏匹配多就调低retry_count重试次数2幂等 skill 可以设 3非幂等设 0log_level日志级别INFO调试时用 DEBUG生产用 INFO这些值不是固定的要根据实际负载和任务特点调。我一般会做一轮压测看 P99 延迟和错误率再决定怎么调。5. 常见问题与排查技巧实录踩过的坑和填坑方法5.1 skill 匹配不准怎么办这是最常见的问题。表现是该触发的 skill 没触发不该触发的乱触发。排查思路分三步。第一步看关键词覆盖。把实际请求里的高频词和 skill 的关键词列表对一遍缺什么补什么。我一般会跑一周的日志统计“未匹配”请求里的词频把 top 20 的词补进关键词。第二步调语义匹配模型。如果关键词没问题但还是不准那就是语义相似度算得不对。换一个更适合你领域的 embedding 模型或者在语义描述里多写几个同义表达。第三步调阈值。阈值太高会漏太低会误。我一般从 0.75 开始每次调 0.05观察一周的准确率和召回率找到平衡点。5.2 skill 执行超时怎么处理超时通常有两个原因skill 本身太慢或者输入数据太大。如果是 skill 太慢先看它的时间复杂度。比如一个 O(n²) 的算法处理大列表肯定慢。优化算法或者加缓存。如果是输入太大可以在调度层做预处理把大输入拆成小块分片执行再合并。还有一种情况是死锁。skill A 等 skill B 的输出skill B 又等 skill A互相卡住。这个在注册时做环检测就能避免。我一般用拓扑排序检查依赖图有环直接拒绝注册。5.3 多个 skill 结果冲突怎么合并有时候两个 skill 都匹配上了输出还不一样。比如一个说“这段代码没问题”另一个说“有语法错误”。这时候需要一套冲突解决策略。我的做法是按优先级取信。优先级高的 skill 结果为准优先级低的作为参考。如果优先级相同就看置信度——每个 skill 输出里带一个confidence字段取高的那个。如果冲突频繁发生说明 skill 的职责划分有问题需要重新设计。两个 skill 管同一件事本身就是设计缺陷。5.4 常见问题速查表问题现象可能原因排查方法解决方案skill 不触发关键词缺失/阈值过高看匹配日志补关键词/降阈值skill 误触发关键词太泛/阈值过低看误触发样本收窄关键词/升阈值执行超时算法慢/输入大/死锁看耗时分布优化/分片/环检测结果冲突职责重叠看冲突日志调优先级/重构 skill内存暴涨skill 泄漏/并发过高看内存曲线修泄漏/降并发日志缺失日志级别/采样看配置调级别/关采样5.5 独家避坑技巧技巧一skill 版本管理要用好。每次改 skill 逻辑版本号加一老版本保留。出问题可以快速回滚。我一般用skill_id version做唯一键调度时指定版本。技巧二灰度发布。新 skill 先挂 10% 流量观察一周没问题再全量。这个在配置里加个traffic_ratio字段就能实现。技巧三定期清理僵尸 skill。有些 skill 写了之后从来没用过或者已经被新版本替代。定期跑一遍使用统计把零调用的 skill 下线减少维护负担。技巧四输入输出做脱敏。skill 日志里可能包含敏感数据记录前先脱敏。我一般用正则把手机号、邮箱、身份证号替换成占位符。技巧五压测要覆盖边界。空输入、超长输入、特殊字符输入这些边界情况最容易出问题。上线前跑一遍边界测试能省很多事后救火的时间。6. 能力扩展的边界与我的实际体会superpowers 这套东西说到底是在“通用能力”和“专用能力”之间搭了一座桥。桥搭得好通用能力就能快速适配各种场景搭得不好就是一堆 skill 互相打架维护成本比不用还高。我在实际项目里最大的体会是skill 的设计比实现重要十倍。一个 skill 如果职责清晰、接口干净实现起来就是几十行代码的事如果职责模糊、接口混乱写几百行也是漏洞百出。所以我现在写 skill 之前会先花时间想清楚三个问题它解决什么问题、输入是什么、输出是什么。这三个问题想明白了代码自然就出来了。另一个体会是不要追求大而全。我见过有人想把所有能力都做成 skill结果注册表里几百个 skill调度一次要遍历半天。skill 不是越多越好够用就行。核心能力常驻边缘能力按需加载这个平衡点需要根据实际业务找。最后分享一个小技巧给每个 skill 写一个“最小可运行示例”。就是一段最简单的调用代码能跑通就行。这个示例放在 skill 的文档里新人接手时看一眼就知道怎么用比看几百行说明文档管用得多。我自己维护的 skill 库里每个 skill 都配了这样一个示例实测下来团队协作效率提升很明显。这套东西后续还可以往两个方向扩展一是做 skill 的自动发现和推荐根据历史调用记录主动推荐可能用得上的 skill二是做 skill 的组合编排把多个 skill 串成一条流水线一次调用完成多个步骤。这两个方向我都在试有进展再分享。