如何让Antigravity Agent技能可配置(无需分叉)
教程介绍如何构建配置层,使Antigravity Agent技能支持项目级配置,避免分叉,并逐步演示构建与测试方法。
中文处理结果
Antigravity Agent技能是一种很好的方式,可以教会你的AI代理一次工作流,并在任何地方重复使用。你编写一个简短的SKILL.md文件,将其放入文件夹,代理就会在相关时自动找到它。
但这些技能有一个隐藏的限制:它们是静态的。如果你下载了别人编写的技能,并希望它的行为略有不同,你必须复制整个文件并手动编辑。而且你可能已经注意到,最近有很多难以维护的“skills”分叉。
在本教程中,我将展示我构建的一个小约定来解决这个问题。它允许任何Agent技能读取特定于项目的配置文件,因此你可以采用任何技能并通过编辑几行YAML来定制其行为(而不用修改技能本身)。
你将逐步构建它、测试它,并了解如何分享它,以便其他人可以使用。
## 目录
- 你将构建什么 - 先决条件 - 什么是Antigravity Agent技能? - 为什么静态技能是个问题 - 可配置技能解决方案 - 如何构建配置加载器 - 如何使技能可配置 - 如何添加项目覆盖 - 如何测试可配置技能 - 另外两个示例技能 - 如何与他人分享你的Agent技能 - 总结
## 你将构建什么
你将构建一个名为“可配置Agent技能”的微型可复用层。它由三个部分组成:
- 一个小的Python脚本resolve_config.py,将技能的默认设置与项目设置合并,并打印结果。 - 一个约定:每个技能附带2个文件,一个带有“旋钮”的config.default.yaml文件和一个SKILL.md文件。它们共同引导代理的行为。 - 一个项目级文件.agent/skills.config.yaml,使用你技能的任何人都可以在其中设置自己的值。
最后,你将拥有一个可用的git-commit-formatter技能,一个团队可以在Conventional Commits模式下运行,另一个团队可以切换到gitmoji模式,所有都使用完全相同的技能文件,无需分叉。
## 先决条件
要继续,你需要:
- 安装Google Antigravity(IDE、CLI或SDK,它们都可以用,因为技能只是文件)。 - 安装Python 3,以及PyYAML。你可以使用python -m pip install pyyaml安装PyYAML。 - 对终端和YAML有基本的熟悉度。你不需要成为专家。
如果你从未编写过Agent技能,接下来的两个部分将让你快速上手。
## 什么是Antigravity Agent技能?
Antigravity中的技能是一个包含SKILL.md文件以及可选脚本、模板或示例的文件夹。SKILL.md文件顶部有一段简短的YAML“前置元数据”(名称和描述),后跟一组用纯Markdown编写的说明。
原始正文摘录
How to Make Your Antigravity Agent Skills Configurable (Without Forking Them)
Antigravity Agent Skills are a great way to teach your AI agent a workflow once and reuse it everywhere. You write a short SKILL.md file, drop it in a folder, and the agent picks it up whenever it's relevant.
But these skills have a hidden limitation: they're static. If you download a skill someone else wrote and you want it to behave a little differently, you'll have to copy the whole thing and edit it by hand. And as you may have noticed lately, there are many "skills" forks floating around that are difficult to maintain.
In this tutorial, I'll show you I built a small convention that fixes this. It lets any Agent Skill read a per-project config file, so you can adopt any skill and customize how it behaves by editing a few lines of YAML (without ever touching the skill itself).
You'll build it step by step, test it, and see how to share it so other people can plug into it.
Table of Contents
- What You Will Build
- Prerequisites
- What Are Antigravity Agent Skills?
- Why Static Skills Are a Problem
- The Configurable Skills Solution
- How to Build the Config Loader
- How to Make a Skill Configurable
- How to Add Project Overrides
- How to Test Your Configurable Skill
- Two More Example Skills
- How to Share Your Agent Skills With Others
- Wrapping Up
What You Will Build
You will build a tiny, reusable layer called Configurable Agent Skills. It has three parts:
- A small Python script, resolve_config.py, that merges a skill's default settings with your project settings and prints the result.
- A convention: each skill ships 2 files, a config.default.yaml file with its "knobs" and a SKILL.md file. They both guide the agent's behavior.
- A per-project file, .agent/skills.config.yaml, where anyone using your skill sets their own values.
By the end, you'll have a working git-commit-formatter skill that one team can run in Conventional Commits mode and another team can switch to gitmoji mode, all using the exact same skill files with no forking.
Prerequisites
To follow along, you'll need:
- Google Antigravity installed (the IDE, CLI, or SDK. Any of them work, since skills are just files.).
- Python 3 installed, with PyYAML. You can install PyYAML with python -m pip install pyyaml.
- Basic comfort with the terminal and YAML. You don't need to be an expert in either.
If you've never written an Agent Skill before, the next two sections will bring you up to speed.
What Are Antigravity Agent Skills?
A Skill in Antigravity is a folder that contains a SKILL.md file and, optionally, some scripts, templates, or examples. The SKILL.md file has a short block of YAML "frontmatter" at the top (a name and a description), followed by a set of instructions written in plain Markdown.
Here's the important part: skills are loaded on demand. The agent reads only the short description of each skill at first. When your request matches that description, the agent pulls in the full instructions and follows them. This keeps the agent's context small and focused.
A minimal skill that enforces Conventional Commits looks like this:
--- name: git-commit-formatter description: Formats git commit messages using the Conventional Commits specification. Use this when the user asks to commit changes or write a commit message. ---
# Git Commit Formatter
When writing a commit message, follow the Conventional Commits format: `type(scope): description`
Allowed types: feat, fix, docs, style, refactor, perf, test, chore.
Drop that in your skills folder, ask the agent to "commit these changes," and it will write a properly formatted message. Simple and useful, right?
Why Static Skills Are a Problem
Now look closely at that skill. The allowed types (feat, fix, docs, and so on) are baked directly into the instructions.
That's fine until someone wants something slightly different. Maybe your team also uses a ci type. Maybe you prefer gitmoji, where each commit starts with an emoji. Maybe you want to require a scope on every commit.
With a static skill, there's only one way to get any of that: copy the whole skill and edit the Markdown. When you do this across a team, everyone ends up with their own private fork. When the original author ships an improvement, none of the forks get it. The skill stops being something you share and becomes something everyone rewrites.
The core issue is that there's no clean line between the skill's logic (which everyone should share) and its settings (which each project wants to control). How do we solve this?
The Configurable Skills Solution
The idea is simple. Instead of hard-coding settings in the instructions, the skill will:
- Ship its settings and their defaults in a separate config.default.yaml file.
- Read a merged config (defaults plus any project-level overrides) before it acts.
The project-level overrides live in a file called .agent/skills.config.yaml, which sits at the root of the user's project:
# .agent/skills.config.yaml # (edit this file in your project instead of the skill globally) git-commit-formatter: style: gitmoji extra_types: [ci, build] scope_required: true
That's the easy flow. Drop the skill in, set a few keys, and you're done. The skill's own files never change.
To make this work, you need a script that reads both files, merges them, and hands the result to the agent. Let's build it.
How to Build the Config Loader
Create a file called resolve_config.py. Its job is to take a skill's name, load that skill's config.default.yaml, find the user's .agent/skills.config.yaml, and merge the two so that user values win.
Start with a deep-merge helper. This is the heart of the loader:
def deep_merge(base, override): """Recursively merge override onto base.
Dicts merge key by key. Anything else (scalars, lists) is replaced wholesale by the override value. """ 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
Notice the deliberate choice here: dictionaries merge key by key, but lists are replaced, not appended. That keeps the behavior predictable. If you want to handle "defaults plus extras", use the explicit extra_types key in the skill as you'll see in the example below.
Next, you need to find your "per-project" config. The loader walks up from the current directory looking for an .agent/skills.config.yaml file:
from pathlib import Path
def find_project_config(start: Path): """Walk upward from start looking for .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
Now put it together. The loader locates the skill's defaults (which sit next to the script), loads your overrides for that skill's name, merges them, and prints the result:
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)
That completes the whole idea. The full version in the sample repo adds a command-line interface, JSON output, and clear error messages, but the logic above is all you really need.
How to Make a Skill Configurable
Now you'll convert the static commit skill into a configurable one. This takes two files.
First, create config.default.yaml next to the skill. It lists every setting and a safe default, so the skill works even when the user has no config at all:
# Default configuration for the git-commit-formatter skill. style: conventional # conventional | gitmoji types: # base set of allowed commit types - feat - fix - docs - style - refactor - perf - test - chore extra_types: [] # additional types, merged on top of `types` scope_required: false # if true, require a scope: type(scope): ... max_subject_length: 72 # hard cap on the subject line
Second, update SKILL.md so that its very first instruction is to resolve the config and apply it. This is the key move: you're telling the agent to read the settings before it does anything else:
--- name: git-commit-formatter description: Formats git commit messages to a team's chosen convention (Conventional Commits or gitmoji). Use this when the user asks to commit changes or write a commit message. Reads per-project settings so teams customize commit style without editing this skill. ---
# Git Commit Formatter (Configurable)
## Step 1 - Resolve configuration (always do this first)
Run the loader and read its output:
`python scripts/resolve_config.py git-commit-formatter --project-root .`
Apply exactly those settings:
- `style`: `conventional` or `gitmoji`. - `types` + `extra_types`: the full set of allowed commit types. - `scope_required`: if true, a scope is mandatory. - `max_subject_length`: hard cap on the subject line.
## Step 2 - Compose the message
Pick the primary type from `types` + `extra_types`, build the subject in the chosen `style`, and enforce `scope_required` and `max_subject_length`.
This pattern ("make the agent run a script and obey its output") is the same one Antigravity's own validation skills use. It keeps the behavior deterministic instead of leaving it to the model's memory.
Notice how extra_types solves the additive-list question. The default list stays put, and the user's extras are simply added on top by the skill. No fork is required to add a ci type.
How to Add Project Overrides
Let's say you want gitmoji commits with two extra types. Create a single file in your project:
# .agent/skills.config.yaml git-commit-formatter: style: gitmoji extra_types: [ci, build] scope_required: true
You just changed three lines of config and didn't open the skill or fork any code. The next time the agent commits, it will use this project settings.
And a different project, with no config file at all, keeps getting the sensible Conventional Commits defaults. You have one skill with many behaviors.
How to Test Your Configurable Skill
You don't need the agent to check that the merge works. Run the loader directly and read the output.
With no overrides, you get the defaults:
$ python scripts/resolve_config.py git-commit-formatter --project-root . style: conventional scope_required: false ...
Now add the .agent/skills.config.yaml override from the last section and run it again:
$ 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 ...
The style flipped to gitmoji, scope_required became true, and your extra types appeared (while the base types list stayed intact). That confirms the merge does exactly what you want.
It's worth writing a small automated test too, so a future change to the loader can't silently break the merge. A test can create a fake skill and a fake project config in a temp folder, run the loader, and assert that user values override defaults while untouched defaults survive.
Two More Example Skills
The same pattern works for any skill. Here are two more to show the range.
A Changelog Generator
Its config.default.yaml exposes the output format (like Keep a Changelog), which commit types to include, and whether to link commit hashes to a repo URL. One project can generate a formal changelog grouped by type, while another can generate a simple bulleted list. It's the same skill with a different config.
# changelog-generator config.default.yaml (excerpt) format: keepachangelog # keepachangelog | conventional | simple include_types: [feat, fix, perf] include_authors: false repo_url: "" # if set, hashes link to commits
A License-Header Adder
Its config exposes the license (Apache-2.0, MIT, or custom), the holder, and a map of file extensions to comment styles. A company sets the holder once in their project config, and every new file gets the right header in the right comment style, without editing the skill.
# license-header-adder config.default.yaml (excerpt) license: apache-2.0 # apache-2.0 | mit | custom holder: "Your Name or Org" year: auto # auto = current year
The lesson is that almost any skill has a few decisions baked into it. When you pull those decisions into a config.default.yaml, you convert a one-off skill into a tool that anyone can reuse and tune.
How to Share Your Agent Skills With Others
Once your agent skills follow the convention, they compose into something bigger. To make your agent skills easy for others to adopt, you have to:
- Keep each skill self-contained: Vendor a copy of resolve_config.py inside each skill's scripts/ folder, so someone can copy a single skill folder anywhere and it just works.
- Document every config key in the SKILL.md, so users know exactly what they can tune.
- Publish a small index: A simple index.json that lists each skill's name, path, and config keys makes it easy for others to discover what you've built and contribute their own.
Because the convention is just "read a config file first," anyone can publish a compatible skill. Each new configurable skill makes the whole ecosystem more useful. In addition to shipping a skill, you're shipping a small standard that other people can build on.
Wrapping Up
You started with a static skill whose behavior was frozen in Markdown, and you turned it into a configurable one that anyone can tune from a single project file.
The entire setup is relatively small. It has the merge function, one convention, and a config.default.yaml per skill.
It also changes how skills are shared. Instead of forking a skill to change one setting, you can keep the shared logic and adjust your own config. Improvements to the skill flow to everyone, and everyone still gets the behavior they want.
If you want to try it, build the git-commit-formatter skill from this tutorial, drop it into your Antigravity skills folder, and add an .agent/skills.config.yaml to a project. Then flip style from conventional to gitmoji and watch the same skill behave differently.
From there, make one of your own skills configurable. Find the settings you baked into the instructions, move them into a config.default.yaml, and let your users take it from there.
The full sample code (the loader, its tests, and all three example skills) is on GitHub at github.com/keepdeploying/configurable-agent-skills.
Thanks for reading. If you build a configurable skill of your own, share it. Let's keep the ecosystem growing.