AWS Context Ontology Accelerator(COA)で業務オントロジーを構築してみた - なぜ今オントロジーなのか?

AWS Context Ontology Accelerator(COA)で業務オントロジーを構築してみた - なぜ今オントロジーなのか?

AWS Context Ontology Accelerator は、AI を使ってオントロジーのドラフトを生成し、人のレビュー・承認を経て、エージェントが正確・一貫性があり・監査可能な意思決定を行えるようにするツールです。実際にデプロイして、データから関係を推論し、業務ルールを検証する過程を追体験して、オントロジーとは何かを感じてください。
2026.08.17

クラウド事業統括本部の石川です。2026 年 7 月 31 日、AWS から Context Ontology Accelerator が発表されました。組織のビジネスを機械可読なモデル(オントロジー)として表現し、AI エージェントが正確・一貫性があり・説明可能で・監査可能な意思決定を行えるようにするオープンソースのアクセラレーターです。

AWS の発表では、これまで数ヶ月かかっていた手作業のオントロジー作成を数日に短縮できるとされています。エージェントを PoC で止めずに本番投入したい方にとって、有力な選択肢になりそうです。

https://aws.amazon.com/jp/about-aws/whats-new/2026/07/aws-context--ontology-accelarator-generally-available/

Context Ontology Accelerator とは

Context Ontology Accelerator は、構造化データソース・非構造化データソースの両方に接続し、AI を使ってオントロジーのドラフトを生成する仕組みです。生成されたドラフトは、ドメインエキスパートがすべての要素をレビュー・編集・承認します。

承認済みのオントロジーは、利用者自身が所有するナレッジグラフに W3C のオープン標準形式で保存されるため、標準準拠のツールであればどれでも扱えます。そして同梱の Model Context Protocol(MCP)サーバーを通じて、任意のエージェントがそのコンテキストを消費できます。

https://aws.amazon.com/jp/blogs/machine-learning/context-intelligence-for-your-data-and-ai-agents-at-scale/

ここで押さえておきたいのが、オントロジーとナレッジグラフの違いです。

オントロジーは「顧客」「注文」「商品」といった概念(クラス)と、その属性・関係・制約を定義するスキーマ層にあたります。一方ナレッジグラフは、そのスキーマに沿って実際のインスタンスと関係を保持するデータ層です。Context Ontology Accelerator は前者を人手の承認つきで整備し、後者に materialize する役割を担います。

AWS の発表では、この背景として次の課題が挙げられています。エージェントが必要とするコンテキスト(エンティティ、ルール、ポリシー、リレーションシップ)は、スキーマや命名規約が競合する数十のシステムに散在しています。チームは定義のすり合わせに数ヶ月を費やしてプロンプトや個別連携に埋め込むものの、結果がトレース可能ではないため、エージェントを PoC から本番へ進めることをためらってしまう、というものです。

提供する機能

主な内容は以下のとおりです。

  • 構造化データソースおよび非構造化データソースに接続し、AI がオントロジーのドラフトを生成する
  • ドメインエキスパートがオントロジーのすべての要素をレビュー・編集・承認する
  • 承認済みオントロジーは、利用者が所有するナレッジグラフに W3C オープン標準形式で保存される
  • 同梱の MCP サーバー経由で、任意のエージェントがオントロジーを消費できる
  • GitHub にて Apache 2.0 ライセンスで本日(2026 年 7 月 31 日)より利用可能
  • 初期リリースでは Amazon Neptune をグラフストア、Amazon OpenSearch Serverless をベクトルストア、Amazon Bedrock 上でホストされる基盤モデルを使用する

AWS は、Context Ontology Accelerator が持つマネージドなユーザー定義オントロジー機能について、将来的に AWS Context のネイティブなフルマネージド機能になるとしています。Context Ontology Accelerator でオントロジーを作成し始めた利用者は、後から AWS Context でそれを利用・管理できるようになる見込みです。

https://github.com/aws/context-ontology-accelerator

https://aws.github.io/context-ontology-accelerator/

対応リージョン

What's New にリージョンの記載はありません。ただし OSS のドキュメントによれば、Context Ontology Accelerator はすべての AWS リージョンにデプロイできるわけではありません。デプロイ可能な範囲は、依存する各サービスが提供されているリージョンになります。

ドキュメントで確認が必要とされているサービスは以下です。特に上 2 つが実務上もっとも狭い制約になるとされています。

サービス 用途
Amazon Bedrock AgentCore Runtime Serve(クエリ)と MCP サーバーのランタイムをホスト
Amazon DataZone / Amazon SageMaker Unified Studio ネームスペースのドメイン、データアセットカタログ
Amazon Neptune ナレッジグラフストア
Amazon OpenSearch Serverless 検索用のベクトル検索
Amazon Bedrock(Guardrails 含む) LLM・埋め込み呼び出し、コンテンツフィルタリング
Amazon Athena(フェデレーテッドクエリ含む) マッピング済みデータソースに対する SQL

デフォルトのデプロイ先は us-east-1 で、ドキュメント上も検証済みなのは us-east-1 のみと明記されています。加えて AWS GovCloud および中国リージョンは非対応です。また、デフォルトのモデル ID は US のクロスリージョン推論プロファイル(us.anthropic.…us.cohere.embed-v4:0)であるため、US 以外にデプロイする場合は自リージョンから呼び出せるプロファイルへの差し替えが必要になります。

料金への影響

What's New に料金の記載はありません。Context Ontology Accelerator 自体は Apache 2.0 の OSS なのでソフトウェア利用料は発生しませんが、デプロイした AWS リソースの費用は当然かかります。

OSS のドキュメントには「Amazon Neptune と Amazon OpenSearch Serverless でアイドル時におよそ 930 USD/月」というコスト警告が記載されており、検証していないときはスタックを削除することが推奨されています。検証用途では、Amazon OpenSearch Serverless の最小 OCU を 0 にする scale-to-zero オプション(cdk deploy -c aoss_min_ocu=0)も用意されています。ただしスケールダウン後の復帰に約 10 秒かかるため、対話的なクエリを提供する環境には向きません。

アーキテクチャ: Scan → Model → Serve

Context Ontology Accelerator は Scan → Model → Serve という 3 フェーズのワークフローで構成されています。

Scan フェーズ

データソースを接続し、スキーマを検出してメタデータを充実させ、ドキュメントを取り込むフェーズです。

構造化ソースとしては、AWS Glue Data Catalog データベースと JDBC データベース(PostgreSQL、Amazon Redshift、MySQL、SQL Server)に対応しています。登録するとスキャンパイプラインが自動で走り、テーブル・カラム・制約を検出したうえで、Amazon Bedrock による説明文・シノニム・キー推論といった AI エンリッチメントが行われます。

ここで重要なのが、エンリッチされたメタデータがナレッジグラフに入る前に必ず人のレビューを挟む点です。ソースのステータスは REGISTERED → SCANNING → ENRICHING → PENDING_REVIEW → APPROVED と遷移し、データスチュワードがテーブル単位・カラム単位で承認・却下できます。スチュワードが編集したメタデータは STEWARD_EDITED として最優先扱いになり、再スキャンでも保持されます。

非構造化ソースとしては、Web アプリからのローカルアップロード(PDF / TXT / DOCX / HTML、1 ファイル最大 50MB)と、Amazon S3 バケット(同一アカウント・クロスアカウント)に対応しています。取り込まれたドキュメントは、前処理 → エンティティ抽出 → ナレッジグラフ構築 → 埋め込み生成というパイプラインを通ります。

Model フェーズ

承認済みデータソースからオントロジーを誘導(induction)し、メトリクスを定義して、統合セマンティックグラフを構築するフェーズです。

オントロジーOWL / Turtle 形式で保存され、Amazon Neptune のナレッジグラフに materialize されます。誘導処理では Amazon Bedrock 上の Claude がテーブルスキーマを解析し、エンティティ間のセマンティックな関係を推論します。

特徴的なのがグラウンディングです。新しく生成されたクラスを、FIBO(※1) などの読み込み済み基礎オントロジーや、そのネームスペースで過去に承認されたオントロジーの概念に整列させ、rdfs:subClassOfskos:*Matchリンクを生成します。既定値の ENHANCED モードでは LLM のリランカーがドメイン整合性を検証するため、名前だけでは拾えない意味的な一致を捕捉しつつ、「同名だが意味が違う」誤マッチ(例: Dublin Core の "Policy" と保険の "policy")を弾きます。

なお、グラウンディングが完了できない場合、システムは中途半端なオントロジーを返さずにジョブを failed にする設計になっています。「グラウンディング漏れ」が「本当にすべて新規概念だった」ように見えてしまう事態を避けるための、fail-loud な作りです。

メトリクスは、total_revenue = SUM(orders.total_amount) のような再利用可能なビジネス計算を SQL 式として定義するものです。Trino、PostgreSQL、Amazon Redshift など複数の SQL 方言を持たせられます。Open Semantic Interchange(OSI)v1.0 形式での一括インポートにも対応しています。

※1 FIBO: Financial Industry Business Ontology(金融業界ビジネス・オントロジー)の略で、EDM Council(Enterprise Data Management Council)が中心となって開発し、OMG(Object Management Group)が標準として採用している、金融ドメインの業界標準オントロジーです。

Serve フェーズ

ユーザーと AI エージェントがコンテキストを問い合わせるフェーズです。自然言語の質問に対して、精度の高い方法から順に試す 3 段階の解決戦略(Resolution Tier)を採ります。

  • Tier 1(メトリクス解決): 質問が定義済みメトリクス 1 件にだけ一致した場合、そのメトリクスの SQL 式を実行します。2 件以上一致した場合は曖昧と判断し、推測せずに Tier 2 へ落とします
  • Tier 2(構造化クエリ): オントロジーを介して NL → SPARQL → SQL に変換する VKG(Virtual Knowledge Graph、Ontop のマッピングを使用)と、カタログスキーマを使った直接の NL → SQL の 2 系統があります
  • Tier 3(ナレッジ検索): ベクトル検索とグラフ探索で関連コンテキストを集め、Amazon Bedrock で自然言語の回答を合成します

Tier 1・Tier 2 で生成された SQL は、実行前に必ず SQL Firewall を通ります。SELECT のみを許可し、ユーザーごとのテーブル許可リストとカラム拒否リストを適用する仕組みです。さらにその手前で Cedar による認可判定が入ります。

クエリの実行経路も自動で選ばれます。単一ソースかつ直接 SQL 可能なデータベースであればネイティブドライバで直接実行(おおよそ 20〜50 ミリ秒)、複数ソースをまたぐクエリや AWS Glue Data Catalog ソースは Amazon Athena フェデレーション(おおよそ 500〜800 ミリ秒)にフォールバックします。

エージェントからのアクセス

MCP サーバーは AgentCore Runtime 上で Streamable HTTP として動作し、以下 6 つのツールを公開します。

ツール 用途
list_metrics 定義済みメトリクスの一覧
describe_schema オントロジースキーマ(クラス・プロパティ・テーブル)の説明
query 自然言語でのネームスペース問い合わせ
translate_sparql 自然言語から SPARQL への変換
rag_retrieval 意味的に類似するドキュメントチャンクの取得
graph_traversal エンティティ関係を辿るセマンティックグラフ探索

注目したいのは認証モデルです。エージェント専用のマシン間クレデンシャルは存在せず、エージェントは常にユーザーの代理として動作します。Web アプリと同じ OIDC の 3LO(Authorization Code + PKCE)フローで取得したトークンを使い、そのユーザーに付与された権限の範囲内でしか動けません。監査ログに記録される principalId も、代理元ユーザーの ID になります。

AWS Context との関係

Context Ontology Accelerator を理解するうえで欠かせないのが、2026 年 6 月 17 日の AWS Summit New York City 2026 のキーノートで発表された AWS Context との関係です。

AWS Context は、既存データ全体のリレーションシップを自動的にナレッジグラフへマッピングし、エージェンティック検索を提供することで、組織内の AI エージェントがガバナンスされたデータリレーションシップ・ビジネスルール・ドメイン知識にランタイムでアクセスできるようにする新サービスです。Amazon Quick を支えるナレッジグラフ技術を、個人のグラフから組織横断のグラフへ拡張したものと説明されています。AWS Glue Data Catalog、Amazon SageMaker Unified Studio、AWS Lake Formation と統合され、コンテキスト層の主要要素は Apache Iceberg 形式で Amazon S3 に publish されます。

なお AWS Context は発表時点で "Coming soon" とされています。

両者の位置づけを整理すると以下のようになります。

観点 Context Ontology Accelerator AWS Context
提供形態 OSS(Apache 2.0、自身でデプロイ) マネージドサービス(Coming soon)
主な役割 業務オントロジーを人の承認つきで作り込む 既存データの関係を自動でナレッジグラフ化し、ランタイムで提供
発表日 2026 年 7 月 31 日 2026 年 6 月 17 日(AWS Summit New York City 2026)
今後 ユーザー定義オントロジー機能が AWS Context のネイティブ機能になる予定 Context Ontology Accelerator で作ったオントロジーを利用・管理できるようになる予定

つまり、いま Context Ontology Accelerator でオントロジー整備に着手しておけば、その資産を将来 AWS Context に引き継げるという建て付けです。裏を返すと、AWS Context を待たずに手を動かせる唯一の選択肢が現時点では Context Ontology Accelerator である、とも言えます。

やってみた

前提条件

検証環境は次のとおりです。

  • リージョン: us-east-1
  • タグ: v0.2.0(2026-08-13 リリース。v0.1.0 比で認可バイパスやクロスネームスペースのデータ漏洩を含む 17 件の修正が入っています)
  • AWS CLI: aws-cli/2.36.19
  • LLMは、Claude sonnet 5を使うように変更

システム構成

coa-dev-aws-architecture-全体構成.drawio

検証データの準備

題材は架空の産業機器商社です。FOREIGN KEY 制約を一切定義していない CSV を Glue のテーブルにして、AI がテーブル間の関係をどこまで推論できるかを見ます。あわせて、構造化データだけでは絶対に答えられない業務ルールを文書側に置きます。

order_id,customer_id,product_id,quantity,total_amount,order_date,status
5001,1,101,10,450000,2025-05-10,shipped
5002,1,104,25,212500,2025-05-18,shipped
5003,2,103,2,360000,2025-06-02,shipped
5004,3,102,4,248000,2025-06-21,pending
5005,4,105,1,240000,2025-07-01,shipped
5006,4,101,6,270000,2025-07-14,cancelled
5007,5,104,40,340000,2025-08-02,pending
5008,2,102,3,186000,2025-08-09,shipped
customer_id,customer_name,email,region,signup_date,loyalty_tier
1,佐藤商事,sato@example.co.jp,Kanto,2024-04-01,gold
2,鈴木物産,suzuki@example.co.jp,Kansai,2024-06-15,silver
3,高橋工業,takahashi@example.co.jp,Chubu,2025-01-20,bronze
4,田中製作所,tanaka@example.co.jp,Kanto,2025-03-05,gold
5,伊藤流通,ito@example.co.jp,Kyushu,2025-07-11,silver

業務文書のほうには、社内規程として売上の定義を書いておきます。抜粋です。

販売運用ポリシー(社内規程 SP-2025)

3. 売上計上の定義
「売上高(revenue)」は、状態が shipped である受注の total_amount の合計と定義する。
pending および cancelled の受注は売上高に含めない。この定義は全社共通であり、部門ごとの独自定義は認めない。

「地域別の売上高を教えて」と聞いたとき、この規程を知らなければ pending や cancelled まで数えてしまいます。

これらのデータは、S3 に置いて Glue のテーブルに定義しました。

% aws s3 ls s3://coa-blog-sample-123456789012-us-east-1 --recursive
2026-08-17 11:29:51       1267 docs/data-glossary.txt
2026-08-17 11:29:51       1536 docs/sales-policy.txt
2026-08-17 11:29:47        363 sample/customers/customers.csv
2026-08-17 11:29:49        389 sample/orders/orders.csv
2026-08-17 11:29:48        334 sample/products/products.csv

% aws glue get-tables --database-name coa_blog_sample \
  --query 'TableList[].[Name,length(StorageDescriptor.Columns)]' --output text
customers	6
orders	7
products	5

後で答え合わせができるよう、正解を Athena で先に出しておきます。社内規程どおり shipped だけを数えたものです。以下は、「出荷済み(shipped)の受注だけを対象に、顧客の地域ごとの受注件数と売上高を集計し、売上高の大きい順に並べる」クエリとその結果になります。

SELECT c.region, COUNT(*) AS order_count, SUM(CAST(o.total_amount AS BIGINT)) AS revenue
FROM coa_blog_sample.orders o
JOIN coa_blog_sample.customers c ON o.customer_id = c.customer_id
WHERE o.status = 'shipped'
GROUP BY c.region
ORDER BY revenue DESC
region order_count revenue
Kanto 3 902500
Kansai 2 546000

対照として、状態で絞らずに集計するとこうなります。

region order_count amount
Kanto 4 1172500
Kansai 2 546000
Kyushu 1 340000
Chubu 1 248000

Kanto が 30% 過大になり、本来は出てこない Kyushu と Chubu が現れます。SQL としてはどちらも正しく動くのに、業務的には片方だけが正解という状況を意図的に作りました。

検証用コストを削減するための CDK 変更

デプロイの前に、コストを見ておきます。公式のドキュメントには次の警告があります。

Cost warning: Neptune + OpenSearch Serverless cost ~$930/mo when idle.

アイドル状態で月 930 USDを削減するため、事前に何が効いているのかをコードを調査した結果、内訳はこうなりました。

ドライバー 既定値の定義 概算 USD/時
Amazon OpenSearch Serverless aoss_min_ocu の既定 2 が indexing と search の両方に適用され実質 4 OCU ~0.96
ontology-engine の Fargate 8 vCPU / 32 GB を常時 1 タスク ~0.47
Interface VPC エンドポイント 20 個 × 2 AZ = 40 ENI ~0.40
Amazon Neptune Serverless ではなく db.r8g.large のプロビジョンド 1 台 ~0.36
NAT Gateway natGateways: 1(既に最小) ~0.045
AWS WAF WebACL × 2 API 用(REGIONAL)と CloudFront 用 ~0.014

冗長構成を削る余地はほとんどありません。Neptune は既に単一インスタンス、NAT は 1 台、OpenSearch Serverless の standbyReplicas は NextGen コレクションの制約で ENABLED 固定、VPC は AgentCore と OpenSearch Serverless が使える AZ の交差条件で 2 AZ を下回れません。削減できるのはサイズだけです。

そこで検証用に 4 点だけ手を入れました。適用した差分です。

参考: v0.20 diff
diff --git a/infra/cdk.json b/infra/cdk.json
   "context": {
-    "env": "dev"
+    "env": "dev",
+    "aoss_min_ocu": 0
   }

diff --git a/infra/lib/stacks/foundation/storage-stack.ts b/infra/lib/stacks/foundation/storage-stack.ts
-      backupRetentionPeriod: 7,
+      // blog verification: 7 -> 1. Throwaway stack; minimises backup storage cost.
+      backupRetentionPeriod: 1,
-        dbInstanceClass: "db.r8g.large",
+        // blog verification: db.r8g.large -> db.t4g.medium.
+        // t3/t4g are Neptune's dev/test burstable classes (medium size only).
+        dbInstanceClass: "db.t4g.medium",

diff --git a/infra/lib/stacks/services/ontology-stack.ts b/infra/lib/stacks/services/ontology-stack.ts
-    const cpu = props.cpu ?? 8192;
-    const memoryLimitMiB = props.memoryLimitMiB ?? 32768;
+    // blog verification: 8192/32768 -> 2048/8192. The defaults above are sized
+    // for 20k-table induction; this run uses a handful of small documents.
+    const cpu = props.cpu ?? 2048;
+    const memoryLimitMiB = props.memoryLimitMiB ?? 8192;
-        LLM_MODEL_ID: "us.anthropic.claude-sonnet-4-6",
+        // blog verification: induction model pinned to Claude Sonnet 5.
+        LLM_MODEL_ID: "us.anthropic.claude-sonnet-5",
-    const rerankModelId = "us.anthropic.claude-sonnet-4-6"; // configured LLM_MODEL_ID
+    const rerankModelId = "us.anthropic.claude-sonnet-5"; // configured LLM_MODEL_ID

aoss_min_ocuscripts/deploy.sh の環境変数から CDK コンテキストへの変換対象に含まれていないため、SCL_ 系の環境変数では渡せません。infra/cdk.json に直接書く必要があります。

Interface VPC エンドポイントの 20 個には手を付けていません。AgentCore・OpenSearch Serverless・Bedrock・ECR など機能に直結するものが大半で、削るとデプロイ失敗や実行時エラーの原因になります。

なお LLM_MODEL_ID の変更はコスト削減ではありません。 誘導/自動生成に使うモデルの既定は Claude Sonnet 4.6 ですが、今回は Claude Sonnet 5 を使いたかったので併せて変更しています。Serve 側のモデルは既定が元から us.anthropic.claude-sonnet-5 なので、そちらは変更不要でした。

これで概算 約 0.73 USD/時まで下がります。CDK のユニットテストがインスタンスクラスや CPU 値を固定でアサートしているため、テスト側も追従させました。

デプロイ

make deploy-dev を実行します。内部では preflight → 全パッケージのビルド → cdk synthcdk deploy --all が走ります。

まず preflight です。

% make preflight
./scripts/preflight-deploy.sh
=== Pre-deploy preflight checks ===

  OK:  Node v22.23.2 found
  OK:  Java 25 found
  OK:  pnpm 10.30.3 found
  OK:  pip functional: pip 24.2 from ... (python 3.12)
  OK:  CDK_DOCKER=docker (explicit, daemon running)
  OK:  Smithy OpenAPI specs present (5 files)
  OK:  Authenticated to ECR Public (us-east-1)
  OK:  VPC headroom: 3/5 used in us-east-1
  OK:  Lambda concurrency headroom: 1000 unreserved, reserving 10 in us-east-1

Preflight passed.

ECR Public への認証を preflight が自動できました。ECR Public は us-east-1 でしか認証できないため、他リージョンにデプロイする場合でもここは us-east-1 を向きます。

SCL_SMUS_ADMIN_ARNS は SageMaker Unified Studio(Amazon DataZone)ドメインの管理者を指定する環境変数です。未設定のまま実行すると、deploy.sh は CDK を起動する前にエラーで停止しますので、設定しました。

% export SCL_SMUS_ADMIN_ARNS="arn:aws:iam::123456789012:role/cm-user"
% make deploy-dev
...
  Total time: 1576.07s

=== Deployment to dev complete ===

16 スタックすべてが揃ったことを確認します。

% aws cloudformation list-stacks --region us-east-1 \
  --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE \
  --query 'StackSummaries[?starts_with(StackName,`coa-dev`)].[StackName,StackStatus]' --output text | sort
coa-dev-api	CREATE_COMPLETE
coa-dev-auth	CREATE_COMPLETE
coa-dev-authnz	UPDATE_COMPLETE
coa-dev-data-layer	CREATE_COMPLETE
coa-dev-edge-waf	CREATE_COMPLETE
coa-dev-guardrail	CREATE_COMPLETE
coa-dev-mcp	CREATE_COMPLETE
coa-dev-metric-service	CREATE_COMPLETE
coa-dev-namespace	CREATE_COMPLETE
coa-dev-network	CREATE_COMPLETE
coa-dev-ontology	CREATE_COMPLETE
coa-dev-serve	CREATE_COMPLETE
coa-dev-sources	CREATE_COMPLETE
coa-dev-storage	CREATE_COMPLETE
coa-dev-vkg	CREATE_COMPLETE
coa-dev-web	CREATE_COMPLETE

所要時間は 1 時間 11 分でした。公式ドキュメントの「約 1.5 時間」とおおむね一致します。最も時間がかかるのは Amazon Neptune と Amazon OpenSearch Serverless を作る coa-dev-storage です。

認証の準備

COAのWeb アプリにサインインするユーザーを用意しますが、既定の初期管理者は nobody@amazon.com というプレースホルダーで、FORCE_CHANGE_PASSWORD のまま放置されます。一時パスワードのメールが届く先がないので、そのままではログインできません。

公式ドキュメントは「初回デプロイ前に SSM の /<prefix>/config にある initialAdminEmail を設定せよ」としています。今回は事後に気付いたので、検証用ユーザーを自分で作って回避しました。

まず、ユーザープールの ID と、これから作るユーザーの情報を変数に入れます。

% POOL=$(aws cloudformation describe-stacks --stack-name coa-dev-auth --region us-east-1 \
    --query "Stacks[0].Outputs[?OutputKey=='UserPoolId'].OutputValue|[0]" --output text)
% CLIENT_ID=$(aws cloudformation describe-stacks --stack-name coa-dev-auth --region us-east-1 \
    --query "Stacks[0].Outputs[?OutputKey=='UserPoolClientId'].OutputValue|[0]" --output text)
% USER="blog-verify@example.com"
% PW='<十分に長いパスワード>'
% aws cognito-idp admin-create-user --user-pool-id "$POOL" --username "$USER" \
  --user-attributes Name=email,Value="$USER" Name=email_verified,Value=true \
  --message-action SUPPRESS
% aws cognito-idp admin-set-user-password --user-pool-id "$POOL" --username "$USER" \
  --password "$PW" --permanent
% aws cognito-idp admin-add-user-to-group --user-pool-id "$POOL" --username "$USER" --group-name Admin

最後に、この後の REST API 呼び出しで使う API のエンドポイントID トークンを取得します。以降のコマンドに出てくる $API$TOKEN はこれです。

% API=$(aws cloudformation describe-stacks --stack-name coa-dev-api --region us-east-1 \
    --query "Stacks[0].Outputs[?OutputKey=='ApiEndpoint'].OutputValue|[0]" --output text)
% API="${API%/}"
% echo "$API"
https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/prod

% TOKEN=$(aws cognito-idp initiate-auth --region us-east-1 \
    --client-id "$CLIENT_ID" --auth-flow USER_PASSWORD_AUTH \
    --auth-parameters USERNAME="$USER",PASSWORD="$PW" \
    --query 'AuthenticationResult.IdToken' --output text)

アプリクライアントは ALLOW_USER_PASSWORD_AUTH が有効なので、ブラウザを介さずに ID トークンを取得できます。取得したトークンのクレームを覗くと、cognito:groupsAdmin が入っていることが確認できます。

{
  "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxxx",
  "token_use": "id",
  "cognito:groups": ["Admin"],
  "email": "blog-verify@example.com"
}

API Gateway の Lambda オーソライザーがこの cognito:groups を読んで platform-admin を付与する仕組みです。ID トークンの有効期限は 1 時間なので、検証が長引いたら取り直してください。

ネームスペースとデータソースの接続

Context Ontology Accelerator をデプロイすると自分のアカウントに立ち上がる エンドポイントに対してリクエストお送り、ネームスペースを作ります。

% curl -sS -X POST "$API/namespaces" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"name":"blog-demo","displayName":"Blog Verification Demo","owner":"blog-verify@example.com"}'
{"namespace": {"namespaceId": "41b32cbe-6399-41cd-a32a-2903743e5b90", "name": "blog-demo",
 "displayName": "Blog Verification Demo", "owner": "blog-verify@example.com",
 "status": "ACTIVE", "dataZoneProjectId": "6j5ef4iojcog87", "sourceCount": 0,
 "createdAt": "2026-08-17T03:43:04.195014+00:00",
 "athenaWorkgroupName": "coa-dev-41b32cbe-6399-41cd-a32a-2903743e5b90"}}

返ってきた namespaceId を以降で使うので変数に入れておきます。

% NS=41b32cbe-6399-41cd-a32a-2903743e5b90

ネームスペースを 1 つ作ると、裏で Amazon DataZone のプロジェクトと専用の Athena ワークグループが払い出されます。 クエリの実行環境までネームスペース単位で分離される設計です。

続いて Glue のデータソースを登録します。この時点では業務文書を登録しません。「構造化データだけでは答えられない」状態を後で画面で見せるためです。

% curl -sS -X POST "$API/namespaces/$NS/sources" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"sourceType":"DATABASE","databaseSource":{"name":"blog-sample-glue",
       "glueConfiguration":{"catalogId":"123456789012","region":"us-east-1",
       "databaseName":"coa_blog_sample"},"metadataEnrichmentEnabled":true}}'
{"sourceId": "c85b68a4-54ed-4209-97e8-f510b31c805f", "status": "REGISTERED",
 "scanJobId": "2026-08-17T03:43:21Z", "createdAt": 1786938201}

同じく sourceId を変数に入れます。

% SRC=c85b68a4-54ed-4209-97e8-f510b31c805f

登録すると自動でスキャンが始まります。状態は REGISTERED → SCANNING → ENRICHING → PENDING_REVIEW と遷移し、3 テーブル 18 カラムのスキャンと AI エンリッチが 50 秒で完了しました。

% curl -sS "$API/namespaces/$NS/sources/$SRC" -H "Authorization: Bearer $TOKEN" \
  | jq '{status, discovered: .databaseDetails.tablesDiscovered,
         approved: .databaseDetails.tablesApproved,
         engine: .databaseDetails.queryEngine,
         enrich: .databaseDetails.metadataEnrichmentEnabled,
         elapsed_sec: (.updatedAt - .createdAt)}'
{
  "status": "PENDING_REVIEW",
  "discovered": 3,
  "approved": 0,
  "engine": "ATHENA",
  "enrich": true,
  "elapsed_sec": 50
}

機能を画面で見る

ここからは Web アプリの画面を一通り操作します。オントロジーの誘導/自動生成・検証・承認はすべて画面から行い、REST API は同じ操作を裏側から確認する用途に回します。CloudFront のエンドポイントにアクセスし、先ほど作成した Cognito ユーザーでサインインします。

サインイン

20260731-coa-00-signin

サインインは Cognito のホスト UI に委譲されます。設定で外部 OIDC IdP(Okta / Microsoft Entra ID / Auth0 / Keycloak)に差し替えることもできますが、それは初回デプロイ前に決めておく必要がありますidpTypeOIDC にすると Cognito のユーザープール自体が作られません。

20260731-coa-01-home

サインインすると「The governed context layer for enterprise AI.」というホーム画面が表示されます。ヘッダー右側に現在のネームスペースを切り替えるセレクタがあり、その右にテーマ切り替え・設定・サインインユーザーが並びます。

左のナビゲーションは、アーキテクチャの 3 フェーズにそのまま対応した構成です。

グループ 項目
Scan Sources
Ontology Induction / Explorer / Metrics
Serve Playground
Administration Namespaces / Identity / System Health

上から順に使う設計になっており、ナビゲーションそのものが製品の全体像を表しています。

画面下部の「How it works」も Scan・Ontology・Serve の 3 列です。Scan は「Glue と SageMaker のカタログを指してテーブルとカラムを棚卸しし、AI が生成した業務コンテキストをレビュー用にプレビューする」、Serve は「すべてのリクエストがポリシー適用を通り、すべての判断がログに残る」と説明されています。人のレビューと監査を前提にした製品であることが、トップページの時点で明示されています。

Namespaces

20260731-coa-02-namespaces

「Namespaces partition the semantic graph into isolated scopes. Each namespace has its own data sources, ontology, and access policies.」と説明されているとおり、ネームスペースがマルチテナントの境界になります。部門ごと・ドメインごとに切る想定です。

API で作成した Blog Verification Demo が Sources 1 件・ACTIVE で並んでいます。作成時に裏で Amazon DataZone のプロジェクトと専用の Athena ワークグループが払い出される点は、先ほど API のレスポンスで確認したとおりです。

Sources

20260731-coa-03-sources

上部に Pending review 1 というステータス別のカウンタが出ます。一覧は All / Database / Documents のタブで絞り込めます。今回登録した blog-sample-glue(Database · Glue)が Pending review で待っている状態です。

20260731-coa-04-source-detail

ソース詳細の Source summary には Tables discovered 3 / Tables approved 0 / 3 と出ており、検出数と承認数が分けて表示されます。Metadata enrichment が Enabled であること、最終スキャン日時、Source ID も確認できます。

タブは Tables / Scan history / Settings の 3 つです。テーブル一覧には Columns 列に 0/6 0/7 0/5 というカウントが出ており、カラム単位でも承認状況が管理されていることがわかります。Enriched 列の AI_GENERATED バッジと、Review status 列の Pending review が対になっている点も、この製品の思想をよく表しています。

右上には Reject source / Approve source / Delete / Re-scan のボタンが並びます。

テーブル詳細 - メタデータのレビュー

20260731-coa-05-table-detail

ここが Scan フェーズの主役で、AI が生成した業務メタデータを人がレビューする画面です。

Table metadata には Description source が AI-generated であることが明示され、説明文のほかに Synonymsorder_transactions, purchase_orders, sales_orders)、Tagssales, transaction, customer, order_tracking)、Glossary termse-commerce, order management, transaction, fulfillment)が並びます。API のレスポンスでは JSON の入れ子として見ていたものが、画面では役割ごとに整理されて出てきます。そして注目したいのが Keys & relationships です。

制約を一切定義していない CSV から推論された関係が、AI_INFERRED バッジと確信度つきで表示されます。右上には Edit keys ボタンがあり、スチュワードが手で直せます。

20260731-coa-06-columns

下部の Columns セクションには「7 columns pending review — AI enrichment produced descriptions, synonyms, and glossary mappings for these columns. Review or edit them before approving.」という案内が出ます。カラムごとに Column / Data type / Description / Synonyms / Glossary / Tags / Sample values / Nullable / Description source / Confidence / Review status が横一列に並びます。

確信度はカラムによって差が付きます。

カラム Confidence AI が付けた説明
order_id 95% Unique identifier for each order transaction
quantity 94% Number of units ordered for the product
total_amount 94% Total monetary value of the order in local currency
order_date 93% Date and time when the order was placed
product_id 93% Unique identifier for the product or item ordered
customer_id 92% Unique identifier referencing the customer who placed the order
status 91% Current fulfillment or processing state of the order (e.g., pending, confirmed, shipped, delivered)

ここで右上の Approve table & all columns を押して承認します。3 テーブル 18 カラムをすべて承認したあと、ソース詳細に戻って Approve source を押すと、ソースの状態が PENDING_REVIEW から APPROVED に変わります。この承認を通していないと、次の induction には進めません。

Induction - オントロジー誘導/自動生成(Induction)

20260731-coa-07-induction

「Induce an ontology from your approved sources, review the proposal, then accept it to publish.」という説明のとおり、承認済みソースから誘導/自動生成し、提案をレビューして、承認して公開するという 3 段構えが画面上でも明示されています。

タブは Proposals と Reference ontologies の 2 つです。まだ何も誘導/自動生成していないので Proposals は 0 件です。右上に Open Explorer と Start induction のボタンがあります。

20260731-coa-08-induce-dialog

Start induction を押すと「Induce Ontology」ダイアログが開きます。入力項目は StrategyData sourcesGrounding ontologies(optional) の 3 つです。

Strategy は 2 択でした。

Strategy 説明(画面の原文)
Table to Ontology Maps relational tables → OWL classes, columns → properties. Best for structured databases.
Unstructured (Lexical Graph) Extracts concepts from document sources via NLP and builds a lexical knowledge graph. Exclusively for document sources.

グラウンディングの説明には「Pick the ontologies to ground against for this run. Accepted induced ontologies are pre-selected (deselect to skip).」とあり、承認済みの誘導/自動生成オントロジーが自動で選択される仕様が読み取れます。今回は初回なので何も選択肢がありません。

Table to Ontology のまま Data sources に blog-sample-glue を選んで Start induction を押します。誘導/自動生成は 2 秒で完了しました。

proposal - 生成結果の承認

20260731-coa-09-proposal-detail

「AI が起案し、人間が承認する」が具体的にどういう UI なのかが、ここに確認できます。Summary には Proposal ID・Status(Pending)・Type(Structured Induction)・Namespace・Created・Datasource(s)・Tables / columns(3 / 18)・Novel classes(3)が並びます。

その下の Proposal graph は、orders を頂点に product_idcustomer_id のラベル付きエッジが productscustomers に伸びています。先ほど AI が推論した外部キーが、そのままクラス間の関係として描かれています。凡例は Novel class / Grounded class / Relationship / Attribute の 4 種類です。

20260731-coa-10-proposal-classes

Proposed classes には 3 クラスが並びます。

Class Origin Relationships Attributes Matches
customers Novel 0 6 0
orders Novel 2 5 0
products Novel 0 5 0

orders だけ Relationships が 2 あるのは、外部キー 2 本が owl:ObjectProperty に関連するからです。今回は初回でグラウンディング対象が無いため、全クラスが NovelMatches は 0 です。

さらに下には Prefixes (shared) / R2RML Mapping / Ontology Source (Turtle) / SHACL Constraints (24 active) が折りたたみで並びます。R2RML と Turtle には Edit ボタンが付いていて、生成物そのものを画面上で直接編集できます

20260731-coa-11-2-validation

SHACL Constraints には Beta バッジと、Infer constraints / Validate / Export SHACL の 3 ボタンがあります。SHACL は RDF データの検証ルールを書く W3C 標準で、NOT NULL やデータ型から機械的に導けるものに加えて、LLM に意味的な制約を推論させるのが Infer constraints です。今回は自動生成された 24 件がアクティブになっていました。

validation - 3 層の検証(Validate)

20260731-coa-12-validation

画面上部の Validate を押すと検証が走ります。ボタンのツールチップに検証の中身がはっきり書かれています。

Read-only quality checks: reasoner consistency (HermiT), structural metrics, and design pitfalls (OoPS!). Doesn't change the proposal.

推論器による整合性検査・構造メトリクス・設計アンチパターン検出の 3 層であること、そして読み取り専用で proposal を変更しないことが明示されています。気軽に何度でも実行できます。

この 3 層は次のように定義されています。

バリデータ
tier1_blocking ConsistencyValidator(HermiT 推論器)/ TaxonomyCycleValidator / ConnectivityValidator / SHACLValidator / DatatypeTokenValidator
tier2_scoring StructuralMetricsValidator(OntoQA 系の構造メトリクス)
tier3_review OoPSValidator(OOPS! による設計アンチパターン検出)/ LabelCompletenessValidator / AmbiguousMatchValidator / CompetencyQuestionValidator

LLM が生成したオントロジーを推論器で機械的に検証できるという点が、形式オントロジーを採用していることの直接的な利点です。メトリクス定義型のセマンティックレイヤーには無い品質保証の層だと言えます。

検証を確認したうえで Accept proposal を押します。押すと「Accepting proposal… Merging into ontology graph (Neptune + AOSS + S3 + embeddings).」と表示され、状態が embeddings_sync を経て accepted に変わりました。所要 6 秒です。

Explorer — 生成されたクラスとグラフ

20260731-coa-13-explorer-classes

承認したオントロジーは Explorer で参照できます。「Browse the ontologies in this namespace, the classes inside them, and the sources they were induced from.」とあるとおり、Classes / Ontologies / Inducted sources の 3 タブ構成です。

20260731-coa-14-explorer-class-detail

行を選択するとクラス詳細のパネルが開きます。KindDescriptionSynonymsDefined in ontology に加えて、Relationships (2)Attributes (5) が並びます。Relationships には domain product_iddomain customer_id が入っており、外部キー由来の関係がここでも確認できます。

20260731-coa-15-explorer-graph

List / Graph の切り替えでグラフビューになります。ただし表示は 3 nodes · 0 edges で、円が 3 つ並ぶだけでした。画面下部には「double-click a class to expand its sub-classes」と出ます。関係が無いわけではありません。 同じクラスを選ぶと詳細パネルには Relationships (2) が並び、「Expand」から遷移するクラス詳細ページでは customer_id: Orders → Customersproduct_id: Orders → Products が表として表示されます。

線が引かれないのはグラフの初期ロードの作りによるものでした。GraphSearch.tsx を読むと、Graph ビューは初回表示のコストを下げるためにクラスごとの getClass 呼び出しをやめ、ontology-overview を 1 回叩いて頂点を組み立てます。このとき作られる頂点は partial フラグ付きで、rdfs:subClassOf しか持ちません

Vertices are flagged partial: they carry only the taxonomy, not the class's relationships/attributes, so the detail panel upgrades them via getClass when a node is selected.

描画側の buildGraphData は subClassOf 以外の関係も引ける作りになっているのですが、頂点がそのエッジを持っていないので描きようがないわけです。今回のオントロジーは 3 クラスすべてが Novel でフラット、継承関係がゼロなので、結果として 0 edges になりました。ノードを選択すると getClass で関係が読み込まれますが、それは詳細パネル側の更新であってグラフの頂点マップには戻らないため、選択しても線は増えません。

外部キー由来の関係を図として見たい場合は、先ほどの proposal 詳細の Proposal graph のほうが適しています。 あちらは Turtle を直接パースして描くので、orders から customersproducts へラベル付きのエッジが伸びていました。

20260731-coa-16-explorer-ontologies

Ontologies タブは棚卸し用で、All / Induced / Foundational / Uploaded で絞り込めます。今回のオントロジーは Classes 3・Properties 18・Axioms 178 でした。

Metrics - 指標の定義

20260731-coa-17-metrics

Metrics は「売上高とは何か」をガバナンス済みの定義として登録する画面です。定義済み指標は Serve の Tier 1 で最優先にマッチする建て付けなので、社内規程をここに落とし込みます。

今回は社内規程 SP-2025 に沿って total_revenue を定義しました。

  • Source: データソース blog-sample-glue / テーブル orders
  • Expressions: 方言ごとの SQL。Athena は TRINO 方言を選びます
  • AI Context: Synonyms(売上 / 売上高 / revenue / total revenue / 売上金額)、Instructions、Examples

Instructions には次のように書きました。

売上高は必ず status = 'shipped' の受注のみを対象とする。pending や cancelled を含めてはならない。この定義は社内規程 SP-2025 第 3 項による全社共通定義である。

「この指標をどう計算するか」だけでなく「ユーザーがどう呼ぶか」「AI がいつ使うべきか」まで書けるのがこの画面の特徴です。

なお API 経由で作る場合、式は完全な SELECT 文である必要がありますSUM(...) のような断片を渡すと、serve 時の SQL ファイアウォールが SELECT 文しか実行しないという理由で弾かれます。また作成リクエストは API Gateway の 29 秒制限に引っかかって 504 が返りましたが、バックエンドの処理自体は完了しており、GET /metrics で確認するとメトリクスは作成済みでした。

Playground - 自然言語問い合わせ

20260731-coa-18-playground-structured-only

Serve フェーズの入口が Playground です。「Ask a question against the governed surface...」という入力欄があり、右上に Standard と Agentic の切り替えと New chat ボタンが並びます。

ここで冒頭に用意した質問を投げます。

地域別の売上高を教えてください

結果は 4 行返ってきました。

Region Total Sales
Kanto 1172500.0
Kansai 546000.0
Kyushu 340000.0
Chubu 248000.0

Athena で先に出しておいた正解は Kanto 902,500 / Kansai 546,000 の 2 地域だけでした。Kanto が 30% 過大で、本来出ないはずの Kyushu と Chubu まで出ています。

「Compiled artifacts」を開くと、実行された SQL がそのまま表示されます。

SELECT
  c.region,
  COALESCE(SUM(CAST(o.total_amount AS DOUBLE)), 0) AS total_sales
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
GROUP BY c.region
ORDER BY total_sales DESC

原因は明快で、WHERE status = 'shipped' が無いためです。一方で JOIN 条件は正しく書けています。Glue のテーブルには FOREIGN KEY 制約が一切無いにもかかわらず、o.customer_id = c.customer_id で結合できているのは、AI が推論しオントロジーの owl:ObjectProperty になった関係が効いているからです。

構造は分かっているが、業務ルールは知らない。 これが「クエリは成功するのに答えが間違っている」という、最も気付きにくい失敗の正体です。

なお、画面で試したのと同じ問い合わせは REST API からも投げられます。エンドポイントは POST /namespaces/{namespaceId}/query です。

% curl -sS -X POST "$API/namespaces/$NS/query" -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -d '{"query":"地域別の売上高を教えてください"}' \
  | jq '.result | {tier, resultRows, queryUsed}'

ここで 1 つ注意点があります。自然言語の質問を渡すフィールド名は query です。text という名前で送ると弾かれます。

% curl -sS -X POST "$API/namespaces/$NS/query" ... -d '{"text":"地域別の売上高を教えてください"}'
{"message": "Missing required field: query"}
<<HTTP 400>>

Smithy の定義でも、Data Layer の Query オペレーションは query: String@required としています。レスポンスは result の下にネストされ、tier / resultRows / queryUsed / trace が入ります。画面の Rationale パネルで見た解決トレースは、この trace 配列と同じ内容です。

ただし REST API には API Gateway の 29 秒制限があります。Tier 3 まで落ちる質問は 30 秒を超えることがあるため、重い問い合わせは Playground のストリーミング経路を使うのが前提になっています。

解決トレース — なぜその Tier になったのか

20260731-coa-19-trace-tier2

回答の「Show trace」を押すと、右側に Rationale パネルが開きます。Tier 構造を理解するのに最も有用な画面です。

1 つ目は Tier 1 がスキップされていることです。No matching metric と出ています。total_revenue というメトリクスを登録済みなのですが、「地域別の」という切り口はスカラー値のメトリクスでは表現できないため、Tier 2 に落ちるのは妥当な判断です。

2 つ目は Model が us.anthropic.claude-sonnet-5 であることです。Serve 側のモデル指定が効いていることが画面から確認できます。

3 つ目が最も興味深く、1 回目の Generate SQL が 0 行で Error になり、SQL を作り直して 2 回目で 4 行を得ている点です。自己修正のループが組み込まれていることがトレースから読み取れます。ただし作り直した SQL も status で絞っていないため、業務的には誤答のままです。

Boundary controls の 3 つ(Cedar によるアクセス制御・SQL ファイアウォール・Bedrock ガードレール)が毎回評価されて記録される点も、監査を前提にした設計を示しています。

ソースを追加する — 業務文書を接続する

さて、社内規程を COA に教えたらどうなるでしょうか。業務文書を画面から追加します。

20260731-coa-20-connect-source

Sources の右上にある「Connect source」を押すと、4 ステップのウィザードが開きます。まず種別を Glue database / JDBC database / Documents から選びます。

20260731-coa-21-connect-source-s3

Documents を選ぶとステップが 3 つに減り、Upload files と S3 bucket のタブが出ます。Upload files は PDF / DOCX / TXT / Markdown を最大 100 ファイルまで直接アップロードでき、S3 bucket はバケット ARN とプレフィックスを指定する方式です。今回は S3 を選び、docs/ プレフィックスを指定しました。

設定画面にパスワードを直接入力する欄が無いのがこの製品の特徴です。JDBC を選んだ場合も認証情報は Secrets Manager の ARN 指定で、COA 側に資格情報を保存しない設計になっています。

20260731-coa-22-sources-with-docs

登録すると自動で取り込みが始まり、SCANNING → SCANNING_ENTITY_EXTRACTION → COMPLETED と遷移しました。2 ファイル・5 チャンクの取り込みに 204 秒かかっています。

filesTotal 2 / documentsProcessed 2 / chunksLLM 5 / chunksEmbed 5 / chunksGraph 5

Sources 一覧のカウンタが Approved 1 / Completed 1 となっている点に注目してください。構造化ソースは承認フローを通るので Approved、ドキュメントソースは取り込み完了で Completed と、種類によって終端のステータスが異なります

Playground - 自然言語問い合わせ(同じ質問の答えは変わるか)

業務文書が入ったので、まったく同じ質問を投げ直します。

地域別の売上高を教えてください

結果は……まったく同じでした。Kanto 1,172,500 / Kansai 546,000 / Kyushu 340,000 / Chubu 248,000 で、解決も Tier 2、生成 SQL も status で絞っていません。

念のため、メトリクスに登録した想定質問例と一字一句同じ文も試しました。

売上高はいくらですか

これも Tier 1 は No matching metric でスキップされ、Tier 2 が 2,306,500(全 8 件の合計)を返しました。正解は shipped のみの 1,448,500 です。

同義語に「売上高」を、想定質問例にこの文そのものを登録してあるのに、なぜ当たらないのか。ここには日本語特有の落とし穴がありました。 同じチャットで、今度は「売上高」という単語だけを投げてみます。

20260731-coa-27-playground-tier1-hit

答えが変わりました。 上が 2,306,500、下が 1,448,500 です。実行された SQL を見比べると違いは明白です。

質問 実行された SQL 結果
売上高はいくらですか SELECT COALESCE(SUM(CAST(o.total_amount AS DOUBLE)), 0) AS total_sales FROM orders o 2,306,500
売上高 SELECT SUM(CAST(total_amount AS BIGINT)) AS total_revenue FROM coa_blog_sample.orders WHERE status = 'shipped' 1,448,500

下の SQL は LLM が生成したものではありません。私が Metrics 画面で登録したガバナンス済みの定義そのものです。結果の列名も total_sales ではなく Total Revenue になっています。

トレースを開くと、何が起きたかがはっきりします。

20260731-coa-28-trace-tier1

Confidence が 100%、根拠は Deterministic metric: total_revenue LLM に SQL を書かせる Tier 2 の 90% とは意味が違い、こちらは決定的です。レイテンシも Tier 2 の 8.9 秒、Tier 3 の 36.2 秒に対して 1.8 秒と桁違いに速く、Match metric は 0ms で解決しています。

英語で聞いた場合も同じく Tier 1 が当たり、matchSourcename(メトリクス名そのもの)になりました。

では、なぜ「売上高はいくらですか」だと外れるのか。原因は Tier 1 のマッチング実装にありました。

# packages/context-manager/src/coa_serve/tier1/metric_resolver.py
escaped = re.escape(name).replace("_", r"[\s_]")
return re.compile(rf"\b{escaped}\b")

メトリクス名と同義語を \b(単語境界)で囲んだ正規表現にしてから、クエリ文字列に対して search() しています。同じロジックを手元で再現すると次のようになりました。

クエリ 売上高 revenue / total revenue
売上高はいくらですか
売上高 一致
今期の売上を教えて
what is the total revenue? 一致
売上高 はいくらですか(スペースを 1 つ挿入) 一致

'売上高は'\b が立つ位置は文字列の両端だけです。「高」も「は」も Python の Unicode 定義では \w に含まれるため、その間に単語境界が生まれません。 一方 'total revenue?' は空白と ? のところに境界が立ちます。

\b空白で語を区切る言語を前提にした仕組みなので、助詞が直接くっつく日本語では、同義語が文中に現れた瞬間にマッチしなくなります。スペースを 1 つ入れるだけで当たることが、その裏付けになっています。

なお Tier 1 は意味検索ではありません。実装のコメントにも「exact name/synonym matching」「fuzzy matching is a typo/plural/abbreviation safety net, NOT a semantic search」と明記されています。索引は by_nameby_synonym だけで、aiContext.examples は Tier 1 のマッチには使われません。想定質問例は下流のティアや AI 向けの補助情報という位置づけです。

日本語環境での実務的な回避策は 2 つです。同義語に助詞込みの表現(「売上高は」「売上高を」など)を登録しておくか、利用者が単語で問い合わせる運用にすることです。

では業務文書は無駄だったのかというと、そうではありません。聞き方を変えると Tier 3 が正しく答えます。

Tier 3 で業務文書を引用した回答

売上高は社内規程でどう定義されていますか

この質問には、日本語で次のように答えました。

社内文書「sales-policy.txt」の「Sales Policy Order Status and Revenue Definition」に基づくと、売上高は以下のように定義されています。
定義:売上高は、状態が「shipped(発送済み)」である全ての注文の total amount(合計金額)の合計として定義されます。
除外対象:「pending(保留中)」状態の注文は売上高に含まれません。「cancelled(キャンセル済み)」状態の注文も売上高に含まれません。

さらに、カタログに登録されたメトリクス total_revenue の定義とも一致していることdata-glossary.txt の記述とも整合が取れていることを、モデルが自分で突き合わせて報告しています。回答の下部には「2 sources cited」と出ます。

Tier 3 の解決トレース

この回答のトレースが、Tier 1 → 2 → 3 のカスケード全体が 1 画面に収まった貴重な例です。

Tier 2 の中がさらに NL→SQLVKG (Ontop) の 2 経路に分かれていることがわかります。定義を問う質問なので NL→SQL は SQL ファイアウォールに blocked され、次に VKG が自然言語から SPARQL を生成(confidence 0.10)して Ontop で SQL に変換し実行しましたが 0 行。そこでようやく Tier 3 に落ちて、ベクトル検索で 2 チャンクを引き当てて合成した、という流れです。

Tier 3(知識検索)は業務文書を確実に参照するのに、Tier 2(NL→SQL)は参照しない。 これが今回いちばんはっきり見えた境界でした。

System Health

20260731-coa-24-system-health

各コンポーネントの稼働状況をまとめて確認できる画面です。「Real-time health status of all backend storage and AI services」とあり、Storage Backends(DynamoDB / Neptune KG / OpenSearch Serverless)と Ontology Induction(Ontology Graph Store / Ontology Vector Store / Bedrock Embeddings / Description LLM)が並びます。

考察

AI によるキー推論は期待以上でした

FOREIGN KEY 制約を一切持たない CSV ベースの Glue テーブルから、主キー 1 本と外部キー 2 本が確信度 0.95 で、しかも正しく推論されました。生成されたオントロジーでは owl:ObjectProperty に昇格し、scl:fkProvenance "AI_INFERRED" という注釈が残ります。実際この推論のおかげで、Playground の自然言語クエリが JOIN customers c ON o.customer_id = c.customer_id を正しく書けていました。スキーマに書かれていない関係を復元してクエリを通すという点では、明確に価値が出ています。

人のレビューを挟む設計は API レベルで強制されています。

テーブルとカラムは PENDING_REVIEW で生成され、承認するまで induction に進めません。承認前にメトリクスを作ろうとすると HTTP 400 で弾かれました。誘導/自動生成したオントロジーも pending の proposal として止まり、Accept proposal を押すまで Neptune には入りません。AI の出力が人の確認を経ずに下流へ流れ込む経路が塞がれているのは、この製品のいちばんの主張だと思います。

推論器による機械検証は形式オントロジーならではの層です

HermiT で論理的整合性を検査し、充足不可能なクラスが無いことを確認できる。構造メトリクスと OOPS! による設計アンチパターン検出まで含めた 3 層が、ボタン 1 つで、しかも proposal を変更しない読み取り専用で走ります。メトリクス定義型のセマンティックレイヤーには無い品質保証だと言えます。

一方で、業務ルールは Tier 2 に届きませんでした

これが今回いちばんの発見です。「売上高 = shipped の合計」という社内規程を文書として取り込み、ベクトルストアにもナレッジグラフにも載った状態で、それでも「地域別の売上高」への回答は WHERE status = 'shipped' の無い SQL のままでした。文書登録の前後で答えは 1 バイトも変わりません。

聞き方を「売上高は社内規程でどう定義されていますか」に変えると Tier 3 が起動し、sales-policy.txt を引用して正しい定義を答え、しかもメトリクス定義や用語集との整合まで自分で突き合わせてきます。知識としては確かに入っているのに、数値を計算する経路からは参照されていない。 Tier 2 が見るのはオントロジーとスキーマであって、文書ではないからです。

Tier 1 は設計どおり動きますが、日本語では当たりにくいです

「売上高はいくらですか」では外れる一方、「売上高」という単語だけ、あるいは英語の "What is the total revenue?" なら Tier 1 が confidence 1.0 で当たり、正解の 1,448,500 が返ります。原因はマッチングが \b(単語境界)付きの正規表現である点で、空白で語を区切らない日本語では助詞が付いた瞬間に境界が消えます。製品が壊れているわけではなく、i18n の考慮が及んでいないという話です。日本語で運用するなら、同義語に助詞込みの表現を登録しておくのが現実的な回避策になります。

そしてここが当たると、ガバナンス済み指標の価値がはっきり出ます。 実行されるのは登録した SQL そのもの、つまり WHERE status = 'shipped' を含む社内規程どおりの式です。Tier 2 の生成 SQL が業務ルールを落としてしまうのに対し、Tier 1 は定義を決定的に再現します。「重要な指標は Tier 1 に載せる」のがこの製品の正しい使い方だと言えます。

解決トレースの情報量は非常に高いです

Tier 1 → 2 → 3 のどこを通ったか、各ステップが何ミリ秒かかったか、Cedar と SQL ファイアウォールと Bedrock ガードレールがどう判定したかが、1 画面に時系列で並びます。Tier 2 の内部が NL→SQL と VKG(Ontop)の 2 経路に分かれていることも、SQL ファイアウォールが危険なクエリを blocked にして VKG にフォールバックする様子も見て取れました。「Tier 1 で拾ってほしかったのに Tier 2 に落ちた → メトリクス定義か同義語を見直す」という改善サイクルを回すための材料が、そのまま画面に出ています。

コスト設計に手が入る余地は限られています

CDK コンテキストで変えられるのは実質 aoss_min_ocu だけで、Neptune のインスタンスクラスも ontology-engine の Fargate サイズも、コードを直接編集しないと下げられません。既定のままだとアイドルで月 930 USD という水準なので、検証用途では編集がほぼ必須になります。今回の削減で約 0.73 USD/時、実際に 2 時間弱の稼働で 1.5 USD 程度に収まりました。

今後に期待したい点

  • Tier 1 の同義語マッチを日本語などの非空白区切り言語に対応させること。\b ベースの単語境界では助詞が付いた時点で外れる
  • 業務文書に書かれたルールを Tier 2 の SQL 生成に反映する経路。せめて「この質問には status のフィルタが要る」というヒントだけでも伝わってほしい
  • コスト調整をコード編集なしで行えるようにする(Neptune のクラス、Fargate のサイズを CDK コンテキストに開放する)
  • us-east-1 以外での検証済みリージョンの拡大
  • AgentCore ENI の解放待ちを短縮するか、destroy.sh が高額リソースを先に落とすオプションを持つこと

最後に

Context Ontology Accelerator の価値

今回の検証で見えた Context Ontology Accelerator の価値は、AI に SQL を書かせることそのものではありませんでした。 データと業務用語の間にある関係と意味を、人がレビューできる形でモデル化し、そのうえで AI の判断を制御できることにあります。FOREIGN KEY 制約を持たない CSV から関係が推論され、生成された OWL に scl:fkProvenance "AI_INFERRED" という出自の注釈が残る。この「誰が言い出した関係なのか」が資産に刻まれることが、後から効いてきます。

では、なぜ今オントロジーなのか。

オントロジーは、セマンティックレイヤーや text-to-SQL、RAG、データカタログを置き換えるものではありません。定義済み指標を正確に届けるのはセマンティックレイヤーが得意ですし、規程や定義書を根拠として提示するのは RAG の役割です。text-to-SQL はスキーマから SQL を組み立てられますが、今回の WHERE status = 'shipped' の欠落が示すとおり、もっともらしいのに業務的には誤った条件を書いてしまうことがあります。データカタログは資産の発見と説明には有用でも、用語と列とテーブルと制約を機械推論できる形で保持するところまでは担いません。オントロジーがこれまで解けなかった問題を解くとすれば、それは個別に最適化されてきた「定義」「根拠」「関係」「実行」を、ひとつの意味モデルの上で結び直し、検証と承認の対象にできるようにした点だと考えます。

関係を推論できることと、業務的に正しい答えが返ることは別

ただし、関係を推論できることと、業務的に正しい答えが返ることは別です。 今回は社内規程を文書として取り込んでも Tier 2 の集計は変わらず、日本語では同義語に助詞が付いた時点でメトリクスに当たらなくなりました。オントロジーは万能薬ではありません。だからこそ承認フローがあり、推論器による検証があり、ガバナンス済み指標があるのだと理解しました。どこを AI の推論に委ね、どこを決定論的に固定するかを設計するための基盤である、という受け止め方が実態に近いと思います。

この分担は、AWS 自身が示している設計思想でもあります。 AWS Prescriptive Guidance は、自律型エージェントに必要な監査可能な推論について「検索と確率的モデルだけでは提供できない能力」だとしたうえで、LLM と記号推論の役割をこう整理しています。

The architecture orchestrates both: LLMs propose candidate knowledge, symbolic reasoners validate and refine it.

今回たどった経路は、まさにこのとおりでした。AI が外部キーの候補を出し、人が画面で承認し、HermiT が論理的整合性を検証し、確定した定義は Tier 1 が決定的に実行する。Context Ontology Accelerator は完成した万能プロダクトというより、AI 時代のデータ活用に必要な部品を実際に組み合わせて確かめられるリファレンス実装だと言えます。オントロジーという概念自体は新しくありませんが、AI に下書きさせ、人が承認し、推論器で検証してからナレッジグラフに載せるところまでを一気通貫で動かせる形で示した点に意義があります。

Context Ontology Accelerator が示すオントロジーの今後

そしてこの先には、マネージドサービスの AWS Context が控えています。 AWS Context はデータから関係を自動で見つけるボトムアップの層、Context Ontology Accelerator は人が業務上の意味を定義するトップダウンの層であり、両者は競合ではなく補い合う関係です。AWS は、Context Ontology Accelerator のマネージドなユーザー定義オントロジー機能が AWS Context のネイティブなフルマネージド機能になり、ここで作り始めたオントロジーを後から AWS Context で利用・管理できるようになるとしています。ただし AWS Context は執筆時点で Coming soon であり、移行の具体的な手段は公開されていません。自動発見だけでも、人手の定義だけでも足りない。 両者を行き来しながら業務上の意味を運用可能な資産に育てていくことが、これから求められるのだと思います。Apache 2.0 で公開されている以上、その予行演習を今日から自社のデータで始められます。この記事がどなたかのお役に立てば幸いです。

合わせて読みたい

https://aws.amazon.com/jp/about-aws/whats-new/2026/07/aws-context--ontology-accelarator-generally-available/

https://github.com/aws/context-ontology-accelerator

https://aws.github.io/context-ontology-accelerator/

https://aws.amazon.com/jp/blogs/machine-learning/context-intelligence-for-your-data-and-ai-agents-at-scale/

https://zenn.dev/aws_japan/articles/59b38ac7ff29fe

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事