← 返回蜂巢洞察

如何让你的反重力技能具备可配置性(同时避免出现代码分支问题)

“反重力智能体技能”是一种非常有效的方法,可以帮助你一次性为人工智能智能体设定工作流程,并让它在各种场景中都能被重复使用。你只需编写一个简短的`SKILL.md`文件,将其放入相应的文件夹中,智能体在需要使用时就会自动加载这些配置。 然而,这类技能存在一个隐藏的局限性:它们是静态的。如果你下载了别人编写的技能代码,但希望它的行为有所改变,你就必须手动复制整个代码并进行修改。而且,最近你也应该注意到了,市面上有很多经过分叉修改的“技能版本”,这些版本往往很难进行维护。 在本次教程中,我将向你展示一种解决方法。这种方法可以让任何智能体技能读取特定项目中的配置文件,因此你完全可以使用现有的技能,只需

“反重力智能体技能”是一种非常有效的方法,可以帮助你一次性为人工智能智能体设定工作流程,并让它在各种场景中都能被重复使用。你只需编写一个简短的`SKILL.md`文件,将其放入相应的文件夹中,智能体在需要使用时就会自动加载这些配置。

然而,这类技能存在一个隐藏的局限性:它们是静态的。如果你下载了别人编写的技能代码,但希望它的行为有所改变,你就必须手动复制整个代码并进行修改。而且,最近你也应该注意到了,市面上有很多经过分叉修改的“技能版本”,这些版本往往很难进行维护。

在本次教程中,我将向你展示一种解决方法。这种方法可以让任何智能体技能读取特定项目中的配置文件,因此你完全可以使用现有的技能,只需通过编辑几行YAML格式的配置文件,就能自定义其行为——而无需直接修改原始的技能代码本身。

你会一步步学习如何构建这个系统,进行测试,并了解如何与他人共享这些配置方案,以便其他人也能将其应用到自己的项目中。

目录

你将构建什么

你将构建一个名为“可配置智能体技能”的小型工具模块。它由三个部分组成:

  1. 一个Python脚本`resolve_config.py`,它的作用是将技能的默认设置与项目特定的配置合并,并输出最终结果。

  2. 一种约定机制:每个技能都会包含两个文件:一个是`config.default.yaml`文件,其中包含了可调整的参数;另一个是`SKILL.md`文件,用于说明智能体应如何根据这些参数来执行操作。

  3. 每个项目还会对应一个配置文件`.agent/skills.config.yaml`,使用者可以在此文件中设置自己需要的参数值。

最终,你将得到一个功能完备的“`git-commit-formatter`技能模块”——某个团队可以使用它以传统的提交格式进行开发,而另一个团队则可以将它切换到使用gitmoji符号的模式来进行操作。无论哪种方式,所有团队使用的都是完全相同的代码文件,根本不存在任何分叉版本的问题。

先决条件

要顺利学习本内容,您需要具备以下条件:

  • 已安装 Google Antigravity IDE、CLI 或 SDK。其中任意一种均可使用,因为这些工具所使用的文件格式都是相同的。

  • 已安装 Python 3 并安装了 PyYAML。您可以通过 python -m pip install pyyaml 命令来安装 PyYAML。

  • 应对终端操作和 YAML 格式有一定的了解。不过无需成为这些领域的专家即可。

如果您之前从未编写过代理技能脚本,接下来的两个章节将帮助您快速入门。

什么是 Antigravity 代理技能?

在 Antigravity 中,一个“技能”实际上是一个文件夹,其中包含一个 SKILL.md 文件,以及一些可选的脚本、模板或示例代码。SKILL.md 文件的开头部分会包含简短的 YAML 格式信息(如技能的名称描述),随后则是用纯 Markdown 编写的指令。

重要的是:这些技能是按需加载的。代理程序在最初只会读取每个技能的描述部分;只有当用户的请求与这个描述匹配时,才会加载完整的指令并执行它们。这样的设计有助于保持代理程序的工作状态简洁且专注。

以下是一个简单的示例:这个技能用于确保提交信息遵循“常规提交规范”:

---
name: git-commit-formatter
description: 使用常规提交规范来格式化 Git 提交信息。当用户需要提交更改或编写提交消息时,可以使用此技能。
---

# Git 提交信息格式化规则

在编写提交消息时,请遵循常规提交规范:
`type(scope): description`

允许的类型包括:feat、fix、docs、style、refactor、perf、test、chore。

将这个脚本放入您的技能文件夹中,然后让代理程序执行“提交这些更改”的操作,它就会生成格式正确的提交信息。很简单且非常实用,对吧?

为什么静态技能会带来问题

现在仔细看看这个示例技能。其中允许的类型(如 featfix 等)是直接写在指令中的。

这种设计在大多数情况下没有问题,但当有人需要一些不同的设置时,就会出现问题。也许您的团队还使用了其他类型的操作,比如 ci;也许您更喜欢在提交信息前加上表情符号;又或者您希望每个提交都必须指定具体的操作范围。

对于静态技能来说,要想实现这些需求,唯一的办法就是复制整个脚本并修改其中的 Markdown 代码。当整个团队都在使用这样的静态技能时,每个人最终都会拥有自己修改过的版本。而当原作者发布了更新内容时,其他人的版本却无法得到更新。这样一来,这种技能就不再是一种可以被大家共享的资源,而变成了每个人都在自行修改的东西。

问题的关键在于:技能的逻辑部分应该是所有人都可以共享的,而其具体设置则应该由每个项目根据自身需求来控制。那么,我们该如何解决这个问题呢?

可配置技能解决方案

这个思路很简单。与其在指令中硬编码设置,不如让该技能本身来处理这些设置:

  1. 将其设置及其默认值保存在一个单独的 config.default.yaml 文件中。

  2. 在执行任何操作之前,会先读取合并后的配置文件(包括默认值以及项目级别的自定义设置)。

项目级别的自定义设置保存在名为 .agent/skills.config.yaml 的文件中,该文件位于用户项目的根目录下:

# .agent/skills.config.yaml 
# 请在您的项目中编辑此文件,而不是对所有技能进行全局配置修改
git-commit-formatter:
  style: gitmoji
  extra_types: [ci, build]
  scope_required: true

使用这种方法非常简单:只需将相应的技能添加到项目中,设置一些关键参数即可完成配置。该技能自身的文件永远不会被修改。

为了让这个机制正常工作,你需要编写一个脚本,该脚本能够读取这两个文件,将它们合并后传递给代理程序。让我们一起来编写这个脚本吧。

如何构建配置加载器

创建一个名为 resolve_config.py 的文件。它的作用是:根据技能名称读取该技能的 config.default.yaml 文件,再查找用户项目中的 .agent/skills.config.yaml 文件,并将两者合并,确保用户的自定义设置优先得到应用。

首先需要编写一个用于深度合并配置文件的辅助函数。这个函数是整个加载器的核心:

def deep_merge(base, override):
    """递归地将 override 的内容合并到 base 中。

    字典类型的数据会按键进行合并;其他类型的数据(如标量、列表)则会被完全替换为 override 中对应的值。
    """
    if isinstance(base, dict) and isinstance(override, dict):
        merged = dict(base)
        for key, value in override.items():
            merged[key] = deep_merge(merged[key], value) if key in merged else value
        return merged
    return override

注意这里的设计意图:字典类型的数据会按键进行合并,而列表类型的数据则会被完全替换,而不会被追加到原来的列表中。这样的设计能够保证程序的行为具有可预测性。如果你需要同时保留默认值和用户自定义设置,可以在技能配置文件中使用 extra_types 这个键,如下例所示。

接下来,脚本需要找到用户项目中的配置文件。加载器会从当前目录开始查找名为 .agent/skills.config.yaml 的文件:

from pathlib import Path

def find_project_config(start: Path):
    """从指定路径开始向上查找 .agent/skills.config.yaml 文件."""
    start = start.resolve()
    for folder in [start, *start.parents]:
        candidate = folder / ".agent" / "skills.config.yaml"
        if candidate.is_file():
            return candidate
    return None

现在把所有这些部分组合起来。加载器会先找到技能的默认配置值,然后读取用户为该技能指定的自定义设置,将两者合并后返回最终结果:

import sys, yaml
from pathlib import Path

def resolve(skill_name, skill_dir, project_root):
    defaults = yaml.safe_load((Path(skill_dir) / "config.default.yaml").read_text()) or {}

    user_path = find_project_config(Path(project_root))
    user_all = yaml.safe_load(user_path.read_text()) if user_path else {}
    user_cfg = (user_all or "").get(skill_name, {}) or {}

    return deep_merge(defaults, user_cfg)

这样就完成了整个流程。示例仓库中的完整版本还增加了命令行界面、JSON格式的输出结果以及清晰的错误提示信息,但上述逻辑才是真正需要的部分。

终端输出显示了git-commit-formatter技能的配置结果。

如何使技能具备配置功能

现在,你将把这个静态的提交技能改造成一个可配置的技能。这需要两个文件。

首先,在该技能所在的目录下创建config.default.yaml文件。这份文件会列出所有的设置选项以及默认值,这样即使用户没有进行任何配置,该技能也能正常工作:

# git-commit-formatter技能的默认配置。
style: conventional          # 传统格式 | gitmoji格式
types:                       # 允许使用的提交类型
  - feat
  - fix
  - docs
  - style
  - refactor
  - perf
  - test
  - chore
extra_types: []              # 额外添加的类型,会叠加在`types`之上
scope_required: false        # 如果设置为true,则必须指定范围:type(scope): ...
max_subject_length: 72       # 主题行的长度上限

其次,更新SKILL.md文件,使其第一条指令就是读取配置并应用这些设置。这一点非常重要:你是在告诉代理在执行其他任何操作之前先读取配置信息:

---
name: git-commit-formatter
description: 将git提交信息格式化为团队选定的样式(传统格式或gitmoji格式)。当用户需要提交更改或编写提交信息时,可以使用这个技能。该技能会读取每个项目特定的配置设置,因此团队无需直接修改此文件即可自定义提交格式。
---

# Git提交信息格式化工具(可配置)

## 第一步——读取配置信息(务必先执行这一步)

运行加载程序并查看其输出结果:

`python scripts/resolve_config.py git-commit-formatter --project-root .`

然后应用这些配置设置:
- `style`:选择“conventional”或“gitmoji”格式。
- `types` + `extra_types`:所有允许使用的提交类型。
- `scope_required`:如果设置为true,则必须指定使用范围。
- `max_subject_length`:主题行的长度上限。

## 第二步——编写提交信息

从`types` + `extra_types`中选择主要的提交类型,按照选定的`style`格式生成主题行,并确保遵守`scope_required`和`max_subject_length`的限制。

这种“让代理运行脚本并执行其输出结果”的设计方式,也是Antigravity自身所使用的验证技能所采用的机制。这种方式能够确保行为的一致性,而不会让模型依赖于内存中的临时数据。

注意extra_types这个设置是如何解决类型扩展问题的。默认的类型列表保持不变,用户自定义的额外类型会被直接添加到默认列表中。因此,即使添加了ci这样的类型,也不需要进行任何修改即可。

如何为项目添加自定义配置选项

假设你希望使用带有两种额外类型的gitmoji格式来进行提交操作。那么只需在项目中创建一个配置文件即可:

# .agent/skills.config.yaml
git-commit-formatter:
  style: gitmoji
  extra_types: [ci, build]
  scope_required: true

你只需要修改三行配置内容,而无需打开任何代码文件或进行任何修改。下次代理执行提交操作时,就会使用这些配置设置。

而对于那些没有配置文件的项目来说,它们仍然会使用默认的“常规提交”格式。这样,你就能够通过一个配置文件来实现多种不同的行为。

代理会根据项目配置自动生成以表情符号开头的提交信息。

如何测试你的可配置技能

你不需要让代理来检查合并操作是否正常进行。可以直接运行加载工具并查看输出结果即可。

如果没有进行任何覆盖设置,那么系统会使用默认配置:

$ python scripts/resolve_config.py git-commit-formatter --project-root .
style: conventional
scope_required: false
...

现在,加入上一节中提到的.agent/skills.config.yaml文件中的配置设置,然后再运行一次加载工具:

$ python scripts/resolve_config.py git-commit-formatter --project-root . --print-sources
style: gitmoji
scope_required: true
extra_types:
- ci
- build
types:
- feat
- fix
- docs
...

此时,style的值被设置为gitmojiscope_required被设置为true,而那些额外的类型也会被正确显示出来(同时基础的types列表保持不变)。这证明了配置修改确实达到了预期的效果。

编写一个自动测试脚本也是很有必要的。这样,即使未来加载工具发生任何变化,也不会影响到合并操作的正常进行。测试脚本可以在临时文件夹中创建虚拟的技能配置和项目设置,然后运行加载工具,从而验证用户自定义的配置是否成功覆盖了默认值,同时确认默认值是否依然完好无损。

另外两个示例技能

这种配置模式适用于任何类型的技能。下面再举两个例子来进一步说明这一点的适用性。

变更日志生成器

这个工具的config.default.yaml文件允许用户指定输出格式(例如是否使用“keepachangelog”格式)、需要包含哪些类型的提交信息,以及是否将提交哈希链接到仓库地址。一个项目可以使用这种配置生成按类型分类的正式变更日志,而另一个项目则可能选择生成简单的列表格式。其实,这仍然是同一个技能,只是使用了不同的配置而已。

# changelog-generator config.default.yaml (excerpt)
format: keepachangelog       # 可选格式:keepachangelog | conventional | simple
include_types: [feat, fix, perf]
include_authors: false
repo_url: ""                 # 如果设置了这个参数,提交哈希将会链接到仓库地址

许可证头添加工具

该工具的配置文件中会指定许可协议类型(Apache-2.0、MIT或自定义格式)、版权持有者,以及文件扩展名与注释格式之间的对应关系。企业只需在项目配置中设置一次这些参数,之后新生成的文件就会自动添加正确的许可证头和相应的注释格式,而无需手动进行任何修改。

# license-header-adder config.default.yaml (示例)
license: apache-2.0          # 可选值:apache-2.0 | mit | custom
holder: "你的名称或组织名"
year: auto                   # 自动获取当前年份

关键在于:几乎任何工具或功能都包含一些固定的配置选项。当你把这些配置选项放入config.default.yaml文件中,这些原本一次性的配置就会变成一个可以被所有人重复使用并根据需求进行调整的工具。

如何与他人分享你的代理技能

一旦你的代理技能遵循了统一的规范,它们就可以组合成更强大的功能。为了让他人更容易采用这些技能,你需要做到以下几点:

  • 确保每个技能都是独立可用的:在每个技能的scripts/文件夹中放置一份resolve_config.py文件,这样别人就可以将某个技能文件夹复制到任何地方,而它依然能够正常使用。

  • 为所有的配置项编写说明:SKILL.md文件中详细解释每个配置项的作用,让用户清楚知道自己可以调整哪些内容。

  • 发布一个索引文件:创建一个简单的index.json文件,列出所有技能的名称、路径和配置项,这样别人就能轻松了解你的成果,并根据自己的需求进行扩展。

因为大家都遵循“先读取配置文件”的规则,所以任何人都可以发布符合规范的技能。每一个可配置的技能都会让整个生态系统变得更加有用。通过发布这样的技能,你其实也在推广一种可供他人进一步开发的标准。

总结

你最初使用的是一个行为固定的静态技能,后来将其改成了可以通过单个项目文件进行配置的动态技能。

整个设置过程非常简单:只需要一个合并函数、一套统一的规范,以及每个技能对应的config.default.yaml文件即可。

这种设计也改变了技能的共享方式——不再需要通过分支来修改某个设置,而是可以直接调整自己的配置文件。这样,所有的改进都会惠及所有使用者,而且每个人仍然能够得到自己想要的功能。

如果你想尝试这个方法,可以按照本教程中的步骤制作git-commit-formatter技能,将其添加到你的Antigravity技能文件夹中,并为该项目创建一个.agent/skills.config.yaml文件。然后将style参数从conventional改为gitmoji,你就会发现同一个技能会呈现出不同的表现效果。

接下来,你可以尝试将自己的某个技能也设置为可配置的。把那些固定的配置选项提取出来放入config.default.yaml文件中,让用户能够根据自己的需求进行自定义设置。

完整的示例代码(包括加载器、相关的测试用例以及三个示例技能)都托管在 GitHub 上,地址为 github.com/keepdeploying/configurable-agent-skills 感谢您的阅读。如果您自己也开发出了可配置的技能,请分享出来吧。让我们一起帮助这个生态系统不断发展壮大。

相关文章

技术实践

了解人工智能软件开发生命周期流程——构建智能代理功能的完整指南

也许你可以理解这样的场景:本周,你用了同样的说明四次向别人解释人工智能模型的使用方法。 你反复讲解过团队是如何构建演示文稿的框架的,哪些检查步骤需要在部署之前完成,以及为什么测试数据库并不是文档中提到的那个。 每次你都要把这些内容重新写一遍,每次智能助手也能完成得不错,但每次新的会话开始时,一切都得从零开始。 而这正是 智能助手技能 所要解决的问题。 技能 实际上就是一个文件夹,其中只包含一个名为 Skill.md 的文件。智能助手在启动时会阅读其中的一行总结内容,而只有当真正需要时才会打开完整的说明文件。你只需把解释内容编写一次,将其与代码一起提交,那么团队中的每个智能助手就能访问这些信息,

阅读全文
技术实践

如何在Flutter开发中运用各种技能:开发者手册

关于人工智能辅助开发,最大的误解之一就是认为使用人工智能就意味着要放弃多年来积累的工程经验。其实并非如此。 你可以将自己所学到的架构模式、犯过的错误、团队遵循的规范,以及作为Flutter工程师所制定的标准,通过特定的技能教给人工智能编码助手。这样一来,你就不必在自身经验与人工智能之间做出选择,而是可以将两者结合起来使用。 然而,几乎每一位Flutter开发者,在第一次在实际项目中使用人工智能编码助手时,都会遇到一些令人沮丧的情况。 比如,当你让助手生成一个个人资料页面时,它虽然能生成能够正常运行的代码,但却没有在`widgets/`文件夹中创建一个结构清晰、可重复使用的`ProfileCar

阅读全文
技术实践

如何使用Python构建一个人工智能文件分析工具

如果你曾经打开过一份30页的PDF文件,然后心想“我绝对不可能读完这一切”,那么你就已经理解了为什么文件分析人工智能工具会非常有用。 想象一下,当你上传一篇研究论文、简历、CSV文件、商业报告或PDF文档后,只需简单地问这样一个问题: “其中最重要的发现是什么?” 人工智能工具无需你手动浏览整个文件,就能理解文件的内容,并回答相关问题。 在本教程中,我们正是要构建这样的工具。我们将使用Python编写一个适合初学者的 AI文件分析工具 ,它能够: 从你的电脑中接收文件 将文件上传到人工智能模型中 读取文件的内容 理解自然语言提出的问题 分析文件 给出有用的答案 处理各种类型的问题,而无需我们为

阅读全文
技术实践

如何使用 Shadcn UI 在 React 中构建可扩展的客户身份验证及入职流程

任何具有合规性要求的B2B SaaS产品(比如涉及银行业务、贷款服务、工资发放或加密货币相关的应用)在开发初期都会遇到同样的问题:在允许企业使用你的平台之前,你必须先核实他们的身份。 这意味着需要收集企业的类型信息、审核他们的注册文件,并向用户展示他们的验证进度,但整个流程不能让人感觉像是在填写繁琐的海关表格一样。 本文详细介绍了如何利用Shadcn UI构建一个功能完备的三步客户身份验证流程:包括用于显示操作进度的步骤提示组件、用于选择账户类型的单选组、用于上传文件的区域,以及用于显示验证状态的警告提示。你会看到实际的代码实现,而不仅仅是简化后的示例代码,同时也会了解到每个设计决策背后的理由

阅读全文