コンテキストレイヤーの実装である Agents Schema を dbt・OSI プロバイダーで試してみた
はじめに
dbt Labs と Fivetran が共同で公開しているオープンスタンダード Agents Schema を Snowflake 上で試してみた内容を記事としました。
本記事内の設定や動作は、検証時点(2026年9月)のバージョンであること、後述の agents-schema・apache-ossie-dbt ともに開発初期段階(0.0.x / dev0)であり将来的に仕様が変わり得る点にご注意ください。
Agents Schema の概要
Agents Schema については、以下に記載があります。
Fivetran と dbt Labs は、統合後に Open Data Infrastructure の構築を共同で進めており、この取り組みの一つに Agents Schema があります。
Agents Schema はコンテキストレイヤーの実装の一つです。実体はデータレイクまたは DWH 内に作成されるスキーマであり、AI エージェントがコンテキストを読み取るためのレイヤーとして機能します。
コンテキストレイヤーの実装としての Agents Schema
ここで、コンテキストレイヤーについて整理しておきます。
本記事でのコンテキストレイヤーは、以下の記事を参考に「指標定義そのものではなく、description・メタデータ・リネージ・社内ドキュメントといった指標以外の非構造化なビジネスコンテキストを、AI エージェントが参照できる形で管理する層」とします。
コンテキストレイヤーと近い概念として、セマンティックレイヤーやオントロジーがあります。上記の記事を参考に、それぞれの役割を整理すると以下の通りです。
| 概念 | 役割 | 特性 |
|---|---|---|
| セマンティックレイヤー | 指標・ディメンションの一元管理 | SQL/YAML にコンパイル可能なロジックとして定義される |
| コンテキストレイヤー | 指標以外の情報(description・メタデータ・リネージ、Confluence/Notion 等のドキュメント)の一元管理 | クエリへ直接コンパイルされない、継続更新される非構造化のビジネスコンテキスト |
| オントロジー | 組織に存在する概念(顧客・注文等)とその関係性の一元管理 | 実世界のエンティティ・関係を形式的に定義する、両者よりさらに上位の世界モデル |
それぞれのレイヤーは競合するものではなく、相補的な役割を持ちながら機能します。
詳細は後述しますが、Agents Schema には、メタデータとしてモデルやカラムの説明、依存関係(リネージ)、さらにはメトリクス定義といったビジネス上の正しい定義を含めることができます。これらの情報がウェアハウス上のスキーマに集約され、AI エージェントはこの情報を参照することでコンテキストを維持できる仕組みです。
Agents Schema の全体像
以下に Agents Schema スキーマの構成が定義されています。
Agents Schema を構築すると、ウェアハウス上のスキーマ(デフォルトはAGENTSスキーマ)に以下のようなテーブル群が作成されます。
AGENTS(スキーマ)
├── ROOT
├── DBT_MODEL / DBT_COLUMN / DBT_DEPENDENCY
├── OSI_DATASET / OSI_FIELD / OSI_METRIC / OSI_RELATIONSHIP
├── LOOKML_VIEW / LOOKML_DIMENSION / LOOKML_MEASURE / LOOKML_EXPLORE
├── OMNI_*
└── SIGMA_DATA_MODEL / SIGMA_ELEMENT / SIGMA_COLUMN / SIGMA_METRIC
起点となるのがAGENTS.ROOTです。このテーブルでは、メタデータソースとなる、どのプロバイダー(dbt・Omni など)のメタデータを利用できるか、それらのテーブルの役割、どのようなスキルが利用可能かを確認できます。
こうした各プロバイダーのテーブル群は、それぞれに用意されたagents-schema CLI のサブコマンドを使うことで作成されます。
現在、プロバイダーには dbt・OSI・LookML・Omni・Sigma・Snowflake Semantic View に加え、独自の業務ルールを登録する「独自スキル」が対応しています。dbt を例にすると、モデルやカラムの説明やリネージ情報がメタデータとして連携され、具体的にはAGENTS.DBT_MODEL / AGENTS.DBT_COLUMN / AGENTS.DBT_DEPENDENCYといったテーブルが作成されます。
先ほどのセマンティックレイヤー・コンテキストレイヤーの整理を Agents Schema にあてはめると、AGENTSスキーマの中には両方の役割が同居していると考えられます。
- セマンティックレイヤー相当:
AGENTS.OSI_METRIC/OSI_DATASET/OSI_FIELD/OSI_RELATIONSHIP(OSI が担当する、指標の定義を保持する部分。dbt Semantic Layer/MetricFlow のように SQL を生成・実行するところまでは行わない) - コンテキストレイヤー相当:
AGENTS.DBT_MODEL/DBT_COLUMNの description、AGENTS.DBT_DEPENDENCY(リネージ)、独自スキル(マークダウンによる非構造化テキスト)
SPEC.md でも dbt は「transformation layer」、OSI は「canonical semantic-layer source」と記載されています。つまり Agents Schema は、コンテキストレイヤー単体ではなく、セマンティックレイヤーの出力とコンテキストレイヤー的な情報を、同じAGENTSスキーマにまとめて提供する基盤とも言えると思います。
試してみる
本記事では、上述のプロバイダーとして dbt・OSI、また独自スキルの定義を試してみます。
前提条件
以下の環境を使用しています。
- OS:Windows 11
- Snowflake:トライアルアカウント
- dbt-core:1.12.4
- dbt-snowflake:1.12.0
- uv:0.9.27
- Snowflake CLI (
snow):3.27.0 - Claude Code +
dbt-labs/agents_schemaプラグイン:0.1.0
dbt の環境構築は以下をご参照ください。
事前準備(dbtプロジェクトをbuildできる状態にする)
事前準備として、dbt Core をインストールし、Snowflake への接続設定、dbt build が実行できる状態としておきます。
サンプルデータの準備
dbt 公式の jaffle_shop チュートリアル)を参考に Snowflake 側にデータの投入先となるデータベース・スキーマを作成し、データをロードします。
create database if not exists raw;
create schema if not exists raw.jaffle_shop;
create schema if not exists raw.stripe;
create table raw.jaffle_shop.customers
(
id integer,
first_name varchar,
last_name varchar
);
copy into raw.jaffle_shop.customers (id, first_name, last_name)
from 's3://dbt-tutorial-public/jaffle_shop_customers.csv'
file_format = (
type = 'CSV'
field_delimiter = ','
skip_header = 1
);
create table raw.jaffle_shop.orders
(
id integer,
user_id integer,
order_date date,
status varchar,
_etl_loaded_at timestamp default current_timestamp
);
copy into raw.jaffle_shop.orders (id, user_id, order_date, status)
from 's3://dbt-tutorial-public/jaffle_shop_orders.csv'
file_format = (
type = 'CSV'
field_delimiter = ','
skip_header = 1
);
create table raw.stripe.payment
(
id integer,
orderid integer,
paymentmethod varchar,
status varchar,
amount integer,
created date,
_batched_at timestamp default current_timestamp
);
copy into raw.stripe.payment (id, orderid, paymentmethod, status, amount, created)
from 's3://dbt-tutorial-public/stripe_payments.csv'
file_format = (
type = 'CSV'
field_delimiter = ','
skip_header = 1
);
dbt プロジェクト側では、上記のテーブルを参照する Source 定義と、ステージングモデル(stg_customers / stg_orders / stg_payments)・マートレイヤーに該当するモデル(customers)を作成します。
各ファイルの内容は以下の通りとしました。
models/staging/sources.yml
version: 2
sources:
- name: jaffle_shop
database: raw
schema: jaffle_shop
tables:
- name: customers
- name: orders
- name: stripe
database: raw
schema: stripe
tables:
- name: payment
models/staging/stg_customers.sql
select
id as customer_id,
first_name,
last_name
from {{ source('jaffle_shop', 'customers') }}
models/staging/stg_orders.sql
select
id as order_id,
user_id as customer_id,
order_date,
status
from {{ source('jaffle_shop', 'orders') }}
models/staging/stg_payments.sql
select
id as payment_id,
orderid as order_id,
paymentmethod as payment_method,
status,
amount / 100 as amount,
created
from {{ source('stripe', 'payment') }}
models/staging/schema.yml
version: 2
models:
- name: stg_customers
description: Staged customer data from the jaffle shop app.
columns:
- name: customer_id
description: The primary key for customers.
- name: first_name
description: Customer's first name.
- name: last_name
description: Customer's last name.
- name: stg_orders
description: Staged order data from the jaffle shop app.
columns:
- name: order_id
description: The primary key for orders.
- name: customer_id
description: Foreign key to the customer who placed the order.
- name: order_date
description: Date the order was placed.
- name: status
description: Status of the order (placed, shipped, completed, return_pending, returned).
- name: stg_payments
description: Staged payment data from the Stripe integration.
columns:
- name: payment_id
description: The primary key for payments.
- name: order_id
description: Foreign key to the order this payment is for.
- name: payment_method
description: The method used for the payment (credit_card, coupon, bank_transfer, gift_card).
- name: status
description: Status of the payment.
- name: amount
description: The payment amount, in dollars.
- name: created
description: Timestamp the payment record was created.
models/marts/customers.sql
with customers as (
select * from {{ ref('stg_customers') }}
),
orders as (
select * from {{ ref('stg_orders') }}
),
customer_orders as (
select
customer_id,
min(order_date) as first_order_date,
max(order_date) as most_recent_order_date,
count(order_id) as number_of_orders
from orders
group by 1
),
final as (
select
customers.customer_id,
customers.first_name,
customers.last_name,
customer_orders.first_order_date,
customer_orders.most_recent_order_date,
coalesce(customer_orders.number_of_orders, 0) as number_of_orders
from customers
left join customer_orders using (customer_id)
)
select * from final
models/marts/schema.yml
version: 2
models:
- name: customers
description: One record per customer, with order metrics.
config:
meta:
owner: analytics-team
columns:
- name: customer_id
description: The primary key for customers.
- name: first_name
description: Customer's first name.
- name: last_name
description: Customer's last name.
- name: first_order_date
description: Date of the customer's first order.
- name: most_recent_order_date
description: Date of the customer's most recent order.
- name: number_of_orders
description: Count of orders placed by the customer.
各種モデル作成後、dbt buildを実行し、開発環境に指定のデータベース・スキーマ配下に各種モデルが作成されることを確認しておきます。

dbt をソースとする AGENTS スキーマの構築
agents-schema CLI を使い、dbtのmanifest.jsonからAGENTS.DBT_*テーブルを構築します。このmanifest.jsonはdbt build(またはdbt compile)の実行時にtarget/配下へ生成されるため、前段の事前準備で一度dbt buildを実行済みであることが前提となります。
また、認証情報は、dbt の profiles.yml とは別に、WAREHOUSE_CREDENTIALSという環境変数(YAML形式)で渡します。Snowflake の場合、以下のような形式です。
export WAREHOUSE_CREDENTIALS=$(cat <<EOF
type: snowflake
account: <account>
user: <user>
warehouse: <warehouse>
database: <database>
role: <role>
private_key_pem: |
<鍵の中身>
EOF
)
# PyPI パッケージを uvx でインストールなし・バージョン固定のまま一時実行
uvx --from "agents-schema==0.0.11" agents-schema dbt --project-dir .
実行結果:
dbt: 4 models, 19 columns, 5 deps
今回は特にスキーマを指定しなかったので Snowflake 側を確認すると、AGENTSスキーマが作成され、さらに以下のテーブルも作成されていました。

AGENTS.ROOT: どのようなメタデータが公開されているかをエージェントが最初に確認するためのテーブル
provider(dbt などのメタデータの出所)とkey(内容の種別)ごとに、エージェント向けの説明文(content)が入っていることが分かります。

AGENTS.DBT_MODEL: モデル単位のメタデータ(モデル名・description・マテリアライズ方法等)
> SELECT * FROM dev_db.AGENTS.DBT_MODEL;
+---------------------------------------+---------------+---------------+---------------+-----------------+-----------------------------------------------------------------+----------------------------------+------+------+
| UNIQUE_ID | NAME | DATABASE_NAME | SCHEMA_NAME | MATERIALIZATION | DESCRIPTION | FILE_PATH | TAGS | META |
|---------------------------------------+---------------+---------------+---------------+-----------------+-----------------------------------------------------------------+----------------------------------+------+------|
| model.agents_schema_dbt.customers | customers | dev_db | dbt_tyasuhara | table | One record per customer, with order metrics. | models\marts\customers.sql | [] | {} |
| model.agents_schema_dbt.stg_customers | stg_customers | dev_db | dbt_tyasuhara | view | Staged customer data from the jaffle shop app. | models\staging\stg_customers.sql | [] | {} |
| model.agents_schema_dbt.stg_orders | stg_orders | dev_db | dbt_tyasuhara | view | Staged order data from the jaffle shop app. | models\staging\stg_orders.sql | [] | {} |
| model.agents_schema_dbt.stg_payments | stg_payments | dev_db | dbt_tyasuhara | view | Staged payment data from the Stripe integration. | models\staging\stg_payments.sql | [] | {} |
+---------------------------------------+---------------+---------------+---------------+-----------------+-----------------------------------------------------------------+----------------------------------+------+------+
AGENTS.DBT_COLUMN: カラム単位のメタデータ(description等)
COLUMN については、はじめschema.ymlでのカラム description 追加前は「0 columns」、追加後に「19 columns」となったためモデルのプロパティ定義の YAML でのドキュメント整備(description 記載)が実質的に必須でした。
> SELECT * FROM dev_db.AGENTS.DBT_COLUMN;
+---------------------------------------+-------------------------+-----------+----------------------------------------------------------------------------------+------+
| MODEL_ID | COLUMN_NAME | DATA_TYPE | DESCRIPTION | META |
|---------------------------------------+-------------------------+-----------+----------------------------------------------------------------------------------+------|
| model.agents_schema_dbt.customers | customer_id | | The primary key for customers. | {} |
| model.agents_schema_dbt.customers | first_name | | Customer's first name. | {} |
| model.agents_schema_dbt.customers | last_name | | Customer's last name. | {} |
| model.agents_schema_dbt.customers | first_order_date | | Date of the customer's first order. | {} |
| model.agents_schema_dbt.customers | most_recent_order_date | | Date of the customer's most recent order. | {} |
| model.agents_schema_dbt.customers | number_of_orders | | Count of orders placed by the customer. | {} |
| model.agents_schema_dbt.stg_customers | customer_id | | The primary key for customers. | {} |
| model.agents_schema_dbt.stg_customers | first_name | | Customer's first name. | {} |
| model.agents_schema_dbt.stg_customers | last_name | | Customer's last name. | {} |
| model.agents_schema_dbt.stg_orders | order_id | | The primary key for orders. | {} |
| model.agents_schema_dbt.stg_orders | customer_id | | Foreign key to the customer who placed the order. | {} |
| model.agents_schema_dbt.stg_orders | order_date | | Date the order was placed. | {} |
| model.agents_schema_dbt.stg_orders | status | | Status of the order (placed, shipped, completed, return_pending, returned). | {} |
| model.agents_schema_dbt.stg_payments | payment_id | | The primary key for payments. | {} |
| model.agents_schema_dbt.stg_payments | order_id | | Foreign key to the order this payment is for. | {} |
| model.agents_schema_dbt.stg_payments | payment_method | | The method used for the payment (credit_card, coupon, bank_transfer, gift_card). | {} |
| model.agents_schema_dbt.stg_payments | status | | Status of the payment. | {} |
| model.agents_schema_dbt.stg_payments | amount | | The payment amount, in dollars. | {} |
| model.agents_schema_dbt.stg_payments | created | | Timestamp the payment record was created. | {} |
+---------------------------------------+-------------------------+-----------+----------------------------------------------------------------------------------+------+
AGENTS.DBT_DEPENDENCY: モデル間・ソース間の依存関係(リネージ)
> SELECT * FROM dev_db.AGENTS.DBT_DEPENDENCY;
+------------------------------------------------+---------------------------------------+---------------+-----------------+
| UPSTREAM_ID | DOWNSTREAM_ID | UPSTREAM_TYPE | DOWNSTREAM_TYPE |
|------------------------------------------------+---------------------------------------+---------------+-----------------|
| model.agents_schema_dbt.stg_customers | model.agents_schema_dbt.customers | model | model |
| model.agents_schema_dbt.stg_orders | model.agents_schema_dbt.customers | model | model |
| source.agents_schema_dbt.jaffle_shop.customers | model.agents_schema_dbt.stg_customers | source | model |
| source.agents_schema_dbt.jaffle_shop.orders | model.agents_schema_dbt.stg_orders | source | model |
| source.agents_schema_dbt.stripe.payment | model.agents_schema_dbt.stg_payments | source | model |
+------------------------------------------------+---------------------------------------+---------------+-----------------+
SKILL_USE: 各スキルがusesフロントマターで宣言したスキーマ・テーブルの依存関係を格納するテーブル(現時点では独自スキルを未登録のため空)
> SELECT * FROM dev_db.AGENTS.SKILL_USE;
+----------+-----------+----------+------------+
| PROVIDER | SKILL_KEY | USE_KIND | OBJECT_REF |
|----------+-----------+----------+------------|
+----------+-----------+----------+------------+
metaカラムを追加
dbt からのメタデータの特徴として、AGENTS.DBT_MODEL / AGENTS.DBT_COLUMNにはdescriptionとは別にMETAという VARIANT 型のカラムが存在します。これは dbt の meta 設定を格納するためのカラムです。
試しにmetaを追加してみます。models/marts/schema.ymlのcustomersモデルに1つ追加しました。
- name: customers
description: One record per customer, with order metrics.
config:
meta:
owner: analytics-team
dbt build、agents-schema dbtを再度実行し、AGENTS.DBT_MODELの対象モデルを再度確認します。
> SELECT UNIQUE_ID, NAME, META FROM dev_db.AGENTS.DBT_MODEL WHERE NAME = 'customers';
+-----------------------------------+-----------+-----------------------------+
| UNIQUE_ID | NAME | META |
|-----------------------------------+-----------+-----------------------------|
| model.agents_schema_dbt.customers | customers | { |
| | | "owner": "analytics-team" |
| | | } |
+-----------------------------------+-----------+-----------------------------+
meta属性がエージェントスキーマ側にも反映されていました。metaは dbt 標準の機能であり、Agents Schema 側で特別な対応をしなくても、任意のキー・バリューをそのまま JSON 形式で連携できる点はメリットが大きいと感じました。descriptionが自由文なのに対し、metaは構造化されたデータなので、プログラム的にフィルタ・判断材料として使いやすいと思います。
エージェント経由で問い合わせる
事前準備
dbt-labs/agents_schemaは、Claude Code / Codexのプラグインとしても提供されており、導入すると次の2つのスキルが使えるようになります。
connect-warehouse: Snowflake / BigQuery / Databricks へエージェントを接続するためのスキルです。agents-schema-search等でウェアハウスに直接アクセスする前に呼ばれ、Snowflake の場合は Snowflake CLI 経由で接続を確立します。この際、後述のagents.ymlにsnow_cli_connectionの指定があればそれを使い、なければsnow connection listで既存接続を確認、それもなければ新規接続を作成するスキルですagents-schema-search: ウェアハウスのデータについて質問された際に、まずAGENTS.ROOTを検索してどのプロバイダーがメタデータを公開しているかを確認し、そのガイダンスに従ってAGENTS.DBT_MODEL等の該当テーブルを照会するスキルです
claude plugin marketplace add dbt-labs/agents_schema
claude plugin install agents-schema@agents-schema
スキル追加後、問い合わせ前にここでは以下の設定を行いました。
- Snowflake CLI のコネクションの設定
- エージェント経由でのクエリ実行に使用するコネクションを設定します(database/warehouse/ロールの指定など)
agents.ymlの配置:connect-warehouseスキルが参照する設定ファイルで、使用するコネクション名をあらかじめ以下のように記載しておきました
# agents.yml
snow_cli_connection: <コネクション名>
agents.ymlは dbt プロジェクトの中に置く必要はなく、少なくともエージェントを実行する作業ディレクトリに配置すればよいです。
今回はローカルのモデル定義を参照できない状態でもAGENTSスキーマだけを頼りに正しく回答できるかを確認したく、dbt プロジェクトのファイルを一切含まないagents.ymlだけを置いた別ディレクトリを作業ディレクトリとし、新しいセッションを開始しました。
モデルに関する問い合わせ
Claude Code のagents-schema:agents-schema-searchスキル経由で、モデルに関する問い合わせを行いました。問い合わせ内容と回答は以下の通りでした。
質問1:
customersモデルにはどんなカラムがある?
回答:
`customers`モデル(`dbt_tyasuhara`スキーマ、「顧客ごとに1レコード、注文メトリクス付き」)には以下のカラムがあります。
| カラム名 | 説明 |
| ------------------------ | -------------------- |
| `customer_id` | 顧客の主キー |
| `first_name` | 顧客の名 |
| `last_name` | 顧客の姓 |
| `first_order_date` | 顧客の初回注文日 |
| `most_recent_order_date` | 顧客の最新注文日 |
| `number_of_orders` | 顧客が行った注文件数 |
`dbt_column`メタデータには`data_type`が記録されていませんでした。
質問2:
stg_ordersのstatusカラムは何を表している?
回答:
`stg_orders`の`status`カラムは、注文のステータスを表しています。取りうる値は以下の5つです。
- `placed`(注文確定)
- `shipped`(発送済み)
- `completed`(完了)
- `return_pending`(返品保留中)
- `returned`(返品済み)
質問3:
customersモデルは何のテーブルに依存している?
回答:
`customers`モデルは、中間モデル`stg_customers`・`stg_orders`を経由して、以下のソーステーブルに依存しています。
- `jaffle_shop.customers`(`stg_customers`経由)
- `jaffle_shop.orders`(`stg_orders`経由)
依存関係の全体像は次の通りです。
jaffle_shop.customers → stg_customers ─┐
├→ customers
jaffle_shop.orders → stg_orders ───┘
質問4:
stg_paymentsは今、他のどのモデルから参照されている?
回答:
`stg_payments`は、現在どのモデルからも参照されていません(依存関係グラフ上、下流にあたるモデルは0件でした)。
いずれの質問についても、Claude Code のツール呼び出しログ(実際にどのSQLをどの順番で実行したか)を確認すると、まずAGENTS.ROOTを検索し、そこから質問内容に応じてAGENTS.DBT_MODEL / AGENTS.DBT_COLUMN / AGENTS.DBT_DEPENDENCYのいずれかを辿って回答していることが確認できました。
集計を問い合わせてみる
続けて、集計を伴う問い合わせを試してみます。少し曖昧な質問ですが、以下の問い合わせを試してみます。
全期間の合計売上(total revenue)はいくらですか?
ここではエージェントが参照できるメトリクス定義が存在しないためか、「ガバナンスされた指標定義が見つからない」という一次回答になりました。dbtのモデル・カラムの説明はあっても、集計ロジック自体は定義していないため、勝手に SUM を組み立てて答えることはしない、という挙動でした。
「全期間の合計売上」については、ガバナンスされた指標定義(osi_metricやlookml_measureなど)がこのAGENTSスキーマに存在しないため、正式な回答はできません。
- AGENTS.ROOTに登録されているのはdbtとskillsプロバイダのみで、売上(revenue)を定義したメトリック層がありません。
- 唯一近い候補はstg_payments.amount(支払額)ですが、以下が不明で計算式を勝手に決められません。
- statusカラムに何を含めるべきか(成功のみか、失敗・返金も含むか)
- 「売上」の定義が「支払total」なのか「注文total」なのかも指定がない
ガイドライン上、指標定義が見つからない場合は推測せず確認を取るルールになっています。以下のいずれかで進めてよいか教えてください。
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
☐ 売上の定義
「合計売上」をどう計算しますか?(stg_paymentsのstatus値の扱いが不明なため確認)
1. 全ステータス合算でSUM(amount)
stg_paymentsのamountを、statusに関わらず全件合計する
2. 成功ステータスのみ合算
stg_paymentsのstatusで成功系(例: success相当)のみ抽出してSUM(amount)する。ただしstatusの取りうる値を先に確認する必要あり
3. 先にstatusの値一覧を確認したい
stg_paymentsのstatusカラムに実際どんな値が入っているかSELECT DISTINCTで確認してから決める
4. Type something.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
❯ 5. Chat about this
セマンティックモデルの追加
はじめは、dbt のセマンティックモデルをstg_paymentsに追加し、agents-schema dbtを再実行すれば集計に関する問い合わせに回答できるようになると考えていました。しかし実際にAGENTS.DBT_MODEL/AGENTS.DBT_COLUMNを確認してもsemantic_model/metricsの情報は反映されませんでした。
少なくとも現時点では dbt プロバイダー経由ではメトリクス定義をAGENTSスキーマへ載せない仕様だったためです。
一方で、Agents Schema では OSI(Open Semantic Interchange)をプロバイダーとして追加することができます。
SPEC.md にも、両プロバイダーの役割が以下のように記載されています。
Source: dbt — "It captures the transformation layer..."
Source: OSI — "OSI is the canonical semantic-layer source..."
上記より、メトリクスの情報は、OSI のフォーマット経由でAGENTSスキーマに載る仕様となっているため、ここでは dbt のセマンティックモデルを後述のコンバーターで OSI 仕様に変換した上で Agents Schema への追加を試してみます。
Apache Ossie(Open Semantic Interchange)の概要
Apache Ossie(旧 Open Semantic Interchange: OSI)は、データ分析・AI・BI プラットフォーム間でセマンティックモデルを交換するための業界横断的なオープン仕様です。「同じ KPI がツールごとに違う定義になってしまう」という課題を解決するために、ベンダー中立の単一フォーマット(JSON/YAML)を提供しています。
- リポジトリ: https://github.com/apache/ossie/tree/main
- 仕様書: https://github.com/apache/ossie/blob/main/core-spec/spec.md
Apache Ossie は、コア仕様に加えて、dbt や Snowflake など各ベンダー固有フォーマットとの相互変換を担うconverters(コンバーター)を提供しています。この変換は下図のようなハブ・アンド・スポーク型のアーキテクチャを採用しています。
- Hub(ハブ): Ossieのコア仕様が、中心となるベンダー中立フォーマットとして機能する
- Spoke(スポーク): 各コンバーターが、特定ベンダーのフォーマットとの相互変換を担当する
┌─────────────┐
│ Snowflake │
└──────┬──────┘
│
┌─────────────┐ ┌─────┴─────┐ ┌─────────────┐
│ dbt ├────┤ Ossie ├────┤ Salesforce │
└─────────────┘ └─────┬─────┘ └─────────────┘
│
┌──────┴──────┐
│ Databricks │
└─────────────┘
※図はこちらより引用。
converters/配下には、dbt・Snowflake・Omni・Databricks など既存の主要なセマンティックレイヤー実装との双方向変換ツールが用意されています。
本記事では、この中のconverters/dbt(apache-ossie-dbt)を使って、dbt のセマンティックモデル仕様を OSI 形式に変換します。
dbt Semantic model から OSI 形式への変換
はじめに dbt でメトリクスを定義します。models/staging/schema.ymlのstg_paymentsに以下を追記しました。
models:
- name: stg_payments
semantic_model:
enabled: true
agg_time_dimension: created
columns:
- name: payment_id
entity:
type: primary
name: payment
- name: created
granularity: day
dimension:
type: time
metrics:
- name: total_revenue
type: simple
agg: sum
expr: amount
MetricFlow には時間軸集計のためのタイムスパインモデルが必須なので、以下のモデルをあわせて追加しました。
{{ config(materialized='table') }}
select
dateadd(day, seq4(), '2000-01-01'::date) as date_day
from table(generator(rowcount => 10000))
次に、Apache Ossie の変換ツール(apache-ossie-dbt)で、dbt のセマンティックモデルを OSI 形式に変換します。
# PyPI未公開(devバージョン)のため、GitHubのサブディレクトリを指定してインストール
uv add "apache-ossie-dbt @ git+https://github.com/apache/ossie.git#subdirectory=converters/dbt"
uv run dbt parse # target/semantic_manifest.json を生成
uv run ossie-dbt msi-to-ossie -i target/semantic_manifest.json -o semantic_model.yaml # Ossie(OSI) YAML へ変換
※ Windows環境では、description内の全角ダッシュ等が原因で'cp932' codec can't encode character'のようなエラーが出ることがあります。その場合は先頭にPYTHONUTF8=1 PYTHONIOENCODING=utf-8を付けて実行してください。
上記を実行すると、以下のようなsemantic_model.yaml(OSI形式)が生成されました。
version: 0.2.0.dev0
semantic_model:
- name: semantic_model
datasets:
- name: stg_payments
source: dev_db.dbt_tyasuhara.stg_payments
primary_key:
- payment_id
description: Staged payment data from the Stripe integration.
fields:
- name: payment
expression:
dialects:
- dialect: ANSI_SQL
expression: payment_id
description: The primary key for payments.
- name: order
expression:
dialects:
- dialect: ANSI_SQL
expression: order_id
description: Foreign key to the order this payment is for.
- name: payment_method
expression:
dialects:
- dialect: ANSI_SQL
expression: payment_method
dimension:
is_time: false
description: The method used for the payment (credit_card, coupon, bank_transfer,
gift_card).
- name: status
expression:
dialects:
- dialect: ANSI_SQL
expression: status
dimension:
is_time: false
description: Status of the payment.
- name: created
expression:
dialects:
- dialect: ANSI_SQL
expression: created
dimension:
is_time: true
description: Timestamp the payment record was created.
metrics:
- name: total_revenue
expression:
dialects:
- dialect: ANSI_SQL
expression: SUM(stg_payments.amount)
description: Governed metric — sum of all payment amounts across all statuses
(no status filter applied). Use this instead of writing an ad-hoc SUM(amount).
dbt のsemantic_model/metrics定義が、OSI のdatasets / fields / metricsという構造にマッピングされています。
agents-schema osi で AGENTS スキーマへ反映
変換した OSI 形式のsemantic_model.yamlを、agents-schema CLI のosiサブコマンドでAGENTSスキーマへ反映します。agents-schema osiは指定したディレクトリ配下の*.osi.yamlファイルを読み込む仕様だったため、まずファイルをその命名規則に合わせてリネームします。
mkdir osi && cp semantic_model.yaml osi/semantic_model.osi.yaml # ファイル名は *.osi.yaml が必須
uvx --from "agents-schema==0.0.11" agents-schema osi --osi-dir osi
※ こちらもWindows環境では同様のcp932デコードエラーが発生することがあります。その場合は先頭にPYTHONUTF8=1 PYTHONIOENCODING=utf-8を付けて実行してください。
出力:
osi: 1 models, 1 datasets, 5 fields, 1 metrics, 0 relationships
実行後、Snowflake 側のAGENTSスキーマを確認すると、OSI_からなるテーブルが作成されていました。
AGENTS.OSI_MODEL: セマンティックモデル自体のメタデータ(モデル名・説明・同義語等)AGENTS.OSI_DATASET: データセット単位のメタデータ(参照元テーブル・主キー・説明等)AGENTS.OSI_FIELD: フィールド単位のメタデータ(列名・説明・時間ディメンションかどうか・SQL方言ごとの式等)AGENTS.OSI_METRIC: メトリクス定義(指標名・説明・SQL方言ごとの集計式等)AGENTS.OSI_RELATIONSHIP: データセット間の関連性(結合元・結合先のキー等)

AGENTS.OSI_METRICを確認するとtotal_revenue = SUM(stg_payments.amount)というメトリクスが登録されていました。
>SELECT * FROM AGENTS.OSI_METRIC;
+----------------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+----------+------------+-------------------+
| MODEL_NAME | NAME | DESCRIPTION | EXPRESSIONS | SYNONYMS | AI_CONTEXT | CUSTOM_EXTENSIONS |
|----------------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+----------+------------+-------------------|
| semantic_model | total_revenue | Governed metric — sum of all payment amounts across all statuses (no status filter applied). Use this instead of writing an ad-hoc SUM(amount). | [ | [] | [] | [] |
| | | | { | | | |
| | | | "dialect": "ANSI_SQL", | | | |
| | | | "expression": "SUM(stg_payments.amount)" | | | |
| | | | } | | | |
| | | | ] | | | |
+----------------+---------------+-------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+----------+------------+-------------------+
再度エージェント経由で集計に関する問い合わせを行う
OSI メタデータ追加後、再度同じ問い合わせを行います。
全期間の合計売上(total revenue)はいくらですか?
応答:
## 全期間の合計売上
**$1,763**
- 使用した指標: `AGENTS.osi_metric` の `total_revenue`(「ステータスに関わらず全支払額の合計」と定義されたガバナンス済み指標)
- ソーステーブル: `AGENTS.osi_dataset` で解決した `dev_db.dbt_tyasuhara.stg_payments`
- 実行SQL: `SELECT SUM(amount) AS total_revenue FROM dev_db.dbt_tyasuhara.stg_payments;`
今度はAGENTS.OSI_METRICの定義に基づき、推測なしで具体的な金額を回答できました。
独自スキルを追加する
さいごに独自スキルの追加を試してみます。
agents-schema skillsを使うと、自社独自の業務ルールや注意点をマークダウンでAGENTS.ROOTに公開し、どのエージェントからも発見・遵守させることができます。
usesフロントマターでスキーマ・テーブルを宣言したマークダウンを用意します。ここでは以下のスキルをskills/revenue.mdとして作成しました。内容としては、「総売上や決済関連の質問に答える際は、SQLを組み立てる前にAGENTS.OSI_METRICのガバナンス済み指標(total_revenue)を参照し、独自にSUM(amount)を組み立てないこと」というルールを記述しています。
---
uses:
schemas:
- DBT_TYASUHARA
tables:
- DEV_DB.DBT_TYASUHARA.STG_PAYMENTS
---
# Revenue Skill
Use this skill when answering total revenue, payment total, or Stripe payment questions for this warehouse.
Before writing any SQL, look up the governed metric in `AGENTS.OSI_METRIC` (metric name `total_revenue`, defined against `stg_payments`). Use its `expressions` column as the exact formula — do not invent a `SUM(amount)` filter on your own, since the metric definition already documents whether payment status is filtered.
記法や例は以下に記載があります。
作成したスキルを以下のコマンドで Agents Schema に追加します。--providerは、このスキルを公開した主体を表す識別子です。省略時はuserがデフォルト値になり、ファイルパスと組み合わさって(provider, skill/<相対パス>)という形でAGENTS.ROOTに公開されます(今回はyasuharaを指定したので、(yasuhara, skill/revenue)として登録されます)。
uvx --from "agents-schema==0.0.11" agents-schema skills --skills-dir skills --provider yasuhara
※ こちらもWindows環境ではスキルのマークダウンに含む文字によってcp932エラーが発生することがあります。その場合は先頭にPYTHONUTF8=1 PYTHONIOENCODING=utf-8を付けて実行してください。
skills: 1 skills, 2 uses
AGENTS.ROOT・AGENTS.SKILL_USEに反映されていることを確認します。
> SELECT provider, key, content FROM AGENTS.ROOT WHERE provider = 'yasuhara';
+----------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| PROVIDER | KEY | CONTENT |
|----------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| yasuhara | skill/revenue | --- |
| | | uses: |
| | | schemas: |
| | | - DBT_TYASUHARA |
| | | tables: |
| | | - DEV_DB.DBT_TYASUHARA.STG_PAYMENTS |
| | | --- |
| | | |
| | | # Revenue Skill |
| | | |
| | | Use this skill when answering total revenue, payment total, or Stripe payment questions for this warehouse. |
| | | |
| | | Before writing any SQL, look up the governed metric in `AGENTS.OSI_METRIC` (metric name `total_revenue`, defined against `stg_payments`). Use its `expressions` column as the exact formula — do not invent a `SUM(amount)` filter on your own, since the metric definition already documents whether payment status is filtered. |
| | | |
+----------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
> SELECT * FROM AGENTS.SKILL_USE;
+----------+---------------+----------+-----------------------------------+
| PROVIDER | SKILL_KEY | USE_KIND | OBJECT_REF |
|----------+---------------+----------+-----------------------------------|
| yasuhara | skill/revenue | schema | DBT_TYASUHARA |
| yasuhara | skill/revenue | table | DEV_DB.DBT_TYASUHARA.STG_PAYMENTS |
+----------+---------------+----------+-----------------------------------+
このスキルの実体はウェアハウス側(AGENTS.ROOT.content)に格納されるため、推論時にはローカルのマークダウン ファイルは不要という点が特徴です。これにより、Claude Code に限らず、AGENTSスキーマへクエリできるどのエージェント・ツールからでも同じスキルにアクセスできる、という点がポイントだと思います。
実際にスキルを使用する問い合わせを試してみます。
/agents-schema:agents-schema-search 総収益はどれくらいですか?
回答:
## 総収益: **$1,763**
**根拠(AGENTS スキーマの定義に基づく)**
- `AGENTS.ROOT` に `yasuhara` プロバイダーの `skill/revenue` エントリがあり、総収益は `AGENTS.OSI_METRIC` の `total_revenue` メトリクスを使うよう指定
- `total_revenue` の定義: **`SUM(stg_payments.amount)`**(ステータスによるフィルタなし、全ステータス合算)
- ソーステーブル: `dev_db.dbt_tyasuhara.stg_payments`(`AGENTS.OSI_DATASET` で確認)
実行したSQL:
SELECT SUM(amount) AS total_revenue, COUNT(*) AS n_payments
FROM dev_db.dbt_tyasuhara.stg_payments;
→ 120件の支払いレコード、合計 $1,763.00
**注意点**: このメトリクス定義は「no status filter applied(ステータスによるフィルタなし)」と明記されており、失敗・返金などのステータスも含めた合算です。もし「成功した支払いのみの収益」が知りたい場合は、`status` カラムでのフィルタが別途必要になります(現状の`AGENTS`定義には status 別の収益メトリクスは見当たりませんでした)。
独自スキルで指定したAGENTS.OSI_METRICのガバナンス済み指標を使い、正しく総収益を回答できました。スキルの指示通り、根拠となったスキル・メトリクス定義・実行 SQL まで明示した上で、「このメトリクスはステータスによるフィルタをかけていない」という定義上の注意点まで回答に含めてくれました。
さいごに
コンテキストレイヤーの実装の一つである Agents Schema を試してみました。
独自スキルを追加でき、その実体がローカルファイルではなくAGENTS.ROOTに格納されるため、ローカルのコードにアクセスできないエージェントからでも、どのツールからでも同じガバナンス済みの定義を参照できる点、既存のdbt buildが生成するmanifest.jsonからモデル・カラムの説明やリネージをそのままAGENTSスキーマへ変換できる点は、導入コストの低さという意味で魅力的でした。
一方で、descriptionやスキルの本文に書いた内容はそのまま AI エージェントから見えてしまうため、メタデータであっても、モデルそのものの公開範囲を制御したい場合や機密情報を含む場合は行アクセスポリシーなどによるアクセス制御も別途検討が必要になりそうと思いました。
本記事の内容がどなたかの参考になれば幸いです。
参考






