前編では Antigravity の4つのサーフェスを「どんなときにどれを選ぶか」という観点で整理しました。実際のプロジェクトでは、4つのどれか一つに決め打ちするより、フェーズごとに入り口を切り替えるほうがずっと滑らかに進みます。ここでは私が個人開発で回している組み合わせ方を、SDK の実装まで含めて具体的にお見せします。
題材は、Dolice Labs のブログ記事の下調べと、それに付随するコード検証を半自動化するという、ありふれた個人開発の一場面です。派手な構成ではありませんが、4つのサーフェスがそれぞれの持ち場で噛み合う様子が見えやすいと思います。
1案件を4フェーズに分けて入り口を割り当てる
最初にやるのは、作業を「性質の違うフェーズ」に割ることです。私は次の4分割を基本形にしています。
- 発散フェーズ — 何を作るか・何を調べるかを広げる。Antigravity 2.0 で複数の調査タスクを並行に投げる。
- 収束フェーズ — コードを実際に書いて整える。IDE で1行ずつ承認しながら固める。
- 運用フェーズ — サーバー上で動作を確かめる。CLI でヘッドレスに実行する。
- 自動化フェーズ — 繰り返す定型を自分のエージェントに委ねる。SDK で組む。
このフェーズ分けが効くのは、各サーフェスの強みと作業の要求がきれいに対応するからです。発散には同時実行、収束には目視レビュー、運用にはヘッドレス、自動化にはコード化。同じハーネスの上で動くので、フェーズをまたいでも前提を作り直す必要がほとんどありません。
発散と収束の橋渡しで気をつけること
2.0 で広げた調査結果を IDE での実装へ持ち込むとき、間に一手間を挟むと事故が減ります。私は「2.0 側で出た結論を、リポジトリの NOTES.md に短く書き出してから IDE を開く」という運用にしています。
これは、並行で走らせた複数タスクの結論が頭の中だけにあると、IDE フェーズで「さっきどっちに決めたか」を取りこぼすからです。実際、これを横着して何度かやり直しになりました。発散の成果物を一度テキストに落とすという地味な一手が、収束フェーズの手戻りをいちばん減らしてくれます。
SDK で最小のカスタムエージェントを動かす
自動化フェーズの中心が SDK です。公式の Antigravity SDK は Python ライブラリで、ローカルでエージェントを書き、同じ共有ハーネス上で動かせます。まずは「カレントディレクトリにどんなファイルがあるか」を尋ねるだけの最小構成から始めるのがお勧めです。
import asyncio
from google.antigravity import Agent, LocalAgentConfig
async def main():
config = LocalAgentConfig(
system_instructions="あなたはコードベース探索を支援する熟練アシスタントです。",
# api_key="your_api_key_here",
)
async with Agent(config) as agent:
response = await agent.chat("カレントディレクトリにあるファイルを教えてください")
print(await response.text())
if __name__ == "__main__":
asyncio.run(main())
ポイントは async with でエージェントのライフサイクルを囲んでいるところです。エージェントはバックグラウンドのセッションやファイルハンドルを抱えるため、コンテキストマネージャで包んでおくと、処理が終わった時点で確実に後始末されます。最初の1本はこの形を崩さないことをお勧めします。
自分の定型作業に寄せて育てる
最小構成が動いたら、system_instructions を自分の繰り返し作業に寄せていきます。私の場合は、記事に載せるコード例が実際に動くかを点検させるエージェントに育てました。考え方は、汎用の指示を具体的なチェック項目に置き換えることです。
INSTRUCTIONS = """\
あなたは技術ブログのコード例レビュアーです。次の手順で点検してください。
1. コードブロックを抽出し、言語を判定する
2. 構文として成立しているかを確認する
3. 明らかに動かない依存・未定義の変数を指摘する
4. 修正案を最小の差分で提示する
出力は日本語の箇条書きで、断定しすぎず根拠を添えてください。
"""
async def review_snippet(code: str) -> str:
config = LocalAgentConfig(system_instructions=INSTRUCTIONS)
async with Agent(config) as agent:
response = await agent.chat(f"次のコードを点検してください:\n\n{code}")
return await response.text()
この程度の薄いラッパーでも、毎回手で確認していた工程が一つ自動化されます。私はこれをブログの公開前チェックに組み込み、記事1本あたりの確認時間を体感で半分ほどに縮められました。大げさな自律エージェントを目指さず、自分が毎日やっている小さな手作業を1つだけ肩代わりさせる、という入り方が現実的です。
非同期エージェントを安全に止める
SDK で一番つまずきやすいのが、エージェントの停止まわりです。非同期で長く走るタスクを途中で止めるとき、後始末を怠るとセッションが宙づりになります。async with に加えて、明示的なキャンセルとタイムアウトを用意しておくと安心です。
async def review_with_timeout(code: str, timeout: float = 30.0) -> str:
try:
return await asyncio.wait_for(review_snippet(code), timeout=timeout)
except asyncio.TimeoutError:
return "点検がタイムアウトしました。コードを分割して再実行してください。"
except Exception as e:
return f"点検中にエラーが発生しました: {e}"
ここで asyncio.wait_for を噛ませておくと、応答が返らないまま処理が固まる事態を避けられます。本番のパイプラインに組み込むなら、この「必ず有限時間で返る」という保証は外せません。
本番デプロイで踏みやすい3つの落とし穴
ローカルで動いたエージェントをそのまま本番に載せるとき、私が実際にハマったのは次の3つでした。
第一に、API キーの扱いです。サンプルではコメントアウトされた api_key を、本番では環境変数から読むように必ず切り替えてください。コードに直書きしたまま push すると、シークレットスキャンに引っかかるうえに事故の元になります。私は環境変数経由を徹底し、リポジトリにはプレースホルダーしか置かないようにしています。
第二に、並行数の制御です。複数スニペットを一気に投げると、エージェントのセッションが同時に開きすぎてレート制限に当たります。asyncio.Semaphore で同時実行数を絞るのが現実的な回避策です。
第三に、失敗時のフォールバックです。エージェントの応答が空だったり壊れていたりする前提で、据え置きや再試行の経路を用意しておきます。私の運用では、点検がエラーで返ったら記事を止めて手動確認に回す、という安全側の分岐にしています。自動化は止まったときに被害を出さない設計まで含めて、ようやく本番品質だと考えています。
どこから組み始めるか
4つのサーフェスを一度に使いこなそうとすると、かえって手が止まります。お勧めの順序は、まず普段の作業を2.0 と IDE の往復で回し、サーバー確認が出てきたら CLI を足し、毎日繰り返す工程が見えてきたら SDK で1つだけ自動化する、という育て方です。
私自身、最初から壮大なエージェント基盤を組もうとして挫折し、結局「毎日やる小さな手作業を1つ消す」ところから積み上げ直しました。同じ共有ハーネスの上にいる強みは、この段階的な拡張がしやすいことにあります。今日の自分がいちばん面倒に感じている工程を1つ思い浮かべて、そこから組み始めてみてください。