
實測:2026-11-14 22:07(Asia/Taipei, UTC+8),
gemini-api 0.4.6;原碼快照2030ff1。初始 Stage 3 只做離線 discovery、validation 與 dry-run;最終整合另執行 auth status 診斷與隔離 shim 測試,未啟動 Antigravity SDK eval、雲端 Agent 或媒體生成,也沒有消耗模型 quota。完整逐字輸出見 Stage 3 實驗紀錄(experiments/05-part3-agy-integration/results.md)。
📚 系列導覽
Part 1(Substack):https://memo.jimmyliao.net/p/gemini-api-cli-part-1-agent-api
Part 2(Substack):https://memo.jimmyliao.net/p/gemini-api-cli-part-2keyless-adcscope
Part 1(Dev.to,English):https://dev.to/jimmyliao/gemini-api-cli-official-guide-part-1-giving-your-ai-agent-a-stateless-multimodal-cli-toolbox-36p3
Part 1 YouTube 16:9 導讀:https://youtu.be/Rb5ij419w2Y
Part 1 YouTube Shorts:https://youtube.com/shorts/82-Z_Jq-ezQ
1. 問題與破題:當 agy 接棒 Gemini CLI,誰負責「程式化與多模態長尾」?
「既然我在用 agy,為何還要在 agy 裡呼叫 gemini-api CLI?」關鍵在工作介面的分工:宿主 Agent 理解需求、讀 repo、改程式與持續推理;API CLI 則把特定模型能力轉成可發現、可預演、可解析的 shell 操作。例如生成媒體、輸出轉錄 artifact,或在 CI 精確建立一個 API request。
2026-06-18 的 consumer 遷移有明確範圍:免費 Code Assist individuals 及 Google AI Pro/Ultra 的 Gemini CLI/IDE extension requests 移往 Antigravity;Standard/Enterprise 組織授權及 paid API key 路徑有不同安排。因此「consumer gemini 退場」不等於所有 Gemini CLI 使用方式停止。Google 官方遷移公告
本系列採用 Golden Hybrid Pattern:日常 coding 與 reasoning 使用 agy 原生池;需要明確 API 能力或指定 GCP project 時才呼叫 gemini-api。Google AI Pro/Ultra 的訂閱池與 GCP API project 池分開;Pro/Ultra 的五小時刷新仍受 weekly limits 約束,不能把 ADC 登入視為將訂閱額度轉入 API。Antigravity Plans 與本專案 tier 研究(experiments/04-tier-limits-and-errors/tier-research.md)分別說明訂閱與 API 邊界。
這是建議的資源分工,並不宣稱 agy 缺乏所有多模態能力。選 CLI 的理由是需要可重現的 API 呼叫契約;模型產生的內容仍可能不同。
2. 官方原碼鐵證:Antigravity SDK 正是 gemini-api 的親生 CI 測試宿主
這個組合有直接的 repository 證據。evals/harness-comparison/README.md 第 11–25 行描述:每次建立 mock Interactions API server,以 Antigravity SDK 啟動 Agent,讓它只靠 shell 發現 CLI 用法;mock server 檢查 method、path 與 body predicate。評估的是「是否送出正確 request」及用了幾次 Bash/assistant turn,而不是比較模型生成文案。
driver/antigravity_driver.py 第 26–31 行 import Agent、BuiltinTools、CapabilitiesConfig、LocalAgentConfig;第 58–59 行明列:
enabled_tools=[BuiltinTools.RUN_COMMAND, BuiltinTools.FINISH],
enable_subagents=False,README 所說「run_command as the only tool」指唯一的操作工具;driver 另外允許完成用的 FINISH。它清除繼承的 GEMINI_/GOOGLE_ overrides,再把 driver 模型 endpoint 明確固定到真實服務,避免被 CLI 的 mock endpoint 污染。CLI 打 mock 不代表整個 eval 免費:README 第 55–58 行明說 SDK driver 使用另外提供的真實 API credential,Agent session 會花模型 tokens;本次沒有執行它。
src/harnesses.ts 將 generated harness 的 gemini-api 導向 --server-url,reference harness 則用 GOOGLE_GEMINI_BASE_URL。共同 system prompt 要求自行 --help discovery、避免互動/TUI、命令自行結束。README 第 70–78 行記載 PR workflow 與 pinned eval model;這是 repository CI 設計證據,不是本次成功跑過 CI 的宣告。
Agent 自發現的機器介面
本次每條 CLI 實驗都使用以下前綴,並附 </dev/null:
env -u GEMINI_API_KEY -u GEMINI_ACCESS_TOKEN -u GEMINI_ENVIRONMENT_KEY -u GEMINI_USER_PROJECT GEMINI_NO_KEYRING=true gemini-api --agent-mode generate "hi" --dry-run </dev/null實際 stdout(exit code 0):
{"dry_run":true,"request":{"method":"POST","url":"https://generativelanguage.googleapis.com/v1beta/interactions","headers":{"Accept":["text/event-stream"],"Content-Type":["application/json"],"User-Agent":["google-genai-cli/0.4.6 gl-go/go1.26.10"]},"body":{"input":"hi","model":"gemini-3.8-flash","stream":true}}}預演建立了 request,沒有向該 URL 送出 HTTP。--agent-mode -o json 與 --agent-mode -o toon 的同一測試都得到相同 JSON envelope,不能假定 TOON 設定會把 dry-run 也變成 TOON。

internal/output/agentmode.go 的實際符號是小寫 shouldRenderStructuredError,不是 exported ShouldRenderStructuredError。第 53–58 行在 agent mode、JSON、非空 jq expression 或 TOON 時選擇結構化錯誤。PreparseRenderingFlags 則處理 Cobra 在遇到未知 flag/command 之前可能尚未解析輸出旗標的情形。因此機器介面也涵蓋「命令拼錯了」的情況。
本機缺 prompt 的 stderr 包含 error_reason: CLI_VALIDATION、error_type: validation_error、exit_code: 2 與修復 hints;呼叫端應分開讀 stdout、stderr 與 process exit code。CLI contract 為 0 成功、1 runtime/API、2 usage/validation、3 authentication/authorization。本 Stage 實測了 0 與 2;1/3 的分類來自原碼及既有文件,不冒稱這次測過所有失敗分支。
--schema 用來發現 request body,並不是約束模型回應的萬用開關;結構化生成須再查 response format 的 schema。--jq 可精簡真實回應,但 Part 1 已驗證 dry-run 不套用 jq。串流 JSON 也可能是 NDJSON,解析器須配合回應形狀。
3. 雙向互調全景圖

Pattern A:Local-to-API
agy 透過 Skill 呼叫 bin/gapi-adc,wrapper 取得 ADC 短效 OAuth token,再以 --user-project 明確歸屬 API project。專項能力可以是 image、video、tts、music、transcribe,或 files 上傳後交 analyze;Google Search grounding 與結構化回應則按當前 schema 組裝。
這條路免 API key,但沒有免除 credentials 管理、IAM、scope 或 API 計費。尤其不能說「我有 Pro,所以這個 API image 免費」。Free/Paid eligibility 取決於 API 模型、功能與 project,不由宿主訂閱推導。
Pattern B:API-to-Cloud/Sandbox
反過來,CLI 也能建立雲端 Agent request。本次實際執行的安全預演為下列命令;執行時同樣加上前述 scrub env 前綴:
gemini-api agent run hi --agent antigravity-preview-09-2026 --dry-run </dev/nullExit 0,只在 stderr 印出預演;request body 的 agent 是 antigravity-preview-09-2026,input 是 hi,stream 是 true。這證明 binary 接受並序列化該名稱,不證明 project 有遠端資格。
AntigravityAgentConfig 提供 type:"antigravity"、model、max_total_tokens,描述 server-side runtime 設定。本機 agy session、SDK eval Agent 與 API Managed Agent 是三種不同執行位置,不能因名稱相同而假定 credentials 共用。
docs/self-hosted/README.md 再把服務端推理接到自有 compute:environments connect 使用 scoped environment key;分離模式由可信 control plane 跑 environments poll,sandbox 以短效 interaction lease token 跑 environments serve。七個 built-in tools 是 execute_bash、view_file、write_to_file、replace_file_content、list_dir、grep_search、find_by_name。
檔案工具受 --root-dir 約束,execute_bash 則需要真正的 OS/container/VM isolation,不能把檔案 root 視為 shell sandbox。Agent Substrate 文件 以 ate-gemini 串起 Kubernetes controller、provision hook 與 actor daemon;worker 不持有 project API key。其明確限制是:mTLS 驗證元件身份,不代替應用對終端使用者的 authentication/ACL。本篇未部署這條路,也沒有啟動長駐 worker。
4. 實戰踩坑:為什麼官方 shim 必加 </dev/null?
setup.sh:20–31 的註解指出 Antigravity command runner 即使沒有輸入,仍會給子程序一條開啟中的 stdin pipe。若 CLI 探測或讀取 stdin 並等待 EOF,Agent 呼叫可能一直不結束。
官方 shim 的核心原文如下;變數與 escape 保持 shell 生成 shim 的原始形式:
for arg in "\$@"; do
if [[ "\$arg" == "@-" || "\$arg" == *=@- ]]; then
exec "$here/bin/generated/gemini-api-real" "\$@"
fi
done
exec "$here/bin/generated/gemini-api-real" "\$@" </dev/null它只在明確指定 @-/*=@- 時保留 caller stdin。不能把它寫成上游已檢查 --stdin:本機 generate --help 確實有 --stdin,所以我們的 wrapper 與 Skill 額外規定,刻意使用該選項並提供輸入時也保留 stdin。
最終整合已在 bin/gapi-adc 內建單一 exec_binary(),offline(含 dry-run)與 online exec 都經此 helper:預設 exec "$binary" "$@" </dev/null;任一參數符合 @-、*=@- 或 --stdin 則保留 caller stdin。離線實際 CLI 已驗證 body 與 prompt 輸入;隔離 shim 也實測一般輸入截斷、三種模式保留,線上分支以假 gcloud/CLI 隔離驗證,未送模型請求;逐字結果見實驗紀錄末尾。
直接在 run_command 呼叫 wrapper 以外的 gemini-api,仍需明確加 </dev/null,刻意讀取 stdin 時例外。真人執行 --reauth 是互動登入流程,不經此 helper,保持原流程。
5. 動手封裝 gemini-api-adc Antigravity Skill
本次產物是 skills/gemini-api-adc/SKILL.md。它使用已在本機 ~/.agents/skills/transcribe-audio/SKILL.md 觀察到的 YAML name/description frontmatter。這次只建立 repo 中的 Skill,未安裝至使用者目錄,也未驗證 agy 自動 discovery/載入。
觸發描述讓 Agent 知道何時需要 API;內文則固定四道決策:
觸發邊界:一般 coding 留在原生池,只有專項 API artifact 或明確 API 測試進入 wrapper。
Auth pre-flight:執行
./bin/gapi-adc --print-auth-status </dev/null;看到必要 scopeMISSING時,請使用者執行./bin/gapi-adc --reauth。此診斷本身會 refresh token/查 tokeninfo,不能列為離線 discovery;exit 0 也可能表示診斷完成但 scope 缺失。Dry-run gate:付費/mutating 操作先看 request,確認模型、project、輸入資料與 artifact 路徑。預演不保證服務端接受。
Tier-aware routing:明確指定
--user-project,不靠未知的 fallback 決定帳單或資料條款。
依 Part 2 project audit(experiments/03-part2-keyless-adc/results.md),候選路由如下:

gdg-kc-465418 與 GDE_Redeem 對應不同 audited billing accounts,不能合稱同一 credits 池。billingEnabled 也不直接證明 Paid Tier 等級、有效餘額或成功付款資格。GDE_Redeem 等已開啟 billing 的 project,仍須先 auth check 與 dry-run,另確認 credits 條款;本篇沒有執行真實扣款測試。
離線驗證 Skill 範例可以清除 credential env、關閉 Keyring,再透過 wrapper 預演;線上則由 wrapper 取得短效 token,不能把本篇測試用的「清除 token」當作直接 CLI 的認證方式。Skill 也明列 wrapper 額外可能回 127,避免把所有失敗硬塞進 CLI 的 0/1/2/3 契約。
5.5 實戰情境貫穿(Part 3 視角):讓 agy 擔任 AI Reels 導演,透過 Skill 調度分鏡生圖與轉片
agy 作為 Creative Director 與 Shell Operator,在 Pro/Ultra 原生池撰寫 storyboard.json 與 dialogue.txt,再執行 ./examples/reels-storyboard-pipeline/run-reels-pipeline.sh --dry-run。這是可採用的流程,此次未啟動 agy;實際八次離線測試見 examples/reels-storyboard-pipeline/dry-run-trace.md,腳本見 examples/reels-storyboard-pipeline/run-reels-pipeline.sh。
bin/gapi-adc 的 exec_binary() 在 Step 1 偵測 --stdin,保留簡報輸入;Steps 2–6 無此旗標,注入 </dev/null 防止 Antigravity 開啟中的 stdin pipe 阻塞。所有 fixtures/* 都是本機合成測試輸入,非模型生成媒體;16×28 PNG 僅測 MIME,不是 9:16 構圖驗收。
Dry-run 審閱與付費授權完成後,才可考慮 --live -p gdg-kc-465418 或 --live -p gde-jimmyliao-redeem。live 先呼叫 --print-auth-status,只接受精確必要 scope 的 PRESENT;MISSING 或未確認即退出 3,提示真人處理 --reauth,不自動開 OAuth。首幀還須人工核准才轉片。本次未跑 live/status 網路診斷;scope gate 也不保證 IAM/credits/模型可用。

此範例示範兩張首幀與第一鏡影片;三鏡合成、精確 15 秒、字幕混音及最終影片 QA 仍須後製,不將 request 成功當成成片驗收。
Part 3 可執行範例程式碼
本機執行檔:examples/part3-agy-skill-director/sample-part3-agent-harness-demo.sh。以下在本專案根目錄整段貼入執行;不需要 clone 公開 OSS repo,本次沒有建立公開 OSS repo。需要 bash、python3 與已安裝的 gemini-api 0.4.6;程式碼與本機腳本使用相同指令,只把腳本定位改為根目錄相對路徑。
實測修正:缺 --out 並非本機 validation error;不能用 image "Missing out flag" 當離線測試。以下改用缺 prompt 且明確 --dry-run 的測試,實測 Exit 2。stderr 的 error 是字串,並沒有 error.type/error.code/error.message;應解析頂層欄位。有限 pipe 測試證明輸入隔離,並非未關閉 pipe 的逾時測試。
bash <<'PART_SAMPLE'
(
set +x
set -euo pipefail
cd examples/part3-agy-skill-director
unset GEMINI_API_KEY GEMINI_ACCESS_TOKEN GEMINI_ENVIRONMENT_KEY GEMINI_USER_PROJECT
export GEMINI_NO_KEYRING=true
W=../../bin/gapi-adc
R=../reels-storyboard-pipeline
echo '步驟:一般 stdin pipe 雜訊應被隔離' >&2
printf 'UNEXPECTED_PIPE_NOISE\n' | "$W" --agent-mode generate 'Reels hook check' --dry-run |
python3 -c 'import json,sys; d=json.load(sys.stdin); assert "UNEXPECTED_PIPE_NOISE" not in d["request"]["body"]["input"]; print("一般 stdin guard:通過")'
echo '步驟:明確 --stdin 保留簡報' >&2
cat "$R/storyboard-brief.txt" | "$W" --agent-mode generate --stream=false --stdin '依簡報產出三鏡分鏡:' --dry-run |
python3 -c 'import json,sys,pathlib; d=json.load(sys.stdin); brief=pathlib.Path(sys.argv[1]).read_text().strip(); texts=[c.get("text", "") for item in d["request"]["body"]["input"] for c in item["content"]]; assert brief in texts; print("明確 --stdin:通過")' "$R/storyboard-brief.txt"
echo '步驟:缺 prompt 的離線 validation(缺 --out 不會觸發此錯誤)' >&2
ERR=$(mktemp)
trap 'rm -f "$ERR"' EXIT
set +e
"$W" --agent-mode image --dry-run </dev/null 2> "$ERR"
rc=$?
set -e
[ "$rc" -eq 2 ]
cat "$ERR" >&2
python3 -c 'import json,sys; d=json.load(open(sys.argv[1])); assert d["exit_code"] == 2; assert d["error_type"] == "validation_error"; print("觀察 Exit:2"); print("error_type="+d["error_type"]); print("error_reason="+d["error_reason"]); print("message="+d["message"]); print("error 是字串,沒有 error.type/error.code/error.message 欄位")' "$ERR"
)
PART_SAMPLE6. 三部曲總結與最佳實踐 Checklist
Part 1:Gemini API CLI 官方指南 建立多模態命令與 machine interface;Part 2:Keyless ADC 與 user tiers 處理 OAuth、project attribution 與 tier 邊界;Part 3 把這些契約封裝成宿主 Agent 可以遵循的 Skill。
☐ 日常 coding 使用宿主原生池,專項需求才選 API。
☐ 固定並記錄 binary 版本,先讀
--usage、子命令 help 與支援的 schema。☐ 分開確認身份、scope、project、資料許可、API enablement 與 billing/credits。
☐ wrapper exec 使用內建 stdin guard;直接 CLI 呼叫附
</dev/null,明確 stdin 輸入與真人登入例外處理。☐ 付費/mutation 先預演;預演通過不等於遠端 entitlement 通過。
☐ 分開解析 stdout、stderr、exit code 與 HTTP status;錯誤不自動換池。
☐ 不記錄 raw credentials;部署 sandbox 時另外處理 shell isolation 與使用者 ACL。
讀者可以先重現完全離線的 Stage 3 實驗,再在已授權的 project 做最小線上測試。這樣每一次從 agy 到 API 的跨界,都有清楚的能力、資料與費用歸屬。
7. Live 實測補錄:m1:0.1 實機串接 Part 1–3 實測與成本帳本(2026-11-15)
於 2026-11-15 00:20:54 → 00:24:23 Asia/Taipei (UTC+8) 在獨立 tmux 終端(m1:0.1)實機執行 experiments/06-live-execution-and-cost-log/run-tmux-step-by-step.sh(搭配 run-reels-pipeline.sh --dry-run 與 sample-part3-agent-harness-demo.sh):
實際串接證據:Part 1 全 8 步 live 生成、
ffmpeg 8.1封裝出可播放examples/reels-storyboard-pipeline/output/final-reel.mp4(9.44s、720x1280)、Part 2gapi-adc(Exit 3預期 403 / routerExit 0) 與 Part 3 stdin/EOF 護欄(Exit 0)均完整記錄於experiments/06-live-execution-and-cost-log/cost-and-call-ledger.md與experiments/06-live-execution-and-cost-log/calls-ledger.jsonl。Agent 實作 Schema 教訓:實測確認
gemini-api generate -o json文字位於steps[].content[].text(非outputs[]),analyze -o json則位於頂層text,且image/video/music必須再透過只讀的gemini-api agent status <response_id>($0)才取得到完整usagetoken 統計;run-tmux-step-by-step.sh已修正此解析並留下回歸證據。


