ochakai

育てて、回す

エージェントが下書きし、人が確かめ、その後どうなったかを測ります。「最初のひと月」で書いたものを、誰も見ていないところで古びさせないための一周です。

内容は v0.27.5 時点のものです。元にしているのは製品リポジトリの改善ループCLI リファレンスgolden query のカナリアで、細かい分岐はそれぞれの原文にあります。

0. status と trust は別の軸

ochakai のドキュメントは、独立した 2 つの軸を持ちます。片方を動かしても、もう片方は動きません。

何を言うか動かすコマンド
statusdraft / stable / deprecatedこのドキュメントは使ってよい状態か。公開の段階ochakai put
trustunverified / machine-confirmed / human-reviewedこの中身を人が確かめたか。来歴の側ochakai verify

ochakai verify はドキュメントを編集しません。status と ETag は動かないままです。逆に ochakai put は本文を書き換えるので status を動かせますが、それ自体は誰かが確かめたことを意味しません。

検索の一覧に出る stable は status で、ドキュメントを取ったときに linked from の行に出る unverified は trust です。draft のまま human-reviewed になることもあれば、stable のまま unverified で居ることもあります。

ochakai list usage --status draft              # 公開の段階で絞る
ochakai search "売上" --trust human-reviewed   # 誰が確かめたかで絞る

draftstable に上げるのは ochakai put です。本文を取り出して frontmatter の status: を書き換え、書き戻します(§2)。

1. 4 つのプロンプトで一周する

エージェントを繋いだら、4 つのプロンプトで全体を歩けます。フックを入れてあるなら、1 つ目と 2 つ目は自動で起きます。

思い出す。知識ベースが答えられることを訊いて、エージェントが推測で答えずに ochakai を見にいくかを確かめます。

売上について既に分かっていることは? 答える前に ochakai を見て。

検索が順位を返し、エージェントは自分で定義を作らずにあなたの定義から始めます。

書き戻す。残す価値のあることを伝えます。

部門別の売上は products.department で割れるが、値は Men と Women の 2 つしか無い。3 つ目を期待した集計は嘘をつく。次のセッションが使えるよう ochakai に保存して。

draft として入り、書いたエージェントの名で来歴が残ります。まだ信頼されておらず、検索もそう言います。

確かめる。ochakai ui を開いてレビューキューでそれを見つけ、「検証」を押します。あるいは理由を付けて「却下」します。

ここだけは、どのエージェントも代わりにやってくれません。import も同じで、取り込んだバンドルの verified: は文書の主張のまま置かれます。デモを入れた直後なら、ochakai verify metrics/revenue が最初の一手です。

ループを閉じる。知識が間違っていたと分かったら、そう言います。

あの golden query の数字が月次決算の確定値と合わない。理由を付けて failed として ochakai に報告して。

report_outcome は、そのドキュメントを再検証のフィードに移します。次のエージェントは、それを検証済みとしては受け取りません。もう一度確かめればフィードから消えます。

最初のプロンプトで何も返ってこないなら、エージェントは実は繋がっていません。ochakai whoami がどのサーバーに誰として話しているかを言います。

2. 確かめる、却下する、公開する

コマンドは 3 つです。web UI の「検証」「却下」ボタンも、同じものを台帳に記録します。v0.27.5 から「検証」ボタンだけは、記録に加えて draft を stable へ上げるため、レビュー待ちの列がそれで減ります。

ochakai verify metrics/revenue
# 確かめた。台帳に自分と時刻が追記される。status も ETag も動かない

ochakai reject metrics/bad-revenue --note "返金を二重に数えている"
# 却下。理由が残り、次のエージェントがそれを読む

ochakai get metrics/revenue > c.md
# c.md の frontmatter の status: を stable に書き換えてから
ochakai put metrics/revenue -f c.md

verify は追記です。最初の確認と 10 回目の再確認は同じコマンドで、再確認こそがドキュメントを 2 つのフィードから外します(§4)。却下されたドキュメントを verify すると、却下が取り消されます。

reject は理由を残します。次のエージェントが同じ提案をする前に読むのが、これです。却下されたドキュメントは検索から隠れ、ochakai search --rejected で明示的に訊いたときだけ返ります。却下そのものの取り消しは ochakai reject <id> --withdraw です。エージェントが同じ提案を繰り返さないのは、この記録が残っているからです。

put は編集です。変更はすべてリビジョンとして残ります。他人の編集を踏まないようにするなら --if-match を添えます。読んだときの版のままなら書き込み、そうでなければ上書きせずに失敗します。新規作成を確実にしたいときは --only-if-new です。

人が担う半分は web UI にあります

ochakai ui   # http://127.0.0.1:8098、あなた自身として

デプロイは要りません。ループバックであなた自身として出るため、編集は human:<あなた> として記録されます。status で絞って検索し、知識をフォルダツリーとして辿り、リンクと利用回数を添えてドキュメントを読み、その場で検証・却下・deprecate ができます。ビルドステップの無い一枚のページで、グラフも、クエリ実行も、チャットも持ちません。

チームで共有するなら、同じコンテナイメージを serve-ui として立てます。Terraform の enable_webui がそれで、「立てて、運用する」§1 のオプション表にあります。

3. レビューの順番

ochakai list usage --status draft    # 直近 90 日で実際に読まれた順

初日はここが全部 0 です。この一覧が意味を持つのは二周目からで、そのとき上位に来る十件が、チームが実際に使っている十件です。よく読まれていて、まだ誰も確かめていないものから確かめます。

並ぶ窓が直近なのは意図的で、「昔たくさん読まれた」ではなく「いま読まれている」が上に来ます。

検証済みの割合を目標にしないでください。取り込んだドキュメントの大半が draft のまま残るのは正常です。下に未検証が何千件あっても、検索では確かめたものが上に来るため、代償は小さく済みます。

4. 3 つのフィードと、その終わらせ方

確かめ直すべきドキュメントを人の前に置くフィードが 2 つあります。どちらも、もう一度確かめることで答えます。

空になるのは再検証の側だけです。こちらは未応答の失敗報告を持つドキュメントだけを保持するため、人が終わらせられます。検証の古さのフィードは全件を並べ替えるだけで、ゼロにはなりません。

3 つ目の stale(stale_after)は、書き手自身が宣言した期限を過ぎたドキュメントを並べます。ドキュメントを編集して期限を宣言し直せば片づきます。その日付はサーバーが観測したものではなく、書き手が立てた主張です。

ochakai list failed --trust human-reviewed   # 再検証
ochakai list verified_at                     # 検証の古さ
ochakai list stale_after                     # 期限切れ

ochakai stats                # 3 つが何を抱えているか、1 回で
ochakai stats --exit-code    # cron 用: 未処理が残っている間は 2 で終了する

web UI では「レビュー」タブのバッジが同じことを示します。静かなキューと空のキューを、これで見分けられます。週に一度これを見るのが、運用としての最小です。

5. 何が測られているか

ドキュメントごとの利用回数は、その知識が使われているかを示します。

ochakai usage metrics/revenue

検索で返された回数、取得された回数、worked と failed の報告数、最後に使われたのがいつかを返します。長いあいだ誰も使っていない検証済みドキュメントは、カナリアの優先度を下げるか deprecated を検討する理由になります。失敗が積み上がったものは、先に確かめ直す理由です。

ochakai stats は知識ベース全体を返します。空振りに終わった検索もそこに含まれ、訊かれた回数の多い順に並びます。

v0.27.0 からは、ディレクトリの付与だけを持つ利用者も自分の数を読めます。答えは scope で何を数えたかを言い、範囲を絞った相手には、何も返さなかった検索を伏せます。どこにも当たらなかった検索には、絞るための id がありません。web UI のレビュー画面には期間とパスのつまみが付き、数字は「この知識ベースが何であるか」と「その期間に何が起きたか」の二段に分かれます。

vectorstruncated は対で読みます。埋め込みモデルの入力窓に収まらないドキュメントは前半だけが載り、後半に書かれたことでは引けません。それでもベクトルは在り、順位に乗り、結果として返るため、数を見るまで区別が付きません。vectors の大半が truncated なら窓の広いモデルへ移る話であり、数件だけなら長すぎるドキュメントを分ける話です。

6. golden query をカナリアとして走らせる

検証済みの golden query は静かに壊れます。データウェアハウスがカラム名を変え、裏側のデータの形が変わっても、知識ベースは気づきません。エージェントが躓くのを待たずに、CI から定期実行して結果を書き戻します。

ochakai は SQL を実行しません。カナリアはあなたの側、つまり CI ジョブやスケジュール実行されるエージェントで走り、データウェアハウスの認証情報もそちら側に留まります。ochakai が渡すのは材料で、見つかったことを記録するだけです。

golden query は Attested Computation です。runtime がどのデータウェアハウスで動くかを言い、# Computation の本文フェンスが SQL 本体を持ちます。

1. 一覧する

ochakai list verified_at --type 'Attested Computation' --trust human-reviewed --limit 100

最後に確かめてから最も間が空いたもの順です。「90 日間確かめ直していない検証済みクエリ」がカナリア実行の出発点になります。取り込んだばかりの知識ベースでこれが空なら、まだ誰も確かめていないだけです。--trust human-reviewed が答えるのは import ではなく ochakai verify です。

一覧が返すのは名前だけで、ドキュメントそのものは渡しません。これから実行する分だけ ochakai get <id> で取ります。

2. 実行する

各ドキュメントの # Computation フェンスを、自分の認証情報でデータウェアハウスに対して実行します。どのデータウェアハウスかは runtime を読んで判断します。

3. 判定する

結果判定
実行エラー(テーブルやカラムが無くなっている)失敗。スキーマ変更でクエリが壊れた
行数やヘッドライン集計が閾値を超えて動いた警告。データが変わったか、定義がずれた
正常確かめ直したものとして記録する

4. 書き戻す

ochakai verify queries/monthly-revenue
# クリーンに走った。台帳に追記され、検証の古さのフィードの末尾に移る

ochakai report queries/monthly-revenue worked
ochakai report queries/monthly-revenue failed --note "スキーマ変更で dry-run が通らない"
# worked と failed の合計は usage に出る

失敗または警告のときは、影響を受けたドキュメントに対して draftInsight を作るか、理由を書いて status: deprecated を提案します。人が来歴を見て判断します。誤りだと確定したら ochakai reject です。

verify を呼んでよいのは、実際にクエリを実行して結果を比較したときです。--dry_run が確かめるのは、クエリがまだコンパイルできることだけです。dry-run で済ませるなら、verify は落として失敗だけを書き戻してください。

CI のスニペット(GitHub Actions + BigQuery)

--dry_run はスキーマ変更による破損を無償で捕まえる。結果のドリフトまで見るなら、クエリを実行して前回と比較する。行数といくつかのヘッドライン集計を artifact として保存し、それを diff するのが簡単なやり方。

name: golden-query-canary
on:
  schedule:
    - cron: "0 21 * * 1" # 月曜 06:00 JST
jobs:
  canary:
    runs-on: ubuntu-latest
    permissions:
      id-token: write # Workload Identity Federation(鍵レス)
    steps:
      - uses: google-github-actions/auth@v3
        with:
          workload_identity_provider: ${{ vars.WIF_PROVIDER }}
          service_account: ${{ vars.CANARY_SA }}
      - name: run canaries
        run: |
          TOKEN=$(gcloud auth print-identity-token --audiences="$OCHAKAI_URL")
          curl -s -H "Authorization: Bearer $TOKEN" \
            "$OCHAKAI_URL/api/v1/search?type=Attested%20Computation&trust=human-reviewed&sort=verified_at&limit=50" \
          | jq -r '.hits[].id' | while read -r id; do
              doc=$(curl -s -H "Authorization: Bearer $TOKEN" \
                -H 'Accept: text/markdown' "$OCHAKAI_URL/api/v1/bundle/$id.md")
              sql=$(printf '%s' "$doc" | sed -n '/^```sql$/,/^```$/p' | sed '1d;$d')
              if ! bq query --nouse_legacy_sql --dry_run "$sql" >/dev/null 2>&1; then
                echo "::error::computation $id no longer compiles against the warehouse"
                curl -s -X POST -H "Authorization: Bearer $TOKEN" \
                  -H 'Content-Type: application/json' \
                  -d '{"outcome":"failed","note":"canary: dry-run failed"}' \
                  "$OCHAKAI_URL/api/v1/usage/$id" >/dev/null
              else
                curl -s -X POST -H "Authorization: Bearer $TOKEN" \
                  -H 'Content-Type: application/json' \
                  -d '{"ruling":"verified"}' \
                  "$OCHAKAI_URL/api/v1/review/$id" >/dev/null
              fi
            done

ここで一周です

あとは §1 の 4 つのプロンプトを、自分のテーブルに対して繰り返します。この先に別の段階はありません。