ANTIGRAVITY LABEN
記事一覧/Antigravity 基本
Antigravity 基本/2026-08-02上級

同じ agent.md を別のリポジトリへ置いたら、静かに別の仕事をしていました — 移植先で能力契約を解決してから走らせる

CLI 1.1.6 で agent.md をファイルとして持ち回れるようになりました。同じ定義を8つのリポジトリへ置き、走らせる前に前提が揃っているかを解決する仕組みを実装し、素朴な確認器との差を実測しています。

Antigravity347Antigravity CLI19エージェント設計17MCP20計測8個人開発92

プレミアム記事

夜の 23 時すぎ、リリースノートを整形するエージェントの定義ファイルを、別のアプリのリポジトリへコピーしました。前の週に書いたものが気に入っていたので、そのまま使い回すつもりでした。

翌朝、出力を読んで手が止まりました。

タグの差分は正しく拾えています。文面も悪くありません。ただ、下書きが Slack に流れていないのです。ログを追うと、エージェントは投稿を試みた形跡すらありませんでした。使えない道具は、最初から無かったことにして進んでいたのでした。

CLI 1.1.6 で、カスタムエージェントを Markdown ファイルとして定義できるようになりました。役割と手順をテキストで持てるため、リポジトリに置いてバージョン管理する運用が素直に成立します。持ち回れるということは、置いた先の環境に依存するということでもあります。

定義そのものは移植できます。定義が前提にしている環境は、移植されません。

個人開発では、アプリごとにリポジトリが分かれています。私の場合は 8 本。同じ作業を 8 回書きたくないからファイル化したのに、そのファイルが置いた先で静かに別の仕事をするなら、意味が半分になってしまいます。

この記事は、その半分を取り戻すために書いた仕組みと、実装しながら見つけた読み違いの記録です。

agent.md が暗黙に前提にしているもの

1.1.6 の agent.md は、YAML フロントマターで振る舞いを宣言します。mainAgentsubagent で立ち位置を、inheritMcp で MCP 設定の継承を、commandExecutionPolicy でコマンド実行の方針を決めます。

この記事で扱う定義は、こういう形です。

---
name: release-notes
mainAgent: false
subagent: true
hidden: false
inheritMcp: true
model: inherit
commandExecutionPolicy: allowlist
allowedCommands:
  - "git log"
  - "git tag"
  - "npm run build"
requiredMcpTools:
  - "github.list_releases"
  - "github.create_release"
  - "slack.post_message"
---
 
# リリースノートを整形する
 
直近のタグからの差分を読み、ストア掲載用の文面へ落としてください。

requiredMcpTools は仕様上のキーではありません。私が自分で足した宣言です。ここが今回の設計の入り口になります。

inheritMcp: true は「移植先の MCP 設定を継承する」という意味であって、「必要な MCP サーバーが移植先にある」ことは何も保証しません。継承するのは設定であり、能力ではないからです。

allowedCommands も同じ構造をしています。npm run build を許可する宣言は、npm が入っていることを意味しません。許可と存在は別の話です。

つまり agent.md には、宣言されている前提と、宣言されていない前提の二層があります。前者は読めば分かります。後者は走らせてみるまで分かりません。

エージェントが「道具が無い」と気づいた時点で止まってくれるなら、まだ救いがあります。実際には、代わりの手段を探して進んでしまうことのほうが多いのでした。夜間に無人で回している枠では、この差が翌朝まで見えません。

だから、走らせる前に解決したいのです。

検証のための土台をつくる

手元の実際のリポジトリをそのまま公開できないため、同じ構造・同じ規模の 8 リポジトリを固定シードで組み立てて測っています。生成スクリプトも載せますので、同じ数字が出ることを手元で確認していただけます。

ばらつかせているのは 4 点です。mcp_config.json の URL キーの綴り、保有している MCP サーバー、サーバーが持つツール名の書き方、そして移植先に入っているコマンド。

#!/usr/bin/env python3
"""mkfixture.py — 検証用のリポジトリ群と agent.md を固定シードで作る"""
import json, os, random, shutil, textwrap
random.seed(20260802)
ROOT = "/tmp/exp/fixture"
shutil.rmtree(ROOT, ignore_errors=True)
 
AGENT_MD = textwrap.dedent("""\
---
name: release-notes
mainAgent: false
subagent: true
hidden: false
inheritMcp: true
model: inherit
commandExecutionPolicy: allowlist
allowedCommands:
  - "git log"
  - "git tag"
  - "npm run build"
requiredMcpTools:
  - "github.list_releases"
  - "github.create_release"
  - "slack.post_message"
---
 
# リリースノートを整形する
 
直近のタグからの差分を読み、ストア掲載用の文面へ落としてください。
""")
 
# (リポジトリ名, URLキーの綴り, {サーバー名: [ツール名]}, 使えるコマンド)
SPECS = [
    ("wallpaper-ios",    "serverUrl", {"github": ["list_releases", "create_release"],
                                       "slack": ["post_message"]}, ["git", "npm"]),
    ("wallpaper-android", "url",      {"github": ["list_releases", "create_release"],
                                       "slack": ["post_message"]}, ["git", "npm"]),
    ("calm-sounds",      "serverUrl", {"github": ["list_releases", "create_release"]},
                                       ["git", "npm"]),
    ("calm-sounds-web",  "url",       {"github": ["list_releases"],
                                       "slack": ["post_message"]}, ["git", "npm"]),
    ("photo-frame",      "serverUrl", {"github": ["listReleases", "createRelease"],
                                       "slack": ["post_message"]}, ["git", "npm"]),
    ("photo-frame-tv",   "url",       {"github": ["list_releases", "create_release"],
                                       "slack": ["post_message"]}, ["git"]),
    ("sleep-timer",      "serverUrl", {"gh": ["list_releases", "create_release"],
                                       "slack": ["post_message"]}, ["git", "npm"]),
    ("sleep-timer-mac",  "url",       {"github": ["list_releases", "create_release"],
                                       "slack": ["post_message"]}, ["git", "npm"]),
]
 
for repo, url_key, servers, cmds in SPECS:
    d = os.path.join(ROOT, repo)
    os.makedirs(os.path.join(d, ".antigravity", "agents"), exist_ok=True)
    with open(os.path.join(d, ".antigravity", "agents", "release-notes.md"), "w") as f:
        f.write(AGENT_MD)
    cfg = {"mcpServers": {}}
    for name, tools in servers.items():
        cfg["mcpServers"][name] = {
            url_key: f"https://mcp.internal.example/{name}",
            "timeoutMs": 15000,
            "tools": tools,
        }
    with open(os.path.join(d, ".antigravity", "mcp_config.json"), "w") as f:
        json.dump(cfg, f, indent=2)
    with open(os.path.join(d, "commands.json"), "w") as f:
        json.dump(sorted(cmds), f)
 
print(f"created {len(SPECS)} repos under {ROOT}")

commands.json は、移植先で使えるコマンドの一覧を模したものです。実運用では shutil.which で調べる部分にあたります。検証を決定的にしたかったため、ファイルへ落としました。

このばらつき方は、私の手元の実情をそのまま写しています。リポジトリを作った時期がばらけているので、設定ファイルの書き方も少しずつ違うのです。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
agent.md の requiredMcpTools と allowedCommands を移植先で解決する preflight 実装(8リポジトリ 10.64 ms・240リポジトリ 318 ms の実測付き)
url と serverUrl の両対応が原因で、素朴な確認器の指摘 17 件のうち 14 件(82.4%)が空振りになった経緯と、正規化で潰す手順
指摘が多いほうの確認器が唯一見落としていた本当の停止要因。MCP ではなく allowedCommands 側にあった話
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

Antigravity 基本2026-07-01
Antigravity 2.0 でチャット側に MCP が出てこないときに確認したこと
Antigravity 2.0 が IDE とチャット型エージェントの2アプリに分かれてから、IDE で設定した MCP サーバーがチャット側の一覧に出てこなくなりました。設定スコープが別々になっている原因と、ワークスペース単位に真実源を一本化して両アプリで揃える手順をまとめます。
Antigravity 基本2026-06-15
ツールが Antigravity へ集約する時期に、ロックインを測って退避路を残す
Google が AI コーディングツールを Antigravity に集約し、6/18 に Gemini CLI が個人向け提供を終える局面で、個人開発者がベンダーロックインの度合いを定量化し、いつでも退避できる構成を残しておくための実務的な設計をまとめました。
Antigravity 基本2026-06-14
Gemini 3.5 Flash がデフォルトになった後、Flash と Pro をタスク単位で振り分ける
Antigravity の既定 Flash が Gemini 3.5 Flash に切り替わった今、すべてを Flash に任せるのも、不安だからと Pro に寄せるのも、どちらも無駄が出ます。タスクの性質ごとに Flash と Pro を振り分ける判定表と、エージェント設定に落とすルーティング実装をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →