今天繼續來看 Antigravity CLI 的另一個儲存核心 ~/.gemini/antigravity-cli/conversations/,看看底下的 SQLite 資料庫有什麼!昨天 transcript 裡面儲存的比較偏向是 Agent Harness 執行的 Log,在真正 Antigravity CLI 執行過程中不應該會被 Query 拿來顯示。而像是在 Antigravity CLI 裡透過 Slash Command 秀出的一些資訊,例如:/usage 或 /context 等,這種需要被 query 拿來呈現的資料,就會被存在 SQLite 裡。當然 Step 對話相關的資訊也會被存在 DB 內,但是具體被怎麼拿來用的還不確定。
conversations/<UUID>.db當你在終端機開啟新的 Antigravity 任務 Session 時,系統就會在 conversations/ 目錄下建立一個以 UUID 命名的 .db 檔案。如果我們用 ls 查看這個目錄,通常會看到類似這樣的檔案結構,這些是 SQLite 在開啟 WAL 模式 時會產生的檔案,簡單來說就是用 SQLite 存的:
~/.gemini/antigravity-cli/conversations/
├── c7b94e1d-8f23-4c91-9e8a-02d4f5a6b7c8.db # SQLite 主資料庫
├── c7b94e1d-8f23-4c91-9e8a-02d4f5a6b7c8.db-wal # WAL 預寫日誌 (Write-Ahead Log)
└── c7b94e1d-8f23-4c91-9e8a-02d4f5a6b7c8.db-shm # 共享記憶體索引 (Shared Memory)
我們可以直接用系統內建的 sqlite3 指令,進去看一下資料庫裡面有哪些資料表:
UUID="c7b94e1d-8f23-4c91-9e8a-02d4f5a6b7c8"
DB_PATH=~/.gemini/antigravity-cli/conversations/${UUID}.db
sqlite3 -readonly "$DB_PATH" ".tables"
指令執行後的輸出會像這樣:
battle_mode_infos gen_metadata steps trajectory_metadata_blob
executor_metadata parent_references trajectory_meta
可以看到裡面一共有 7 張資料表,大致可以分成周邊輔助與核心運作兩部分。
其中幾張屬於輔助的表:
trajectory_meta 與 trajectory_metadata_blob:記錄會話的身分識別、專案工作區路徑與 Git 分支等環境資訊。parent_references:若這個 Session 是 Subagent,用來記錄 Parent Session 的 UUID 與派生關係。battle_mode_infos:其實我不太確定這是什麼功能,Gemini 說是多模型對抗評測(A/B 盲測)時的對決紀錄。也許曾經或是未來要出?而真正儲存整場對話運作的核心資料,則是另外這三張表:
steps:記錄整個任務推進的事件狀態機(思考、工具呼叫與執行狀態)。gen_metadata:記錄每次模型調用時的相關數據(例如:我們最在意的 Token 使用量與快取用量)。executor_metadata:記錄執行器狀態與修改檔案前後的 Diff 快照(中斷時用來做檔案 Rollback)。剛才在目錄底下看到的 .db-wal 與 .db-shm,代表 Antigravity CLI 開啟了 SQLite 的 WAL 模式(Write-Ahead Logging),較新的 Step 會先以 Append 方式寫入 WAL 日誌檔(-wal),之後再寫回主資料庫,這樣可以讓 Antigravity CLI 不會因為資料庫讀寫而效能下降。
我們在試著探查資料時有一個需要注意的地方:當終端機背景正在跑 agy 任務時,如果你在另一個視窗下指令去查這顆 DB,最普通的預設連線可能會去爭奪或更新共享記憶體。萬一連線佔用 Lock,剛好碰到 agy 要寫入下一步驟,agy 就會直接噴出 database is locked (5) 當場 crash。
因此在終端機查看時,建議加上 -readonly 參數,強制以唯讀模式開啟:
# 加上 -readonly 以唯讀模式開啟,避免觸發鎖定干擾 Agent 運作
sqlite3 -readonly "$DB_PATH" ".tables"
加上 -readonly 參數後,SQLite 就只會進行純粹的唯讀操作,完全不搶寫入鎖,就能安全地一邊跑 Agent 一邊看資料了。
整個會話最關鍵的三張資料表與關聯如下:

我們可以用 .schema 指令看一下它們在 SQLite 裡的真實定義:
sqlite3 -readonly "$DB_PATH" ".schema gen_metadata"
sqlite3 -readonly "$DB_PATH" ".schema executor_metadata"
CREATE TABLE `gen_metadata` (`idx` integer,`data` blob,`size` integer NOT NULL DEFAULT 0,PRIMARY KEY (`idx`));
CREATE TABLE `executor_metadata` (`idx` integer,`data` blob,PRIMARY KEY (`idx`));
這幾張表的作用非常分明:
steps:
idx、步驟類型 step_type 以及執行狀態 status。gen_metadata:
idx(整數,Primary Key):對應模型調用(Generation)的步驟序號。data(BLOB,二進位):存放模型調用返回的核心遙測數據。size(整數):記錄二進位 payload 的位元組大小。executor_metadata:
這幾張表全部以 idx 串接對應,所以關係可能會是 1 對 1 或是 1 對 0。
在 gen_metadata 表裡,最引人注目的就是 data 這個 BLOB(Binary Large Object) 欄位。我是很好奇裡面到底存了什麼,所以我們下 SQL 把資料撈出來看看:
sqlite3 -readonly "$DB_PATH" "SELECT idx, hex(substr(data, 1, 40)), size FROM gen_metadata LIMIT 1;"
印出來的內容長這樣:

印出來的不是純文字或 JSON,而是一整串沒辦法讀的十六進位字串,底層其實是二進位資料(BLOB)。
仔細看這串十六進位位元組:開頭是 12 02 ...,後面接 22 24 63 37 62 39 ...。以下是 Gemini 的說法:「有接觸過 Google 技術棧的人應該不陌生,這正是標準的 Protocol Buffers(Protobuf)Wire Format(例如 22 代表 Field Tag 4,24 代表長度 36 bytes,後面的 ASCII 字元解出來剛好就是剛才看到的 Session UUID c7b94e1d-8f23-4c91-9e8a-02d4f5a6b7c8)」。我是沒有這麼快看出來啦,畢竟我平常不會沒事把轉換後的二進位資料拿出來觀賞,但是我是很快就被說服了哈哈(截圖是我本機實測的另一組 UUID,但拆解出來的欄位結構一模一樣)。
Antigravity CLI 在記錄這些底層調用資料時,為了空間與寫入效能,直接把記憶體中的 Protobuf 二進位序列化存進了 SQLite。但問題來了:Google 官方並沒有釋出這段資料的 .proto 定義檔啊! 沒有 proto 定義,我們就無法知道每個 Tag 具體代表什麼欄位與內容啊!
哇?怎麼辦呢?