最初のひと月
ochakai を立てた直後の知識ベースは空です。そこからエージェントが検索で知識を見つけ、その知識が育ちはじめるまでの手順です。
内容は v0.27.5 時点のものです。元にしているのは製品リポジトリのこの記事の原文で、細かい分岐は原文にあります。
0. 準備: 範囲を決めて、問いを書き出す
範囲は小さく始めます。初日はデータセット 2 つ、テーブル 5〜10 個で十分です。未検証の draft が数千件あるキューは、じきに誰も開かなくなります。3 つ目のデータセットは来週足せば間に合います。
次に、チームが実際に訊いている問いを 10〜20 個書き出します。
「先月の売上はいくらだったか」 「リピート購入率は先月から動いたか」 「チャネル別の内訳は」 …
この一覧は後で 2 回使います。§2 で何から書くかを決め、§3 で検索が効いているかを判定します。思いつかないときは、データウェアハウスのジョブ履歴で何度も実行されているクエリや、社内チャットで繰り返し訊かれている質問を見てください。問いを先に書くのは、後回しにすると、自分が書いた知識で答えられる問いばかりを選んでしまうからです。
1. テーブルの一覧を取り込む
スキーマは自分で取得して、その結果を ochakai に渡します。ochakai がデータウェアハウスに接続することはありません。
bq query --max_rows=100000 --format=json --nouse_legacy_sql \
'SELECT table_schema, table_name, column_name, data_type, is_nullable, description
FROM `your-project.your_dataset.INFORMATION_SCHEMA.COLUMNS`
ORDER BY ordinal_position' \
| ochakai seed --project your-project - | ochakai import -
--max_rows は省けません。bq query が既定で表示するのは先頭 100 行だけで、打ち切ったことは表示されません。カラムが合計 100 本を超えるデータセットでは、エラーや警告が出ないまま、一部のテーブルしか入りません。seed が最後に出す「seeded N tables」の N を自分のテーブル数と突き合わせれば、その場で分かります。
取り込んだドキュメントは、すべて draft で入ります。手元にできるのは、誰も説明を書いていないテーブルとカラムの一覧です。
id の prefix は、この日に決めるものの中で唯一、後から変えると手間の大きい設定です。--prefix を後で変更しても既存のドキュメントの名前は変わりません。2 つ目のカタログができるだけで、古いほうは誰にも読まれないまま残ります。毎日の同期のしかたと id の付け方は examples/bigquery-catalog にあります。
BigQuery 以外のデータウェアハウスから取り込む
ochakai seed は、INFORMATION_SCHEMA.COLUMNS の列名を持つ JSON を読む。要るのは table_schema・table_name・column_name・data_type・is_nullable の 5 つで、注記があれば description も読む。知らないキーは無視されるため SELECT * でも動く。形式は JSON の配列でも、一行に一オブジェクトでもよい。
この 5 つは ANSI の綴りであり、Snowflake でも Redshift でも Databricks でも同じ SELECT が通る。BigQuery の綴りなのは description だけで、Snowflake なら comment がそれにあたる。
SELECT table_schema, table_name, column_name, data_type, is_nullable,
comment AS description -- Snowflake。無い所ではこの行を落とす
FROM your_db.INFORMATION_SCHEMA.COLUMNS
WHERE table_schema NOT IN ('INFORMATION_SCHEMA')
ORDER BY table_schema, table_name, ordinal_position
あとはクライアントに JSON で出させて、そのまま渡す。PostgreSQL と、その系統のデータウェアハウスなら:
psql -At -d your_db -c "
SELECT json_agg(t) FROM (
SELECT table_schema, table_name, column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_schema NOT IN ('pg_catalog','information_schema')
ORDER BY table_schema, table_name, ordinal_position
) t" \
| ochakai seed - | ochakai import -
BigQuery 以外では --prefix だけを使い、--project は付けない。--project が書き込む resource は bigquery:// で始まる住所。他のデータウェアハウスでは誤った住所になる。付けなければキーごと省かれる。間違った住所を名乗るドキュメントは、住所を名乗らないドキュメントより悪い。
取り込まれるドキュメントの型は、どのデータウェアハウスでも BigQuery Table になる。これは OKF の語彙の綴りであって、ochakai がデータウェアハウスを見分けているわけではない。型の集合は開いているため、自分の綴りにしたければ frontmatter の type: を書き換えて ochakai put で戻せる。
2. 型の順に書いていく
次の順で、型ごとに書いていきます。
| # | 型 | 何に答えるか | 最初の目安 |
|---|---|---|---|
| 1 | BigQuery Table / Dataset | このテーブルは何で、何に注意するか | 取り込み済み。注意点を 1 つ書き足す |
| 2 | Glossary Term | その語が指すもの(「完了した注文」とは) | エージェントが取り違えた語だけ、5 個ほど |
| 3 | Policy | 数字を決める規則(収益認識、会計年度) | 2〜3 個 |
| 4 | Metric | 定義。SUM(price) にあたる部分 | セマンティックレイヤーがあるなら省いてよい |
| 5 | Attested Computation | 承認されたクエリ本体 | §0 の問いに一対一で 10〜20 本 |
| 6 | Insight | 数字の読み方。ベースライン、季節性、しきい値 | 最初は 3〜5 個 |
| 7 | Skill | 手順。「このクエリの走らせ方」 | 後回しでよい。無くても動く |
この順にするのは、後ろの型が前の型を指すからです。golden query は sources でテーブルのドキュメントを指し、Insight は Metric を指します。リンクは本文から作られるため、指される側が先に存在している必要があります。
効果が大きいのは 5 で、他の道具が持っていないのは 6 です。text-to-SQL の公開実験では、スキーマだけを渡した場合の正答率が 3% 前後でした。質問と検証済み SQL の対を検索して渡すと 75〜80% に上がります。差を作っているのはモデルではなく、検証済みクエリの蓄積です。Insight は、セマンティックレイヤーとデータカタログのどちらにも無い型です。100 という数字の良し悪し。8 月がいつも 15% 低いことの意味。こうしたことを書いておける場所が他に無い、というのが ochakai を使う理由の半分です。
ドキュメントは、こういう形をしています
フロントマター付きの markdown です。ochakai が保存しているファイルそのもので、ochakai get が返すのもこれです。次は Attested Computation、golden query 一件の例です。
--- type: Attested Computation title: 月次の計上売上 description: 完了した注文の月次売上(例) status: draft runtime: bigquery question: 今年度の月次売上は? tags: [sales, revenue] --- # Computation ```sql SELECT DATE_TRUNC(o.created_at, MONTH) AS month, SUM(o.total_price) AS revenue FROM `myproject.shop.orders` AS o WHERE o.status = 'completed' AND o.created_at >= DATE_TRUNC(CURRENT_DATE(), YEAR) GROUP BY month ORDER BY month ``` # Caveats - **完了した注文だけ。** `status = 'completed'` 以外は除いている。 - 金額は円、税込。返金は引いていないため、返品率の高い月は締めた数字より高く出る。 - 月の境目は注文の作成時刻(`created_at`、UTC)であり、経理の締めとは数時間ずれることがある。
読む価値があるのは # Caveats の側です。SQL はセマンティックレイヤーにもありますが、返金を引いていないことと、月の境目が経理とずれることは、書いた人しか知りません。ochakai put がこのファイルをそのまま受け取ります。
もう一件、表の 6 番 Insight の例です。
---
type: Insight
title: 月次売上の読み方
description: ベースライン、お盆、朝の遅延。この数字に驚く前に確かめる三つ
status: draft
tags: [sales, revenue, interpretation]
sources:
- id: fy2026-close
resource: https://wiki.example/finance/monthly-close
title: 月次決算スケジュール (FY2026)
author: human:sato@example.co.jp
last_modified: 2026-04-01T00:00:00Z
generated: { by: analysis_agent/2.1, at: 2026-08-20T02:10:00Z }
stale_after: 2027-04-01T00:00:00Z
---
数字そのものは[月次の計上売上](/queries/monthly-revenue.md)が出す。
ここにあるのは、その数字が知らせなのかどうかを見分ける方法である。
## 平常の揺れは前年同月比 ±6%
過去 3 年でこの幅を超えたのは 4 回。うち 3 回は下のどちらかで説明が
付いた。
## 8 月は毎年落ちる
お盆に法人の発注が止まるため、8 月は前月比で 12〜18% 低い。前年の
8 月と比べること。前月と比べると、毎年「悪化」が見つかる。
## 朝に見た数字は低い
受注データの取り込みが終わるのは 06:00 JST である[^fy2026-close]。
それより前に見た当日ぶんは、本当の落ち込みと見分けが付かない。日中の
数字を使うなら `MAX(created_at)` を添える。
[^fy2026-close]: 月次決算スケジュール (FY2026)
runtime と question は Attested Computation のもので、Insight は持ちません。逆にこちらは sources を持ち、脚注 [^fy2026-close] がその一行がどの資料に由来するかを名指します。stale_after はその日を過ぎたら見直すという書き手の宣言で、本文がすぐ古びる型ほど効きます。
必ず要るのは type だけです。残りは Open Knowledge Format v0.2 が定めるもので、ochakai はそれをそのまま保存します。本文の見出しも決まりではありません(# Computation だけは、golden query の SQL の在り処として決まっています)。知らないキーは往復しても消えないため、自分のチームの語を足してかまいません。
書くのはエージェントです。テーブルのドキュメントを開いて渡し、こう頼みます。
このテーブルについて、クエリを書く前に知っておくべきことを # Caveats に書き足して ochakai に保存して。必ず要るフィルタ、嘘をつくカラム、タイムスタンプのタイムゾーン。
ひと月で verified が 20〜30 件あれば、十分に育った知識ベースです。説明が無いまま残る draft は、誰の邪魔にもなりません。
3. 検索で見つかるかを確かめる
書いたことと、エージェントが検索で見つけられることは別です。§0 で書き出した問いを、そのまま実行します。
while read -r q; do printf '\n=== %s\n' "$q" ochakai search "$q" --limit 3 done < questions.txt
ここで返るものが、そのままエージェントの見るものになります。結果は三通りです。
- 期待したドキュメントが返った。その問いは片付いています。
- 何も返らない。書くものが足りていません。
ochakai statsの gap 行に、何も返さなかった検索が訊かれた回数の多い順に並びます。次に書くものの一覧です。 - 別のものが返った。多くは語の問題です。検索は本文を読むので、チームが実際に使う語を本文に入れるのが直し方です(タイトルだけ直しても変わりません)。ドキュメントが長すぎて後半が載っていない場合もあり、それは
ochakai statsのtruncatedに出ます。
外した問いは消さずに questions.txt に残し、直したらもう一度全部実行します。そのうち SQL を伴うものが Attested Computation になり、カナリアとして CI で走り続けます。
4. 二周目からの育て方
まずエージェントを繋ぎます(「エージェントを繋ぐ」)。想起と書き戻しを習慣任せにしないなら、同じページのフックを入れます。
ochakai list usage --status draft # 直近 90 日で実際に読まれた順
一週間動かすと、ここに読まれた順が出ます。二周目からは、その上位から確かめます。順番の決め方と、確かめる・却下する・公開するコマンドは「育てて、回す」です。
ひと月後の状態
エージェントが使うテーブルは一通り取り込まれ、そのうち何割かには人しか知らなかったことが書かれています。§0 の問いの大半は ochakai search で答えが返ります。書く側はここで止めてかまいません。あとは §2 と §3 の繰り返しです。