sandbox_schema
作る前に、保存するデータを画像ではなくテキストで並べます。テーブルとそのフィールドを並べ、フィールドごとに型、何が入るかの短い説明(すべてのフィールドで必須)、参照するテーブルを書きます。スキーマはテキストとしてツールの結果に返り、人はアプリの設計のページで同じ版をテキストの表として見て、丸で囲み、話し、文字を書き込んで報告します。ボックスは要りません。
| 入力 | 出力 |
|---|---|
topic(最大 80 文字、どの版でも同じ)、tables(1–30 個、すべてのフィールドに note)、任意の note(最大 300 文字:この版で変えたこと)、任意の id(ボックス。そのボックスのページにも設計を表示する) |
ok、designId(dsg_ で始まる、その設計)、reviewId(dsn_ で始まる、この版)、kind(schema)、topic、version、appUrl、id を渡したときは boxId、next、注意があれば warnings、人がこの会話にメモを残していれば fromHuman。スキーマのテキストは JSON のあとに text として続く。画像も imageUrls もない |
ツールのタイトル(MCP の title。クライアントによってはこれでツールを表示します)は Lay out a data schema です。注釈は readOnlyHint: false(成功するたびに 1 版保存する)、destructiveHint: false、openWorldHint: false です。
いつ使うか
新しく作るもの・変えるものの作業順は、sandbox_draft(画面)→ sandbox_architecture(サービス)→ sandbox_schema(保存するデータ)→ ボックスで作る → sandbox_review です。作業が触れない段階だけを飛ばします。新しく何も保存しない変更にはスキーマはありません。
作業で保存するものを追加・変更するとき(新しいテーブル、新しいカラム、意味の変わるフィールド)、または人がスキーマを見たいときに sandbox_schema を使います。代わりに HTML、SVG、画像、図、Markdown のファイルを書かないでください。このツールが並べ、すべての版を残し、人が答えるための道具も用意します。
返ってくるのがテキストであること以外は sandbox_draft と同じです。ボックスは要らず、設計はアカウントとこの会話に属し、ボックスが停止しても残ります。id は任意で、この作業のボックスを渡すと、そのボックスのページにも設計が表示されます。呼び出しはサーバーで行い(チェックして保存するだけで、描画はしません)、凍結したボックスを起こすことはありません。停止していないボックスを id に渡して成功すれば、そのボックスの使用に数えられ、呼んだ会話がボックスを持つ会話になります(sandbox_draft)。
何を書くか
この作業に必要なテーブルとフィールドだけを並べます。new: true は、今保存されているものと比べて新しい・違うテーブルとフィールドに付けます。テキストでは [new]、アプリでは「新規」が付きます。比べる相手は今保存されているもので、前の版ではありません。前の版から変えたことは note に書きます。
すべてのフィールドに note が必要です。何が入るかを短く書きます(「キャンセル待ちの順番。予約済みなら空」)。人がコードを読まなくてもそのフィールドを判断できるようにするためです。note のないフィールド、空や空白だけの note があると、呼び出し全体が失敗します(エラー)。label とすべての note は人が読む言語で書きます。渡したとおりに表示され、翻訳されません。
tables:
| フィールド | 必須 | 上限 | 内容 |
|---|---|---|---|
name |
必須 | 64 文字、重複不可 | テーブル名(bookings) |
label |
40 文字 | そのテーブルが何を持つか、人が読む言語で、名前のあとに表示(「予約」) | |
new |
この作業で追加するテーブル | ||
columns |
40 個 | フィールド、上から下へ |
columns:
| フィールド | 必須 | 上限 | 内容 |
|---|---|---|---|
name |
必須 | 64 文字 | フィールド名 |
note |
必須 | 1–120 文字 | そのフィールドに何が入るかの短い説明(「予約済み/キャンセル待ち/取消」) |
type |
推奨 | 40 文字 | 型(uuid、text、int、timestamptz) |
ref |
64 文字 | このフィールドが指すテーブル。→ テーブル名 と表示。このスキーマにないテーブルでも受け付け、warnings で知らされる |
|
new |
今と比べて新しい・違うフィールド |
綴りの違うフィールドや余分なフィールドはエラーになり、使えるフィールドが挙がります。黙って無視されることはありません。上限は文字数で数えます(漢字・かなも 1 文字)。呼び出しのうち id、topic、note 以外がスキーマの仕様で、JSON で最大 64 KB です。
例
{
"topic": "予約データ",
"tables": [
{
"name": "classes",
"label": "クラス",
"columns": [
{ "name": "id", "type": "uuid", "note": "クラスの ID" },
{ "name": "starts_at", "type": "timestamptz", "note": "開始時刻" }
]
},
{
"name": "bookings",
"label": "予約",
"columns": [
{ "name": "id", "type": "uuid", "note": "予約の ID" },
{ "name": "class_id", "type": "uuid", "ref": "classes", "note": "どのクラスか" },
{ "name": "status", "type": "text", "note": "予約済み/キャンセル待ち/取消" },
{ "name": "waitlist_rank", "type": "int", "note": "キャンセル待ちの順番。予約済みなら空", "new": true }
]
}
]
}
返り値
スキーマのテキストは JSON のあとに text として続きます。目を通してから、どこを見てほしいかを人に 1 行で伝えます。next も同じことを言います。上の例を最初の版として送ると、こうなります:
Schema "予約データ" v1
[new] = added or changed in this version; "→ table" = references that table; "# …" = what the field holds
classes (クラス)
id uuid # クラスの ID
starts_at timestamptz # 開始時刻
bookings (予約)
id uuid # 予約の ID
class_id uuid → classes # どのクラスか
status text # 予約済み/キャンセル待ち/取消
waitlist_rank int # キャンセル待ちの順番。予約済みなら空 [new]
- テーブルごとに 1 ブロック:
name、括弧に入ったlabel、new: trueのテーブルには[new]。続いてフィールドごとに 1 行:名前、型、refがあれば→ テーブル名、#とそのnote、new: trueのフィールドには[new]。columnsのないテーブルは(no columns)です。呼び出しにnoteがあれば、1 行目の下にChanged in this version: …の行が入ります。 - これらの決まった文字は、アカウントの言語にかかわらず常に英語です。あなたが書いた文字は絵文字も含めて渡したとおりに出ます。
designId(dsg_で始まる)はその設計で、このtopicのどの版でも同じ、reviewId(dsn_で始まる)はこの版の ID、versionはアカウント、種類、topicごとの番号(どのボックスを渡したか、渡したかどうかには関係しない)、appUrlはアプリのその設計のページ/design/<designId>(リンクを知っていれば誰でも開けます。フィードバックを送れるのはアカウントだけ)、boxIdはidに渡したボックス(渡さなければない)です。warningsは、このスキーマにないテーブルへのrefを知らせます。例:table "bookings" column "member_id": ref "members" is not one of the tables in this diagram。
人のアプリでは
人はアプリのその設計のページと「設計」一覧で、ボックスの id を渡したときはそのボックスのページの「スキーマ」でも、これを見ます。アプリでも画像ではなくテキストです。テーブルごとに 1 枚のカードで、テーブル名、label、新しいテーブルには「新規」の小さなタグ。その下にフィールドごとに 1 行で、名前、型、→ テーブル名、説明が並びます。新しくないテーブルの中の新しいフィールドや変えたフィールドは、名前の横に「新規」が付きます。テーブル全体が新しいときはテーブル名に 1 回だけ付け、フィールドごとには付けません。スマホでは 1 行目に名前と型、その下に説明。幅の広い画面では「カラム|型|説明」の 3 列に並びます。アプリ自身の文字(「新規」、列見出し)はアプリの言語に従います。
各テーブルのカードの下に「ここを報告」があります。そのテーブルのカードを画像にし、人はそこに丸を描き、話し、文字を書き込んで送ります。1 回の報告に複数のテーブルへのメモを入れられます。
人の報告と次の版
- ある版への報告は、ボックスがあってもなくても、その版を書いた会話に確認のフィードバックと同じように戻ってきます。アプリのフィードバックを受け取るよう設定した会話を起こすか、この会話が次に設計ツールかボックスに対するツールを呼んだときに
fromHumanとして届くか、AI へのメッセージをコピー で届きます。sandbox_reportにreportIdだけを渡して(idなしで)読みます。メッセージはFeedback on schema "<topic>" v<n>: …で始まります。囲まれた画像はそれぞれ、人が報告したテーブルのカードで、そのメモのsource.labelに版とテーブルが入ります(例:スキーマ「予約データ」v1 · bookings、アプリの言語で)。囲まれた画像、音声の文字起こし、画像に書き込まれた文字(notes[].labels)を読んでください。メッセージの最後はChange it as asked, then call sandbox_schema again with the same topic for the next version.です。自動でこの会話に戻るには、アダプターが 0.6.0 以降(ボックスのidを渡したときは 0.5.4 以降)で、Claude Code と Gemini CLI のフィードバック用 hook も 0.5.4 以降で入れたものである必要があります(自動で戻るための条件)。詳しくはsandbox_draft。 - 承認や確定の手順はありません。言われたとおりに直し、同じ
topic(idを渡していたなら同じidも)でもう一度sandbox_schemaを呼びます。仕様は全体を渡し(すべてのフィールドにnote)、前の版から変えたことを 1 文のnoteに書きます。それが次の版(v2、v3…)で、どのボックスからでも、ボックスなしでもかまいません。
エラー
呼び出しは、どのフィールドかを示すメッセージで失敗します。何も保存されず、どのボックスの使用にも数えられません:box not found (it must be one of yours; see sandbox_status or GET /v1/boxes)(渡した id がこのアカウントのボックスではありません。ボックスなしで書くなら id を外します)、topic is required: …、topic is at most 80 characters、note is at most 300 characters、spec is at most 64 KB、またはスキーマのチェックが受け付けないものを <パス>: <問題> で返します。パスは呼び出しの引数そのものです。
tables[0].columns[2].note: required (a short comment on every field):そのフィールドにnoteがないか、空です。すべてのフィールドにnoteを付けてください。ツールの input schema でも必須になっています。tables[1].name: duplicate table name "bookings" (also used by spec.tables[0]):括弧内のspec.tables[0]は呼び出しのtables[0]ですtables[0].columns[2]: unknown field "comment" (allowed: name, type, note, ref, new)spec: unknown field "table" (allowed: tables):余分な、または綴りの違う最上位の引数(id、topic、note以外の引数はすべてスキーマのチェックに渡り、それらはまとめてspecと呼ばれます)
そのフィールドを直して呼び直してください。
すべてのツールとトピックはツールリファレンスに並んでいます。