---
title: "SotaAgents — ユーザーマニュアル"
description: "チャットでの AI 活用から、Capability の利用、アプリの開発・インストール、組織の管理まで、必要な情報をまとめたマニュアルです。"
url: "https://sotaagents.ai/ja/manual"
generated_by: "sotaagents-ldp"
docs_index: "https://sotaagents.ai/manual/llms.txt"
locale: "ja"
---

# SotaAgents — ユーザーマニュアル

## はじめに

SotaAgents の概要と基本概念を理解し、初めてのサインインを行います。

### 概要

SotaAgents はチャットを中心とした AI ワークスペースです。サインインしてワークスペースを選び、質問を入力するだけで、アシスタントがチームのドキュメントを参照し、ファイルを生成し、Web を検索し、接続済みのツールを呼び出して回答します。ホーム画面の中央には入力ボックスが表示されます。

![中央に入力ボックス、サイドバーに workspace 切り替えと最近の会話がある SotaAgents のホーム画面](/manual/assets/product/chat-home-20260813.webp)
_ホーム画面：入力ボックスが一つ、左に workspace と最近の会話。_

組織のオーナーと管理者は、**管理コンソール（Admin Console）**からプラットフォームを管理します。ワークスペースの作成、アプリのインストール、クレジット管理、監査ログの確認などを行う専用エリアです。

### 基本概念

### 組織（Organization）

会社に相当する単位です。請求、メンバー、クレジットを保持します。ユーザーは 1 つ以上の組織に所属できます。

### ワークスペース（Workspace）

組織内のチーム用スペースです。会話、ファイル、インテグレーション、MCP サーバー、インストール済みアプリを保持します。サイドバー上部のセレクターで切り替えます。

### 機能（Capability）

メッセージに追加するショートカットです。Generate Image、Create Slides、Write Doc、Search Web などがあります。チャット入力欄で `/` を入力すると一覧が開きます。

### 会話（Conversation）

チャットのスレッドです。すべての会話はサイドバーに日付ごとに表示され、プロジェクトに整理できます。

### プロジェクト（Project）

関連する会話をまとめるグループです。共有インストラクション、コンテキストファイル、メンバーを任意で設定できます。サイドバーの Projects ページから作成します。

### アーティファクト（Artifact）

アシスタントが生成・引用するファイルです。生成された .docx、画像、引用元の PDF などが該当し、チャット横のアーティファクトパネルに表示されます。

### アプリ（App）

組織に専門機能を追加するインストール型の拡張です（Knowledge Base・Office App・Web Search・CAD・Remagine）。管理者が管理コンソールの App Store からインストールします。

### API キー（API Key）

承認済みの machine-to-machine 統合用の資格情報です。組み込みの Public Deployment はブラウザーに組織 API キーを置かず、制限付き guest session を使用します。

### インテグレーション（Integration）

Knowledge Base アプリが提供する任意の connector です。利用可否や provider は、アプリの導入・workspace での有効化・tenant 設定に依存します。

### MCP サーバー（MCP server）

管理者が設定するツールのプラグインです。接続すると、アシスタントが会話の途中でそれらのツールを使い、ユーザーに代わって操作を実行できます。

### サインイン

![メール先行ログインとソーシャルログイン選択肢を表示する SotaAgents サインインページ](/manual/assets/product/auth-login-20260813.webp)
_最初にメールを入力すると、そのアカウントで許可されたサインイン方法が表示されます。_

SotaAgents は 4 つの認証方法に対応しています：**メールアドレス + パスワード**、**Google SSO**、**Microsoft SSO**、**Apple SSO**。

1. #### サインインページを開く

   [https://app.sotaagents.ai/](https://app.sotaagents.ai/) にアクセスします。

2. #### 認証方法を選ぶ

   - **メールアドレスとパスワード** — 登録済みのメールアドレスとパスワードを入力し、「Sign in」をクリックします。
   - **Google SSO** — 「Continue with Google」をクリックし、Google アカウントで認証します。
   - **Microsoft SSO** — 「Continue with Microsoft」をクリックし、Microsoft アカウントで認証します。
   - **Apple SSO** — 「Continue with Apple」をクリックし、Apple アカウントで認証します。

3. #### パスワードを忘れた場合

   サインインページの「Forgot password?」をクリックし、メールアドレスを入力すると、パスワード再設定用のリンクがメールで届きます。リンクを開いて新しいパスワードを設定してください。パスワードの再設定はセルフサービスで完結し、管理者の対応は不要です。

4. #### サインイン状態の維持

   SotaAgents はセッションを自動的に維持します。共用端末で利用した場合は、作業後にサイドバー下部のアカウントメニューから「Sign out」を実行してください。

5. #### アカウントを作成する

   アカウントがない場合は _Register_ を選び、名前・メールアドレス・パスワードを入力してメールを確認します。登録はユーザーアカウントを作成しますが、未所属の組織や workspace へ参加するには招待が必要です。

対応する native desktop/mobile build は、system browser で OAuth を開き、90 秒で失効する 1 回限りの PKCE code を app callback で交換します。Callback が失敗・失効・使用済みになった場合、古い link や code は再利用せず app から sign-in を最初からやり直してください。利用可否は deployment によって異なります。

> [!WARNING]
> サインインできない場合
>
> メール確認と登録時と同じ認証方法を確認してください。サインインできても tenant が表示されない場合は、その組織または workspace の管理者に招待を依頼してください。

認証後にワークスペース画面が表示されます。サイドバー上部の workspace セレクターで workspace を切り替えます。

### 最初の会話

1. #### AI モデル・Speed・Reasoning Effort を選ぶ

   タスクに応じて、AI モデル、Speed、Reasoning Effort を選択します。

   - **Reasoning Effort** — 応答を生成する前の推論の深さを制御します。高くするほど詳細な応答になりますが、処理時間が長くなります。
   - **Speed** — ルーティングを変更します。`Standard`（既定）は品質を優先し、`Fast` はスループットを優先します。Fast に 1.5 倍の追加料金はありません。

   > [!NOTE]
   > **推奨**特別な要件がない場合は、既定の設定を推奨します。

![Composer で開いた model セレクター。利用可能な Claude と Gemini model と credit 倍率が並ぶ](/manual/assets/product/chat-model-settings-20260813.webp)
_利用可能な各 model に credit 倍率が表示され、選ぶ前にコストが分かります。_

2. #### リクエストを入力する

   リクエストは、質問として入力するか、**目的**・**背景（コンテキスト）**・**希望する出力形式**を明示した構造的な説明として入力します。

![中央にリクエスト入力欄があるホーム画面](/manual/assets/product/chat-home-20260813.webp)
_ここにリクエストを入力します。下の操作は会話に紐づきます。_

3. #### 結果を確認して続ける

   応答を確認し、必要に応じて修正を依頼します。その後、出力ファイルをダウンロードするか、会話を続けて結果をさらに調整します。

![質問、整形された回答、消費 credit、返信 composer を示す会話](/manual/assets/product/chat-conversation-20260813.webp)
_回答には固有の操作と消費 credit が付きます。同じスレッドで返信して精度を上げます。_

4. #### ファイルを添付する（必要な場合）

   チャット入力バーの **(+)** から添付します。ファイルは Core に保存され会話に紐づきますが、Knowledge Base への自動取り込みや OCR は保証されません。

   - **形式：**現在の uploader が受け付ける画像、PDF、一般的な文書
   - **上限：**1 メッセージ 20 件、1 会話 100 件、1 ファイル 100 MB

### 利用できる機能（Capability）

画像・スライド・文書・シート/PDF・図・サイトの生成、Web 検索、導入済み app の tool 呼び出しに対応します。実際の機能は workspace の app と policy に依存します。Slash directive は次に送るメッセージだけに適用され、会話中ずっと続くスイッチではありません。

通常の質問では、その run で利用可能な tool をアシスタントが選ぶことがあります。Knowledge Base と Web 検索は保証された既定動作ではないため、根拠が必要な場合は capability または情報源を明示してください。

| 機能 | アシスタントが生成するもの |
| --- | --- |
| Search Knowledge Base | ワークスペースにインデックスされたドキュメントを対象に、セマンティック + 全文のハイブリッド検索を実行します。利用できるのは Knowledge Base app が導入・有効化され、run で選択された場合です。結果には利用可能な引用が付きます。 |
| Search Web | 最新の Web 上で回答を検索し、出典を引用します。 |
| Create Slides | トピックやアウトラインからプレゼンテーション一式を作成します。エクスポート前にデッキエディターで編集できます。 |
| Write Doc | 見出しと書式を備えた `.docx` 文書 — レポート、メモ、ブリーフなど。 |
| Create Sheet | 数式・グラフ・書式を備えた `.xlsx` スプレッドシート。 |
| Create PDF | レイアウトが固定された仕上がりの PDF — 契約書、データシート、1 枚ものの資料。 |
| Generate Image | テキストプロンプトからの画像 — イラスト、モックアップ、バナー。 |
| Draw Diagram | 説明文からのフローチャートやプロセス図。 |
| Build Site | 要件からの小規模な Web ページ。HTML としてエクスポートされます。 |

### 利用できる機能

機能（Capability）は、アシスタントに生成してほしい出力の種類を指定するものです。チャット入力欄で `/` を入力すると一覧が開き、選択した機能が送信前のメッセージに追加されます。

### 各 capability の詳細

### Search Knowledge Base

導入・有効化された Knowledge Base app の indexed document を検索します。検索方式、OCR、connector、引用は app と provider 設定に依存します。Web 検索も Knowledge Base も全リクエストの既定ではなく、Slash directive は送信する 1 メッセージにだけ適用されます。

社内ドキュメント

ハイブリッド（ベクトル + 全文）検索

引用付き

> [!NOTE]
> **サンプルプロンプト**「社内ドキュメントから [トピック] に関する情報を探してください。最も関連性の高いセクションの要点を要約し、出典ドキュメント名を含めてください。」

### Search Web

社内データにない情報源について、インターネット上の公開されている最新情報を検索します。標準の Web 検索、ニュース検索、画像検索、ページ全文の抽出に対応します。すべての回答に出典リンクが引用されます。

インターネット検索

ニュース検索対応

出典リンクを引用

> [!NOTE]
> **サンプルプロンプト**「[トピックと期間] について [検索の目的] を調べてください。[情報源の範囲] をもとに [含めたい内容] を要約し [範囲]、主要な数値と公式な出典の引用を含む簡潔な箇条書きで返してください [出力形式]。」

### Document Generation（DOCX · Excel · PDF · PPTX）

自然言語のリクエストから、文書・スプレッドシート・PDF・プレゼンテーションを作成します。ファイルは Office アプリによって生成され、必要に応じて Gotenberg で PDF に変換されます。

**Write Doc**・**Create Sheet**・**Create PDF**・**Create Slides** の各機能をカバーします。

DOCX · EXCEL · PDF · PPTX

ダウンロード + 編集可能

> [!NOTE]
> **DOCX**「[文書の目的] のための DOCX ファイルを作成してください [形式]。[内容]。見出し 1 / 2 の明確な階層、箇条書き、サマリー表を使ったプロフェッショナルな書式にしてください [体裁]。」

> [!NOTE]
> **EXCEL**「[計算 / 管理の目的] のための Excel ファイルを作成してください [形式]。[内容]。[指標] を自動計算する数式、[データ] を可視化するグラフ、[条件] を強調表示する条件付き書式を含めてください [体裁]。」

> [!NOTE]
> **PDF**「[文書の目的] のための PDF ファイルを作成してください [形式]。[内容]。[対象読者] に適した [カラートーン] の、クリーンでミニマルなデザインにしてください [体裁]。」

> [!NOTE]
> **PPTX（スライド）**「[対象読者] 向けに、[トピック] に関する [枚数] 枚のスライドレポートを作成してください [内容]。[要点] をカバーし、[ブランドカラー] を使った [フォーマル / モダン / ミニマル] なスタイルにしてください。[スタイル]」

### Generate Image

自然言語の説明からイラストや画像を作成します。

> [!NOTE]
> **サンプルプロンプト**「[被写体とシーン] の画像を作成してください [内容]。[アート / 写真 / 3D レンダリング] のスタイル、[カラーパレットと雰囲気] で [スタイル]、アスペクト比は [1:1 / 16:9] にしてください [比率]。」

### Draw Diagram

自然言語の説明からフローチャートやプロセス図を作成します。

> [!NOTE]
> **サンプルプロンプト**「[プロセス名] のプロセス図を描いてください [目的]。[開始] から [終了] までのステップを含めてください [内容]。[利用場面] に適した、明確でプロフェッショナルなフローチャートにしてください [体裁]。」

### Build Site

自然言語の説明から Web サイトを作成します。

プロフェッショナルな Web サイト

HTML エクスポート

> [!NOTE]
> **サンプルプロンプト**「[目的] のための [サイト種別（例：マイクロサイト / ランディングページ）] を作成してください [目的]。[セクション（例：概要、スケジュール、FAQ、お問い合わせ）] を含めてください [内容]。ミニマルでプロフェッショナル、操作しやすいデザインにしてください [体裁]。」

### アカウントとセッション

![プロフィールアバターから開いたアカウントメニュー](/manual/assets/product/chat-account-menu-20260813.webp)
_この節の操作はすべて左下のプロフィールアバターの下にあります。_

### ライト / ダークテーマ

_Settings → General_ で Appearance を Light、Dark、System から選びます。System は OS の設定に従います。

### モーション軽減

OS でモーション軽減が設定されている場合、インターフェースは自動的にそれに従い、アニメーションが最小化されます。

### モデルとセッション設定

モデル、Reasoning effort、Speed は、desktop と mobile の composer にあるモデルセレクターから設定します。[モデルとセッション設定](/ja/manual/using-sotaagents/model-and-session-settings)を参照してください。

### Settings

サイドバー下部のアカウントメニューから _Settings_ を開き、General、AI Agent、Memory、Security、Usage、および gateway が対応する Login history を管理します。

### General と AI Agent の設定

_General_ タブでは、プロフィール情報、Appearance、Chat font、Motion を設定できます。

![General タブで System、Light、Dark の Appearance メニューを開いた Account Settings](/manual/assets/product/chat-settings-general-20260903.webp)
_General はプロフィール情報と表示設定を一か所にまとめます。_

_Settings → AI Agent_ では、送信ショートカット、Queue または Steer の follow-up 動作、ターン完了通知、Custom instructions、Stats for nerds、model context 表示を設定します。

![送信ショートカット、follow-up、通知、Custom instructions を表示する AI Agent タブ](/manual/assets/product/chat-settings-ai-agent-20260903.webp)
_AI Agent に会話動作と診断設定がまとまっています。_

_Voice_ セクションでは読み上げの Voice、Style、Speed を選びます。音声は文ごとにストリーミングされるため、回答全体の完了前に再生できます。

![Voice、Style、Speed を表示する AI Agent の音声設定](/manual/assets/product/chat-settings-ai-agent-voice-20260903.webp)
_Voice 設定はアシスタント回答の Read aloud に適用されます。_

### Personal Memory

_Settings → Memory_ を開きます。_Personal memory_ は保存済み項目を削除せず機能全体を一時停止/再開し、_Use memory in chats_ は recall、_Learn from chats_ は完了済み chat からの background capture を個別に制御します。学習カテゴリは communication style、working style、tool preference、personal detail、long-term goal ごとに設定できます。カテゴリを OFF にしても既存項目は削除されません。Incognito と guest/public session は Personal Memory を使用も保存もしません。

![Recall、chat からの学習、カテゴリ policy、管理、activity、import、export を個別に設定する Personal Memory 画面](/manual/assets/product/chat-memory-settings-20260813.webp)
_Recall・学習・カテゴリ許可は独立しており、Memory を一時停止しても保存済み項目は残ります。_

_View and manage memory_ では各項目の確認、誤った文言の編集、review 待ち項目の confirm、forget ができます。Workspace-specific memory はその workspace でのみ関連しますが、他メンバーには共有されずアカウント本人だけの情報です。_Memory activity_ は policy と項目の変更履歴を表示し、export は JSON を保存、import は別 AI の内容を preview してから追加します。

![Communication、personal detail、working style の保存項目と edit/forget 操作を表示する private Personal Memory manager](/manual/assets/product/chat-memory-items-20260813.webp)
_保存項目は全 workspace または一つの workspace に関連付けられますが、常にアカウント所有者だけの private data です。_

### 2 要素認証とログイン履歴

_Settings → Security_ で authenticator 2FA、recovery codes、trusted devices を管理します。Login history は Core が記録した session を表示し、古い native OAuth login は client/gateway が提供する場合に限り表示されます。

★. #### 利用量の確認

   画面**左下**の**プロフィールアバター**を選択すると、残りの利用量とクレジット残高を確認できます。

↩. #### ログアウト

   左下の**プロフィールアバター**メニューを開き、「Sign out」を選択してセッションを終了します。

## SotaAgents を使う

中心はチャットです。メッセージを入力すると、アシスタントが必要に応じて回答・検索・ファイル生成・ツール呼び出しを行います。会話をプロジェクトに整理したり、チームメイトと共有したり、会話ごとにモデルを調整したりすることもできます。

### チャットを始める

チャットは必ずワークスペースの中で行うため、まずワークスペースを開きます。サイドバー上部の**ワークスペースセレクター**を開き、作業するワークスペースを選ぶと、中央に _How can I help you today?_ と表示された入力ボックスのあるホーム画面が読み込まれます。そこに質問を入力すると会話が始まります。

### チャット画面のレイアウト

![Workspace selector、New Conversation、Search、Projects、Recents と中央 composer を備えた chat layout](/manual/assets/product/chat-home-20260813.webp)
_Sidebar に workspace、検索、会話があり、残りが thread です。_

| エリア | 表示される内容 |
| --- | --- |
| サイドバー（左） | 上部のワークスペースセレクター New Conversation ボタン Search（コマンドパレットで会話を検索） Projects（プロジェクト一覧へ移動） 最近の会話 下部のアカウントメニュー |
| チャット UI（中央） | 会話エリア チャット入力欄（モデルセレクター、テキストボックス、**(+)** 添付ボタン、ファイルチップ、送信 / 停止ボタン） `/` を入力すると機能（Capability）一覧が開きます |
| アーティファクトパネル（右） | 生成ファイルや引用をクリックすると開きます ファイルの閲覧・ページ移動・ダウンロードができます |

### メッセージの送信

1. #### 新しい会話を開始する（任意）

   サイドバーの「New Conversation」をクリックすると、新しい会話を開始できます。

2. #### 入力して送信する

   `Enter` で送信、`Shift`+`Enter` で改行します。

3. #### 回答のストリーミングを確認する

   アシスタントの回答はリアルタイムで表示されます。検索、ファイル生成、ツール呼び出しが必要な場合は、回答の途中に_ツールステップ_がインラインで表示されます。

![見出しと箇条書きを含む回答がスレッドに流れ込む様子と、その下の返信 composer](/manual/assets/product/chat-conversation-20260813.webp)
_回答は書かれながら流れてきます。完了を待たずに読めます。_

4. #### 回答を途中で止める

   アシスタントの回答中は、送信ボタンが _Stop_ ボタンに変わります。クリックすると生成を停止できます。

![回答の下の操作列：再試行・コピー・読み上げ・フィードバックと消費 credit](/manual/assets/product/chat-message-actions-20260813.webp)
_各回答に固有の操作と消費 credit が付きます。_

### 引用返信・読み上げ・分岐

アシスタント回答内の文章を選択して _Reply_ をクリックします。選択した引用が composer の上に添付され、次のメッセージに正確な文脈を渡せます。

![アシスタント回答内の選択テキストと composer に添付する Reply 操作](/manual/assets/product/chat-quote-reply-20260903.webp)
_話したい部分だけを選択して、その引用へ直接返信します。_

アシスタント回答の _More_ メニューから _Read aloud_ または _Fork from this message_ を選べます。メッセージからの Fork は、その回答までの会話を新しい thread にコピーし、元の会話は変更しません。

![Read aloud と Fork from this message を表示するアシスタントメッセージの More メニュー](/manual/assets/product/chat-message-fork-menu-20260903.webp)
_同じメニューから回答の読み上げ、またはその地点での分岐ができます。_

### 編集と長い会話

過去のユーザーメッセージを編集すると、暗いオーバーレイの上で composer が編集モードになり、スクロールがロックされます。`Esc` または外側のクリックで終了できます。別の会話に切り替えて戻っても編集中の内容は保持されます。

![暗いオーバーレイの上で過去のメッセージを編集する composer](/manual/assets/product/chat-message-edit-overlay-20260903.webp)
_編集モードが画面を占有し、分岐位置を明確にします。_

長い会話が context 確保のため自動要約されると、chat stream に _Context automatically compacted_ activity が表示されます。

![会話内に表示された Context automatically compacted activity](/manual/assets/product/chat-context-compaction-20260903.webp)
_自動 compaction は毎回 timeline に記録されます。_

### 非アクティブな組織

組織のプランが非アクティブな場合、composer に通知が表示されます。既存の内容は閲覧できますが、プランが復旧するまでメッセージ送信、ファイルアップロード、app 変更は無効です。

![組織の subscription がキャンセルされ送信が無効であることを示す composer](/manual/assets/product/chat-org-inactive-notice-20260903.webp)
_組織の非アクティブ通知は、無効になった操作と同じ場所に表示されます。_

> [!NOTE]
> 問題が起きた場合
>
> メッセージの下にエラーバナーが表示され、「Retry」と「Dismiss」ボタンで対応できます。

### モデルとセッション設定

**モデルセレクター**は desktop と mobile の composer 内にあります。現在のモデル名からモデル、Reasoning effort、Speed を選び、以降のメッセージに適用します。

1. #### モデルを選ぶ

   セレクターには組織で現在利用できる model だけが表示されます。Locked model は表示されません。権限のある Owner/Admin は _Console → Organization → Chat Models_ から access request を送信します。

![利用可能な Claude と Gemini、Reasoning effort、Speed を表示する現在の model セレクター](/manual/assets/product/chat-model-settings-latest-20260903.webp)
_Chat picker には選択可能な model のみ表示され、access request は Console で行います。_

2. #### Reasoning effort を設定する

   _Reasoning effort_ は、応答前にモデルがどれだけ考えるかを設定します — _None_・_Minimal_・_Low_・_Medium_・_High_・_X-High_。高くするほど難しい問題への回答品質が上がる可能性がありますが、時間とクレジット消費が増えます。対応しているモデルでのみ表示されます。

3. #### Speed を選ぶ

   _Standard_ は品質を優先し、_Fast_ は最もスループットの高い route を優先します。Credit は provider が報告したコストどおりで、Fast 用の 1.5 倍追加料金はありません。対応 model でのみ表示されます。

### ターン統計と model context

_Settings → AI Agent_ で _Stats for nerds_ と _Show model context_ を有効にします。Composer 下の行には turn、step、LLM 時間、tool call 時間、平均 TTFT が表示されます。Context readout では window 全体の使用量と system prompt、message、attachment、tool call、skill の内訳を確認できます。

![ターンごとの時間統計と model context 使用量の内訳を表示する composer](/manual/assets/product/chat-turn-stats-model-context-20260903.webp)
_ターン時間と context 使用量は AI Agent settings で有効にする任意の診断情報です。_

### ファイルの添付

契約書、シート、スクリーンショットなどを会話にドロップします。上限は 1 メッセージ 20 件、1 会話 100 件、1 ファイル 100 MB です。

1. #### 添付する

   入力エリアにファイルを**ドラッグ & ドロップ**するか、プラスボタン（**+**）をクリックしてファイルを選択します。画像やドキュメントを入力欄に直接貼り付けることもできます。

2. #### アップロード完了を待つ

   各ファイルはアップロード状況を示すチップとして表示されます。送信前に取り消す場合は、チップの _x_ ボタンで削除します。画像、PDF、一般的なドキュメント形式に対応しています。

3. #### メッセージを送信する

   送信すると Core がファイルを会話に保存し、同じ thread の後続ターンから参照できます。

> [!NOTE]
> 添付ファイルと Knowledge Base の違い
>
> 添付は Core の raw file であり、Knowledge Base への自動取り込みや OCR は行われません。共有検索用にするには、workspace で導入・有効化された [Knowledge Base](/ja/manual/using-sotaagents/integrations) アプリへ別途取り込んでください。

### リッチな回答表示

アシスタントの回答はプレーンテキストにとどまりません。SotaAgents は回答を完全な書式付きでレンダリングし、生成コンテンツを回答内に直接埋め込めます。

### 書式

- **コードブロック** — シンタックスハイライト付き。言語ラベルと_コピー_ボタンがあります。
- **テーブル** — 罫線付きで、幅が広い場合は横スクロールできます。
- **リスト** — 箇条書きと番号付きに対応します。
- **リンク** — 新しいタブで開きます。

### 回答内の生成コンテンツ

- **生成画像** — インラインで表示され、クリックするとライトボックスで拡大表示されます。
- **生成ファイル** — 文書、シート、スライド、PDF はブロックとして表示され、[アーティファクトパネル](/ja/manual/using-sotaagents/artifacts-panel)で開いてダウンロードできます。
- **Web 検索結果** — アシスタントが Web を検索した場合、結果がインラインで表示され、回答に反映されます。
- **Subagent の作業** — 委任した作業は名前付き chip で表示されます。開くと、内部 message を main timeline に展開せず durable transcript を確認できます。

### アーティファクトパネル

アシスタントがファイルを生成したとき、または引用を開いたとき、チャット右側の**アーティファクトパネル**に表示されます。

### 表示される内容

| 種類 | 表示内容 |
| --- | --- |
| 生成ドキュメント | アシスタントが作成した Word 文書、スプレッドシート、スライド、PDF — ダウンロードボタン付きでプレビューされます。 |
| ファイルと画像 | PDF、画像、動画、音声、テキスト、Markdown、HTML、CSV はパネル内で直接レンダリングされます。 |
| 引用プレビュー | 引用の元になったドキュメントが、引用ページを開いた状態で表示されます。 |
| Subagent transcript | 委任タスク、結果、最終 status を含む名前付き read-only transcript。History を再読み込みした後も開けます。 |

1. #### アーティファクトを開く

   メッセージ内の生成ファイル、引用チップ、または名前付き subagent chip をクリックします。右側にパネルが開きます。

![Launch Readiness Analyst subagent chip を durable transcript として artifact panel に開いた chat](/manual/assets/product/chat-subagent-artifact-20260813.webp)
_Subagent 作業は main thread では compact に保たれ、artifact panel で durable transcript として開きます。_

2. #### 閲覧・移動する

   Artifact の種類に応じて、ドキュメントまたは subagent transcript のスクロール、PDF のページ送り、画像のズーム、メディアの再生ができます。

### Skill と Office preview

Skill viewer では左側に固定 file tree を表示しません。上部の breadcrumb から skill 内の別ファイルを選択します。

![パネル上部でファイル選択 breadcrumb を開いた Skill viewer](/manual/assets/product/chat-skill-viewer-breadcrumb-20260903.webp)
_Breadcrumb で skill ファイルを切り替え、preview 領域を広く保てます。_

ダウンロードしたファイルは元の filename を保持します。Excel preview は埋め込み画像、chart、shape を表示します。DOCX form preview は layout を保持し、入力は body のみを変更して header、footer、page geometry を維持し、footnote marker を field に変換しません。

3. #### ダウンロードする

   ダウンロードボタンでファイルを PC に保存します。

### 引用と出典

アシスタントがワークスペースのドキュメントや Web を根拠に回答する場合、必ず出典を引用します。引用は回答内に小さなチップとしてインライン表示され、出典ファイル名が示されます。

1. #### 引用を見つける

   回答内の、出典ファイル名が表示された小さなチップを探します。カーソルを合わせる（モバイルではタップする）と、出典のタイトル、セクション、引用箇所の抜粋を示すカードが表示されます。

2. #### 出典を開く

   チップをクリックすると、出典ドキュメントがアーティファクトパネルで開きます。ドキュメントは完全なプレビューとして表示され、Office ファイルはドキュメントビューアーで開くため、原文を文脈の中で確認できます。

### 履歴

正常に作成された通常の会話は workspace 履歴に保存されます。Incognito session は History に保持されません。Core が session 中に一時保存する場合はありますが、close または expiry で purge され、上限は 24 時間です。会話作成前に guardrail で block された request、一部の作成失敗も履歴に表示されません。

1. #### 会話を探す

   サイドバーの **Search** をクリック（または `⌘``K`）でコマンドパレットを開きます。最近の会話が並び、そのまま移動できます。_Recents_ をスクロールして任意の会話をクリックすることもできます。表示中の会話はハイライトされます。

![最近のチャットと推奨アクションを並べた検索コマンドパレット](/manual/assets/product/chat-search-palette-20260813.webp)
_Search はページ上にコマンドパレットを開きます。最近の会話が先、続いて New Conversation や Projects などの操作。_

2. #### グループ化を変更する

   _Recents_ の横のスライダーアイコンをクリックして _Group by_ メニューを開きます。_None_（フラット表示）、_Date_（今日・昨日・今週…）、_Project_（プロジェクト別）から選択します。

3. #### 管理して続ける

   最大 100 件を pin し、三点メニューから rename/delete できます。応答中は次の message の queue/edit、stop、retry、過去 message の編集と分岐ができます。

### 会話を Fork する

Sidebar または history bar の会話オプションから _Fork_ を選ぶと、thread 全体を新しい会話にコピーします。アシスタント回答から Fork すると、その地点で分岐します。元の会話は変わらず、新しい会話は origin/provenance chip のない独立した thread です。

Composer draft は conversation route ごとに保持されます。履歴を作らない場合は送信前に _Incognito_ を有効にしてください。

### プロジェクト

プロジェクトを使うと、関連する会話を 1 つの名前の下にまとめ、共有インストラクションやコンテキストファイルを任意で設定できます。サイドバーの _Projects_ をクリックすると一覧が開きます。

### プロジェクトの作成

1. #### 一覧を開く

   サイドバーの _Projects_ をクリックします。タブで _Created by you_ と _Shared with you_ を切り替えられます。最終更新日、名前、作成日で並べ替えできます。

2. #### 作成する

   「New project」をクリックし、名前（必須）と説明（任意）を入力して確定します。プロジェクトはすぐに一覧に表示されます。

![2 つの project を並べた Projects 画面。自分が作成した project と共有された project のタブ付き](/manual/assets/product/chat-projects-list-20260813.webp)
_新しい project はすぐ一覧に表示されます。_

### 会話の追加と移動

1. #### プロジェクトに追加する

   サイドバーまたはプロジェクト内の任意の会話で **…** メニューをクリックし、_Add to project_ を選択します。サブメニューにプロジェクト一覧が表示され、そこから新規プロジェクトの作成もできます。

![サイドバーの会話の三点メニューと、利用可能な project を並べた Add to project サブメニュー](/manual/assets/product/chat-add-to-project-20260813.webp)
_どの会話も三点メニューから project に入れられます。_

2. #### 移動または解除する

   同じ **…** メニューから、_Move to project_ で別のプロジェクトへ移動（確認画面が先に表示されます）、_Remove from project_ で会話を削除せずにプロジェクトから外せます。

### プロジェクトの中

プロジェクトを開くと、プロジェクト内で新しいチャットを開始するコンポーザーと、含まれる会話の一覧が表示されます。右サイドバーでは次の設定ができます。

![会話、Instructions、context file、member を表示する project 詳細ページ](/manual/assets/product/chat-project-detail-20260813.webp)
_Project 内では会話、共有 instruction、context file、閲覧できる member を確認できます。_

- **Instructions** — プロジェクト内で開始するすべてのチャットに適用される共有インストラクションを設定します。
- **Project context** — すべてのプロジェクトチャットで利用できるファイルやテキストスニペットを添付します（最大 50 件）。
- **Members** — ワークスペースのメンバーをプロジェクトに招待し、アクセスを管理します。

### 名前の変更と削除

プロジェクトカードまたはプロジェクト詳細ページの **…** メニューから、_Edit_（名前や説明の変更）または _Delete_（プロジェクトの削除）を実行できます。削除するとプロジェクトとその会話は直ちに削除されます。この操作は取り消せません。

### 共有

会話のスナップショットを、リンク経由でチームメイトや外部に共有できます。共有リンクは作成した時点の会話を固定して保存するため、その後の新しいメッセージはリンクを更新するまで含まれません。

### 共有設定

| 公開範囲 | 閲覧できる人 |
| --- | --- |
| Workspace only | 現在のワークスペースのメンバー。 |
| Organization | 組織にサインインしているすべての人。 |
| Public link | リンクを知っているすべての人。サインインは不要です。 |

### 共有の手順

1. #### 共有ダイアログを開く

   会話ヘッダーの共有アイコン（または三点メニュー → _Share_）をクリックします。ダイアログに現在の公開範囲とリンクが表示されます。

![ツール操作を含めるトグルと、workspace メンバー・組織・リンクを知る全員という公開範囲を持つ共有ダイアログ](/manual/assets/product/chat-share-dialog-20260813.webp)
_このダイアログで公開範囲を選び、リンクを作成します。_

2. #### 公開範囲を選ぶ

   _Workspace only_・_Organization_・_Public link_ から選択します。Public link は誰でも閲覧できます。機密性のある会話は公開共有しないでください。

3. #### 任意：ツールアクティビティを含める

   _Show tool activity_ を ON にすると、共有ビューにツールステップ名が含まれます（ツールの出力自体は表示されません）。会話に添付ファイル、アーティファクト、ナレッジソース、シークレットの可能性がある内容が含まれる場合は、ダイアログに警告が表示されます。

4. #### リンクをコピーして共有する

   リンクをコピーして任意の方法で共有します。受け取った人は、ワークスペースに参加せずに `/share/c/:token` でスナップショットを閲覧できます。

5. #### 更新または無効化する

   _Update link_ でスナップショットを更新し、新しいメッセージを反映します。_Revoke link_ は直ちにアクセスを停止し、旧 URL を開いた人には期限切れページが表示されます。

> [!NOTE]
> Create a copy
>
> 共有リンクを受け取った人は、「Create a copy」をクリックすると、スナップショットを自分のワークスペースに複製し、そこから会話を続けられます。

### インテグレーション

ドキュメント connector は Core UI の必須 route ではなく、**Knowledge Base** アプリが所有します。組織への app 導入、workspace での有効化、必要な設定/provider がそろった場合だけ表示されます。

範囲：Knowledge Base app

設定：role/config 依存

Provider：deployment 依存

1. #### Knowledge Base を開く

   Workspace の app surface から開きます。app や connector が見つからない場合は、管理者に導入・有効化・設定を確認してもらいます。

2. #### Source を接続または取り込む

   Tenant が提供する connector を選びます。一部は Composio または provider OAuth を使用します。利用可能な provider と認可手順は deployment によって異なります。

3. #### Indexing を確認する

   App 内で sync/process が完了し、document status が ready になるのを確認します。Chat 添付を indexed Knowledge Base document とみなさないでください。

4. #### 検索を明示する

   Chat で Knowledge Base capability を選ぶか、使う source を明示します。Connector があるだけで全質問が自動検索されるわけではありません。

> [!WARNING]
> 固定 connector を仮定しない
>
> Google Drive、OneDrive、SharePoint などは tenant の app/provider が実際に提供する場合に限り利用できます。固定リストではなく現在の UI を確認してください。

### MCP サーバー

MCP サーバーは、アシスタントに**ツール**を提供します。インテグレーションがドキュメントの_読み取り_を可能にするのに対し、MCP サーバーは_操作の実行_を可能にします — Linear の Issue 作成、Slack への投稿、Notion データベースの更新、社内 API へのクエリ実行など。「MCP」は _Model Context Protocol_ の略で、AI エージェントにツールを公開するためのオープン標準です。

代表的なプロバイダー：Linear · Notion · Slack · GitHub · Asana

設定：ワークスペース管理者

利用：すべてのワークスペースメンバー

### インテグレーションと MCP の違い

| 観点 | インテグレーション | MCP サーバー |
| --- | --- | --- |
| 役割 | 対象システムのドキュメントをナレッジベースに取り込みます。 | アシスタントに、対象システムを操作するツールを与えます。 |
| アシスタントができること | 内容を_読み_、回答で引用します。 | _操作_します — 作成、更新、ライブデータの照会。 |
| データの鮮度 | 最終同期時点のスナップショット。更新には再同期が必要です。 | ライブ — アシスタントがその場でシステムを呼び出します。 |
| 使いどころ | チームのドキュメントを根拠にした回答が欲しいとき。 | 回答だけでなく、タスクの実行までさせたいとき。 |

### ワークスペース管理者向け — MCP サーバーの登録

1. #### MCP Servers を開く

   ワークスペースコンソールから _MCP Servers_ を選択します。このワークスペースに接続されているサーバーが一覧表示されます。

![MCP Servers 画面：左に接続済みサーバー一覧、右に選択したサーバーの状態・transport・認証方式・tool 一覧](/manual/assets/product/ws-mcp-20260813.webp)
_一覧に登録済みの全サーバーが並び、選ぶと transport・認証・公開している tool が分かります。_

2. #### サーバーを追加する

   「Add server」をクリックし、**Name**、サーバーの HTTPS **URL**、**Auth method**（SaaS アプリは OAuth、社内ツールは API キー、または None）を入力します。

![名前・サーバー URL・transport と、Advanced 内の認証方式および prompt hint を持つ MCP サーバー追加ダイアログ](/manual/assets/product/ws-mcp-add-20260813.webp)
_サーバー追加には URL と transport が必要です。認証と prompt hint は Advanced にあります。_

3. #### 認証する

   OAuth サーバーの場合は「Connect」をクリックし、ブラウザでスコープを承認します。API キー方式の場合はフォームにキーを貼り付けます。キーは暗号化され、以後表示されることはありません。

4. #### テストしてツールを更新する

   「Test」ボタンで接続を確認し、「Refresh tools」をクリックしてサーバーのツールカタログをワークスペースに取り込みます。

5. #### ワークスペースごとにツールを許可する

   サーバーを接続すると、ツールは自動的にアシスタントから利用可能になります。ここで個別のツールを OFF に切り替えて制限できます。OFF にしたツールはアシスタントからは見えません。

### 代表的な MCP サーバー

| サーバー | アシスタントができること | 認証 |
| --- | --- | --- |
| Linear | Issue・コメント・担当者の作成 / 参照 / 更新 | OAuth |
| Notion | ページ検索、ページ作成、データベース行の更新 | OAuth |
| Slack | メッセージ投稿、チャンネルの読み取り、ユーザー検索 | OAuth |
| GitHub | PR の読み取り、コメント、コード検索、ワークフロー起動 | OAuth または PAT |
| Asana | タスクの一覧・作成・ステータス更新 | OAuth |
| 社内 HTTP MCP | エンジニアが公開する任意の機能 | API キー |

> [!WARNING]
> 許可するツールは慎重に
>
> アシスタントは、有用と判断すれば与えられたどのツールでも使用します。破壊的なツール（delete・drop・force-push など）は、アシスタントの役割上どうしても必要な場合を除き、公開しないでください。

## 管理コンソール

組織のオーナー・管理者向け — ロール、ワークスペース、アプリ、メンバー、API キー、クレジットを管理します。

### ロールと権限

アクセス権は 2 つのレベルで機能します。**組織ロール**は、請求・メンバー・ワークスペースなど、アカウント全体でできることを定めます。**ワークスペースロール**は、特定のワークスペース内でできることを定めます。ワークスペースごとに異なるロールを持つことができ、組織のオーナーと管理者は、組織配下のすべてのワークスペースで自動的に管理者権限を持ちます。

![組織ロールと状態とともに各メンバーを一覧するメンバー表](/manual/assets/product/console-participants-20260813.webp)
_Members は組織の全員と、そのロールを表示します。_

### 組織ロール

| ロール | できること |
| --- | --- |
| Owner | 組織メンバー、workspace、API key、app、security と、下記の Owner/Admin 向け credit-policy 操作。プラットフォームの subscription 変更や money movement 権限は含みません。 |
| Admin | メンバー、workspace、app、多くの credit-policy 設定。各 screen/mutation は API が個別に認可し、無制限の billing 権限ではありません。 |
| Member | 追加されたワークスペースの利用。 |

### Subscription と credit の権限

| 操作 | 権限 |
| --- | --- |
| 組織の credit overview を読む | 組織メンバー |
| Credit package の CRUD/割り当て、rolling user limit | Organization Owner または Admin |
| Guest Credit add-on の参照と workspace guest allocation | Organization Owner または Admin |
| Plan の upgrade/downgrade/cancel、top-up/refund | SotaAgents 運営チームのみ |
| Pool/seat 設定と Guest Credit add-on lifecycle | SotaAgents 運営チームのみ |

### ワークスペースロール

![Workspace role とともに member を一覧する workspace の Participants タブ](/manual/assets/product/ws-participants-20260813.webp)
_Workspace role は組織 role とは別に、各 workspace で設定します。_

| ロール | できること |
| --- | --- |
| Workspace Admin（`WS_ADMIN`） | Workspace settings、member、app、integration、guardrail、MCP server を管理します。 |
| Workspace Member（`WS_MEMBER`） | Workspace と利用可能な capability を使えます。Member、app、workspace settings は変更できません。旧 Editor/Chatter 値は compatibility 上この role に map されます。 |

> [!NOTE]
> 組織のオーナー・管理者は自動昇格します
>
> 組織のオーナーまたは管理者は、組織配下のすべてのワークスペースでワークスペース管理者の権限を持ちます。自分自身を個別に招待する必要はありません。

### コンソール概要

管理コンソール（`/console`）は、組織のオーナーと管理者がプラットフォームを管理する場所です。ワークスペースのチャット UI とは独立しており、ほとんどの機能へのアクセスには組織の Admin または Owner ロールが必要です。

![プランと自分のロールを表示する Admin Console の組織ディレクトリ](/manual/assets/product/console-orgs-20260813.webp)
_コンソールは組織一覧から始まり、各カードにプランとロールが出ます。_

![組織の identity と管理設定を表示する Organization Settings ページ](/manual/assets/product/console-settings-20260813.webp)
_Organization Settings には、現在の role が管理できる identity と policy がまとまっています。_

コンソールは**組織**を軸に構成されています。組織詳細画面から次の各画面に移動できます。

- **Dashboard** — users、workspaces、AI responses、credit/model 使用状況
- **Workspaces** — ワークスペースの作成・管理・設定
- **Apps** — App Store からの拡張機能のインストールと管理
- **Participants** — 組織メンバーとロールの管理
- **API Keys** — システム間連携用の資格情報
- **Activity** — 組織全体の監査ログ
- **Credits** — credit の使用、割り当て、alerts、logs、権限付き Guest Credits
- **Chat Models** — 利用可能なモデルの制御と組織既定モデルの設定
- **Security** — 組織レベルのセキュリティ設定
- **Settings** — 組織名と一般設定

### ダッシュボード

組織ダッシュボードでは、コンソールを離れずにプラットフォームの利用状況をリアルタイムで把握できます。

![メンバー・workspace・AI response のタイル、credit チャート、ユーザー別 credit、利用傾向を示す組織ダッシュボード](/manual/assets/product/console-dashboard-20260813.webp)
_ダッシュボードは組織の活動に答えます：メンバー、workspace、response、credit の行き先。_

### 3 つの KPI card

Total Users、Workspaces、AI Responses が現在の組織を要約します。

### Credit usage

時系列および user 別の view で credit の消費箇所を確認します。

### Model usage

利用が許可された chat model の使用内訳を表示します。

### Trends

User と AI response の変化を表示します。現在の dashboard は recent activity feed を保証しません。

### ワークスペース

Workspaces タブには組織内のすべてのワークスペースが一覧表示されます。ここから新規作成や、既存ワークスペースの詳細設定に進めます。

![Slug と作成日とともに組織の workspace を一覧する Workspaces タブ](/manual/assets/product/console-workspaces-20260813.webp)
_各 workspace は独立した context で、app・integration・履歴を個別に持ちます。_

一覧上部の _Grid / List_ toggle で、visual card と compact row を切り替えます。変わるのは表示方法だけです。

![Grid と List の toggle を表示した組織 Workspaces ページの List view](/manual/assets/product/console-workspaces-list-20260903.webp)
_List view は workspace の identity、slug、説明、作成日を compact な行で表示します。_

### ワークスペースの作成

1. #### 「Create workspace」をクリック

   Workspaces タブで「Create workspace」ボタンをクリックし、名前と説明（任意）を入力します。

2. #### 設定する

   作成後、詳細画面で Apps、MCP Servers、Participants、Guardrails、Activity、Feedback、Configure Embed、Settings を role に応じて管理します。

### ワークスペースレベルのタブ

![組織に install 済みの demo app と workspace access control を表示する workspace Apps tab](/manual/assets/product/ws-apps-config-20260813.webp)
_組織に install した app は全 workspace で既定 enabled です。この tab で workspace ごとの disable/re-enable override を設定します。_

| タブ | できること |
| --- | --- |
| MCP Servers | このワークスペース用の MCP ツールサーバーの接続と管理。 |
| Apps | 組織にインストール済みのアプリを確認し、既定の有効状態をワークスペース単位で上書き。 |
| Participants | ワークスペース単位のメンバー管理とワークスペースロールの割り当て。 |
| Guardrails | Input と tool output の保護を設定・確認。 |
| Activity | ワークスペースのアクティビティログの閲覧と CSV エクスポート。 |
| Feedback | このワークスペースの会話から送信されたユーザーフィードバックの確認。 |
| Configure Embed | Public guest deployment の設定、preview、publish、unpublish。 |

![会話から送られた rating と comment を一覧する workspace Feedback ページ](/manual/assets/product/ws-feedback-20260813.webp)
_Feedback は workspace review 用に会話の評価とコメントを集約します。_

### Public Deployment（Configure Embed）

Workspace access を持つ Organization Owner/Admin は allowed origins、chat model、外観、任意の lead form、guest 向け app/tool exposure を設定して preview できます。Publish は public deployment を作り、unpublish は新規 guest access を停止します。Browser に organization API key は置きません。

- Public-chat boundary が origin、session、IP を検査します。
- Guest conversation は別の Guest Credit pool から workspace allocation を消費します。
- Publish 前に app/tool と allocation warning を確認します。

![Workspace public deployment の Configure Embed ページ](/manual/assets/product/ws-embed-20260813.webp)
_Guest deployment の設定、preview、publish、unpublish を一か所で行います。_

> [!NOTE]
> クイックアクション
>
> ワークスペース一覧には、状況に応じたクイックアクション（例：_Add datasource_、_Invite member_、_Try assistant_）が表示され、よく使う操作にワンクリックでアクセスできます。

### ワークスペース設定

ワークスペース詳細画面で _Settings_（ワークスペースサイドバーの下部）を開くと、ワークスペースの名前変更と削除ができます。削除は確認ステップ付きのモーダルダイアログで実行されます。削除されたワークスペースのデータは復元できません。

![Identity、slug、description、tag、assistant system prompt、response format を表示する workspace settings](/manual/assets/product/ws-settings-20260813.webp)
_Workspace settings は別ページではなく drawer で開きます。_

### アプリのインストール

アプリは、組織に専門機能を追加するインストール型の拡張です。管理者は管理コンソールの **Apps** タブ（_組織詳細 → Apps_）から管理します。

![Installed・Catalog・Recovery タブと local seed の contract-probe app を表示する組織 App Store](/manual/assets/product/console-apps-20260813.webp)
_実際の catalog は deployment ごとに異なり、この local capture は TestStack の contract-probe app を使います。_

> [!NOTE]
> 2 層構造のアプリ管理
>
> **組織レベル：**exact app environment を組織に install します。**Workspace level：**すべての workspace は既定で enabled を継承します。Admin は利用させない workspace にだけ明示的な disable override を作り、後から再度 enable できます。

### アプリの例

Catalog は deployment と organization に依存します。以下の名前と contribution 数は、ある時点の artifact の例であり固定 inventory ではありません。現在の app detail を正としてください。

| アプリ | 追加される機能 | 提供内容 |
| --- | --- | --- |
| Knowledge Base | ハイブリッド（セマンティック + 全文）検索と出典引用を備えた共有ドキュメントストア。社内ドキュメントをアップロードすると、アシスタントが根拠付きで回答できます。主なツール：`hybridSearch`、`searchDocuments`、`structuredQuery/Sql`、ファイル管理。 | 19 Tools · 1 Skill · 2 UI Slots |
| Office App | Word 文書、Excel スプレッドシート、PowerPoint / PDF プレゼンテーション、ダッシュボードをサンドボックス内で生成・編集します。自動品質チェック付きのスライドデッキエディターを含みます。 | 11 Tools · 1 Skill · 1 UI Slot |
| Web Search | 公開 Web のリアルタイム検索とページ本文の抽出。主なツール：`webSearch`、`fetchWebPage`（1 URL あたり最大約 50,000 文字）。 | 3 Tools · 1 Skill · 1 UI Slot |
| CAD | 建設向けの CAD / BIM ワークフロー — PDF・DWG・DXF・IFC ファイルの取り込み、レイアウトを考慮した OCR、ページ引用付きの Q&A、記号の自動カウント、面積計算、インタラクティブな BIM モデルビューアー。 | 5 Tools · 2 Skills · 7 UI Slots |
| Remagine | AI ショート動画の作成：アシスタントが動画ごとのワークスペースで Remotion（React/TSX）コードを記述し、esbuild によるライブプレビューを提供、最終的な MP4 を Remotion Lambda でレンダリングします。 | 11 Tools · 1 Skill · 1 UI Slot |

### App Store の画面構成

Apps タブには 4 つのサブビューがあります。

- **All** — 組織で利用可能なすべてのアプリ。
- **Installed** — 現在有効なアプリ。
- **Catalog** — 追加可能なアプリのマーケットプレイス全体。
- **Recovery** — ソフトアンインストールされたアプリ。削除されたアプリは完全削除まで 30 日間ここに保持され、必要に応じて復元できます。

### アプリのインストール手順

1. #### Catalog タブを開く

   _Console → 対象の組織 → Apps → Catalog_ に移動します。

2. #### インストールする

   Development、Staging、Production の exact environment card を開き、version と contribution を確認して「Install」をクリックします。Environment は組織に install され、すべての workspace で既定 enabled になります。

![Local contract-probe app の exact Production environment 詳細。version、status、surface overview を表示](/manual/assets/product/console-app-detail-20260813.webp)
_App detail は一つの exact environment に pin され、現在の install 状態を表示します。_

3. #### Workspace access を確認する

   Workspace 詳細 → _Apps_ を開きます。新しく install した app は既定で enabled です。利用させない workspace だけ disable し、制限を外すときは再度 enable します。

![Install 済み demo app と継承された access state を表示する workspace Apps config](/manual/assets/product/ws-apps-config-20260813.webp)
_Override がなければ enabled。Control は明示的な workspace override を作成または変更します。_

4. #### アンインストールする

   Installed タブで「Uninstall」をクリックします。アプリは Recovery に移動し、30 日間は復元できます。30 日を経過すると完全に削除されます。

> [!WARNING]
> アプリのクレジット消費
>
> 各アプリは利用時にクレジットを消費します。アプリごとの消費量は Credit Logs タブで確認できます。支出を抑えたい場合は、ワークスペース単位のクレジットアラートを設定してください。

### メンバーの招待

_Console → 対象の組織 → Participants → Invite_ からメンバーを招待します。

1. #### 招待を送信する

   相手のメールアドレスを入力し、組織ロール（Member または Admin）を選択します。同時にワークスペースへの追加とワークスペースロールの設定も任意で行えます。

![メールアドレスを入力しロールを選択した、送信可能な招待パネル](/manual/assets/product/console-invite-form-20260813.webp)
_アドレスを入力し、組織ロールを選び、送信します。_

2. #### 招待を受諾する

   相手にはリンク付きのメールが届きます。リンクをクリックするとサインインまたは登録を求められ、その後、組織と指定したワークスペースに自動的に参加します。

3. #### 再送または削除する

   承諾されるまで、招待されたユーザーは参加者テーブルに_非アクティブ（Inactive）_として表示されます。アクションメニューから招待リンクのコピー、招待の再送信、誤送信した招待の削除を実行できます。

![非アクティブな招待ユーザーのアクションメニューを開き、招待リンクのコピー、招待の再送信、削除を表示した参加者テーブル](/manual/assets/product/console-invite-pending-20260813.webp)
_非アクティブ行は招待が承諾または削除されるまで残り、保留中の招待に対する操作はこのメニューにまとまっています。_

### API キー

API key は承認済み machine-to-machine 統合を認証します。組み込みの _Configure Embed_ は browser 内で organization API key を使わず、publish/embed identity を制限付き guest session に交換します。Chat または組み込み widget だけを使う場合、その目的の key は作成しません。

1. #### API Keys を開く

   左サイドバーの _Console → 対象の組織 → API Keys_ に移動します。

![公開鍵・スコープ・状態・最終利用・作成日とともに key を一覧する API Keys 画面](/manual/assets/product/console-api-keys-20260813.webp)
_各 key にスコープと利用履歴の有無が表示されます。_

2. #### キーを作成する

   右上の「Create API Key」をクリックします。ダイアログが開くので、後から識別できるよう任意の**名前**（例：「Production environment」）を入力し、「Create」をクリックします。

![名前を入力した Create API Key ダイアログ](/manual/assets/product/console-api-key-dialog-20260813.webp)
_名前は自分用のラベルで、key の権限には影響しません。_

3. #### キーとシークレットを直ちに保存する

   「API Key created」画面は**一度しか表示されません**。**API Key**（形式：`sota_ek_…`）と **API Secret** の両方が表示されるので、この時点で両方をコピーし、安全に保管してください。画面を閉じた後は再表示できません。

![作成直後に一度だけ表示されるダイアログ。API key、マスクされた secret、再表示されない旨の警告](/manual/assets/product/console-api-key-created-20260813.webp)
_Secret は一度しか表示されません。閉じる前にコピーしてください。_

4. #### 確認して閉じる

   保存が済んだら「I have saved the Secret」をクリックしてダイアログを閉じます。

5. #### API 呼び出しでキーを使用する

   API key は承認済みの server-to-server 統合でのみ使用します。ブラウザーや public widget に secret を埋め込まないでください。主な用途は、自社システムに SotaAgents を組み込むための ticket handshake の署名です — [自社システムへの SotaAgents 組み込み](/ja/manual/enterprise-integration/embedding-in-your-systems)を参照してください。

6. #### キーを無効化する

   キーを削除せずに利用を停止するには、対象キーの行にある「Actions」ボタンから「Disable」を選択し、ダイアログで確認します。キーは直ちに無効になり、一覧には無効状態のまま表示されます。

> [!WARNING]
> キーは秘密情報として扱う
>
> API キーをソース管理にコミットしたり、チャットで共有したりしないでください。パスワードと同様に扱います。キーが漏えいした場合は、直ちに無効化して新しいキーを作成してください。

### 監査ログ

監査ログは、「誰が・いつ・何をしたか」の完全な記録を、組織レベルと各ワークスペースレベルの両方で管理者に提供します。ログは読み取り専用で、CSV にエクスポートできます。

### 記録される内容

| 列 | 説明 |
| --- | --- |
| Time | 操作のタイムスタンプ。 |
| Actor | 操作を実行したユーザーまたはシステム。 |
| Action | イベントの種類：_create_・_update_・_delete_・_execute_。 |
| Target | 操作の対象 — アプリ、データソース、インテグレーション、参加者、チャット。 |
| Details | クリックするとイベントの全ペイロードを展開表示します。会話の完全なコンテキストと操作の構造化データを含みます。 |

### ログへのアクセス

![Action type filter、summary analytics、event row を表示する organization activity log](/manual/assets/product/console-activity-20260813.webp)
_Organization-level log は全 workspace を対象にし、action type で絞り込めます。_

- **組織レベル** — _Console → 対象の組織 → Activity_。組織内の全ワークスペースを横断したすべてのイベントを表示します。
- **ワークスペースレベル** — _Console → 対象の組織 → Workspaces → [ワークスペース] → Activity_。そのワークスペースのイベントのみを表示します。

### フィルタリングとエクスポート

検索ボックス、実行者フィルター、操作種別フィルター、期間指定でログを絞り込めます。「Export CSV」をクリックすると、現在の絞り込み結果をダウンロードできます。

![Summary strip、event chart、conversation ごとの row を表示する workspace activity log](/manual/assets/product/ws-activity-20260813.webp)
_Workspace log は同じ記録を一つの workspace に限定します。_

### クレジット管理

SotaAgents は利用量を組織レベルの_クレジット_として課金します。チャットの各ターン、文書生成、画像生成、ツール呼び出しのすべてがクレジットを消費します。クレジット関連の設定は _Console → 対象の組織 → Credits_ で管理します。現在は Credit Allocation、Member Allocation、Credit Alerts、Credit Logs、権限に応じた Guest Credits の 5 タブです。

![Credit Allocation タブの Credits 画面。プラン、seat 設定、基準 credit 単位を表示](/manual/assets/product/console-credits-20260813.webp)
_Credit は組織全体で管理します：プール、seat、上限。_

### Credit Allocation（クレジット割り当て）

このタブの上部には、組織のクレジット状況をまとめた KPI バンドが表示されます。表示内容はプランによって異なります。

- **Business / Enterprise（プール制）：**プール総量、消費済み、残量、シート数。組織全体の上限に対する消費状況がライブのプール消費バーで表示されます。
- **その他のプラン（シート単位）：**シート数、基本単位（Base unit）、請求サイクル、リセット日。

KPI バンドの下には、消費量上位 10 名のメンバーごとの利用状況バーが表示されます。バーは色分けされます：緑（上限内）、橙（上限接近）、赤（ブロック中 / 超過）。

**リセット日**（締め日、1–28）と**シート数**のフィールドを編集できるのは SotaAgents 運営チームのみです。組織のオーナーや管理者は編集できません。

#### クレジットパッケージ（Business・Enterprise のみ）

Business および Enterprise プランでは、組織のオーナーと管理者が名前付きのクレジットパッケージを作成できます。各パッケージは、組織の基本単位に適用する倍率で定義されます（基本単位はプランに紐づき、編集できません）。1 つのパッケージが既定として設定され、新規メンバーに自動的に割り当てられます。_Members_ 列は割り当て人数を示します。メンバーがいるパッケージは削除できないため、先に別のパッケージへ再割り当てしてください。無効化しても既存の割り当ては維持されます。

![倍率、credit、member 数、status、割り当て済み package の無効な削除ボタンを表示する Credit Packages table](/manual/assets/product/console-credit-packages-members-20260903.webp)
_Members 列を見ると、割り当て済み package を削除できない理由が分かります。_

#### ローリング 5 時間制限

組織のオーナーと管理者が編集できます。任意の 5 時間のローリングウィンドウ内で 1 ユーザーが消費できるクレジットの上限を設定します。空欄のままにすると無制限です。メンバーが上限に達すると、ウィンドウが進むまで以降のリクエストはブロックされます。すべてのプランで利用できます。

### Member Allocation（メンバー割り当て）

全組織メンバーの消費クレジット、割り当てクレジット、残高、進捗バーを表示するページネーション付きのテーブルです。赤くハイライトされた行は割り当て超過（消費が割り当てを超過）を示します。

![各メンバーの credit 使用量と残高を表示する Member Allocation タブ](/manual/assets/product/console-credits-allocation-20260813.webp)
_Member Allocation は各人の使用量と残りを示します。_

- **検索とフィルター** — 名前、ロール（Owner / Admin / Member）、または credit package で絞り込めます。
- **パッケージの割り当て** —（Business・Enterprise のみ、組織のオーナー / 管理者）メンバーに個別のパッケージを割り当て、既定パッケージを上書きします。

![Member table の上で credit-package filter を開いた Member Allocation](/manual/assets/product/console-credit-package-filter-20260903.webp)
_Package filter で同じ allocation policy のメンバーをまとめて確認できます。_

### Credit Alerts（クレジットアラート）

ワークスペース単位のクレジットアラートを設定すると、利用量がしきい値を超えた際に管理者へメールで通知されます。アラートは設定可能なローリング時間ウィンドウ（1〜24 時間）に基づいて発火します。

1. #### ワークスペースを選択する

   _Console → 対象の組織 → Credits → Credit Alerts_ に移動し、ドロップダウンから設定対象のワークスペースを選択します。

2. #### 監視ウィンドウを設定する

   _Window (hours)_ に 1〜24 の値を入力します。このローリングウィンドウ内のクレジット消費がチェックされます。

3. #### しきい値を設定する

   _Warning_ しきい値、_Critical_ しきい値のいずれか、または両方を ON にし、それぞれのクレジット量を入力します。Critical のしきい値は Warning より大きい値にする必要があります。

4. #### 追加の通知先を設定する（任意）

   既定のワークスペース管理者に加えて通知するメールアドレスを入力します（カンマまたは改行区切り、最大 10 件）。

5. #### 保存する

   「Save」をクリックします。設定したウィンドウ内でワークスペースがしきい値を超えると、メールアラートが送信されます。

### Credit Logs（クレジットログ）

すべてのクレジット取引を記録する追記専用の台帳です。期間（30 日 / 90 日 / カスタム）、プロバイダー（チャット、Knowledge Base、Office App、Web Search、CAD、Remagine、サンドボックスなど）、ユーザー、フリーテキストで絞り込め、CSV にエクスポートできます。組織の管理者とオーナーのみ閲覧できます。

各エントリーには、タイムスタンプ、ユーザー、プロバイダー、消費クレジット、USD コスト、取引後の残高が記録されます。

### Guest Credits

Public Deployment 専用の別 pool です。Owner/Admin は add-on を確認して workspace guest allocation を管理し、SotaAgents 運営チームは add-on lifecycle と pool configuration を管理します。Allocation が尽きると、新しい guest session または turn が拒否される場合があります。

### チャットモデル

**Chat Models** タブ（_Console → 対象の組織 → Chat Models_）では、組織全体で利用可能な AI モデルの制御と、組織既定モデルの設定を行います。

![組織のデフォルト、選択中の model 数、provider フィルター、credit 倍率付きの model 行を表示する Chat Models タブ](/manual/assets/product/console-chat-models-20260813.webp)
_Chat Models は、組織が公開する model と既定の model を決めます。_

### 利用可否

組織の allow-list でメンバーが選択できる model を管理します。Platform-restricted model は chat picker に表示されません。権限のある Owner/Admin はここで access request の送信または取消ができ、承認された grant だけが model を利用可能にします。Access が付与されると組織の Owner/Admin にメールが送信されます。

### 組織の既定モデル

1 つのモデルを組織の既定として設定します。自分でモデルを固定していないメンバーには、チャット入力欄でこのモデルが事前選択されます。

> [!NOTE]
> 離脱前に保存を
>
> 変更は「Save」をクリックするまで反映されません。未保存の編集がある場合、ページ下部に保存バーが表示されます。

### セキュリティ

**Security** タブでは、認可された role が Enterprise SSO と **IP Access** を設定します。どちらも plan/role gate の対象です。

### IP Access

信頼する IPv4 CIDR を追加して organization IP policy を有効にします。有効な rule の外からの request は `ORG_IP_DENIED` で拒否され、workspace shell に access-denied notice が表示されます。許可された network へ移動するか、admin に rule 修正を依頼してください。

> [!WARNING]
> Enterprise プランが必要です
>
> SSO の設定と強制には Enterprise Cloud サブスクリプションが必要です。既存プロバイダーの削除と強制の解除は、どのプランでも実行できます。

### SSO プロトコル

2 つのプロトコルから選択します。

| プロトコル | 入力する情報 |
| --- | --- |
| OIDC | Issuer URL、Client ID、Client Secret。任意でカスタム Discovery Endpoint（既定は `issuer/.well-known/openid-configuration`）。フォームに表示される _Callback URL_ を IdP 側の許可リダイレクト URI に登録してください。 |
| SAML | IdP Entry Point URL、IdP Issuer、IdP 証明書（PEM）。任意で IdP メタデータ XML の貼り付けも可能です。フォームに表示される _ACS URL_・_SP Entity ID_・_SP Metadata URL_ を IdP に登録してください。 |

> [!NOTE]
> シークレットは書き込み専用です
>
> Client Secret（OIDC）と証明書（SAML）は保存後に再表示されません。フォームには設定済みかどうかだけが表示されます。差し替える場合は値を再入力してください。

### メールドメイン

組織で使用するメールドメイン（例：`company.com`）を追加します。SSO の強制を有効にするには、事前にドメインの検証が必要です。

#### 検証方法

| 方法 | 仕組み |
| --- | --- |
| DNS TXT | ドメイン追加時にチャレンジトークンが生成されます。`_sotaagents-sso-verify.<domain>` にトークンを含む DNS TXT レコードを作成し、「Verify DNS」をクリックします。 |
| Manual | SotaAgents 運営チームがドメイン申請を確認し、承認または却下します。 |

### SSO のテスト

**Test SSO** をクリックすると、設定した IdP との実際のラウンドトリップが開始されます。結果はインラインで表示されます。強制を有効にするには、この接続テストに合格している必要があります。

### SSO の強制

_Enforce SSO_ トグルを有効にすると、メンバーは設定済みの IdP を通じた認証が必須になります。有効化には次の条件をすべて満たす必要があります。

- プロバイダーが保存済みであること。
- 1 つ以上のドメインが検証済みであること。
- 現在の設定で SSO 接続テストに合格していること。

> [!WARNING]
> ロックアウトされた場合
>
> 強制が有効な状態で IdP の設定が不正になった場合は、サポートにご連絡ください。SotaAgents 運営チームがリカバリー用エンドポイント経由で強制を解除し、アクセスを復旧できます。

### ガードレール

ガードレールは、アシスタントを誘導・乗っ取ろうとする入力を遮断し、個人情報を隠し、ツールや文書から取り込んだ内容を検査します。設定はワークスペースのナビゲーションにある **Guardrails** から開きます。開けるのは権限を持つ担当者だけです。

### ガードレールが検査する対象

ワークスペース側で設定できる検査は 2 つあります。これに加えて、モデルの思考内容に対する保護がプラットフォーム側で常に適用されます。

| 設定項目 | 検査対象 | 内容 |
| --- | --- | --- |
| _User input enforcement_ | 利用者のメッセージ | 利用者が入力した文章を、アシスタントが回答する前に検査します。メールアドレスや電話番号などの個人情報をここで隠すこともできます。 |
| _Tool output enforcement_ | ツールや文書の内容 | ツール、アップロードしたファイル、Web、ナレッジベースから取り込んだ文章を、使用する前に検査します。 |
| _Model reasoning_ | 画面への送信前・保存前のモデルの思考内容 | プラットフォーム側の検査が、認証情報や個人情報を隠したうえで思考内容を画面に送り、保存します。ワークスペースで強度を選ぶ項目ではありません。 |

### 各モードの動作

モードは _User input enforcement_ と _Tool output enforcement_ それぞれに個別に選びます。各モードの動作は次のとおりです。

| モード | User input enforcement | Tool output enforcement |
| --- | --- | --- |
| Off | ワークスペースで選んだ入力検査を実行しません。 | ワークスペースで選んだツール出力の検査を実行しません。 |
| Observe（記録のみ） | 該当箇所をログに記録するだけで、書き換えも遮断もしません。 | 該当箇所をログに記録するだけで、書き換えも遮断もしません。 |
| Redact（マスク） | 個人情報（例：メールアドレス）を、アシスタントが読む前に隠します。 | 該当箇所を可能な範囲で隠し、そのまま処理を続けます。 |
| Enforce（ブロック） | リスクのあるメッセージ（例：制限を外そうとする指示）を遮断します。個人情報は引き続き隠されます。 | 通常は危険な内容を渡さず、警告を表示します。Knowledge Base アプリの実行結果は「隠す」までが上限です。記録や隠す処理は行いますが、取得した文書そのものは遮断しません。 |

> [!NOTE]
> プラットフォーム側の保護は止まりません
>
> ワークスペースの一括スイッチと _Off_ が無効にするのは、ワークスペースで選んだ検査だけです。プラットフォームが必須としている検査は動き続け、設定画面では _Enforced by the platform_ と表示されます。

### ワークスペースでガードレールを有効にする

1. #### 設定画面を開く

   管理画面でワークスペースを開き、サイドバーの _Guardrails_ を選びます。項目が表示されない場合は、いまの権限では閲覧できません。

![プラットフォーム必須の保護、モデル思考内容のマスク、User input を Enforce、Tool result を Redact に設定し、11 個中 2 個の検査を選んだ Guardrails 画面](/manual/assets/product/ws-guardrails-20260813.webp)
_設定画面はプラットフォーム必須の保護とワークスペース側の設定を分けて表示します。この例では入力を遮断、ツール結果を隠す設定にし、11 個中 2 個の検査を選んでいます。_

2. #### 一括スイッチをオンにする

   _Enable guardrails for this workspace_ を切り替えます。これはワークスペースで選んだ検査を制御するもので、プラットフォーム必須の保護は切り替えに関係なく有効です。

3. #### 強度を選ぶ

   _利用者のメッセージ_ と _ツールの出力_ に対する動作をそれぞれ設定します（Observe / Redact / Enforce）。各選択肢の下に説明が表示されます。

4. #### 実行する検査を選ぶ

   このワークスペースで使う検査にチェックを入れます（検索や絞り込みもできます）。何も変更しなければ、推奨の初期設定がそのまま使われます。一部の検査は値の入力が必要です（禁止語の一覧、競合名、許可するトピック）。入力しないと保存できません。

5. #### 保存する

   _Save_ をクリックします。以降の新しいメッセージから、すぐに反映されます。_Export rules (CSV)_ で現在の設定をダウンロードできます。

### 利用できる検査

_推奨_ と付いた検査は初期状態で有効です。最後の 3 つは、照合するための一覧を利用者が入力します。

![遮断・マスク・記録のみ・モデル思考内容の記録を、段階・検査名・マスク済みの抜粋とともに一覧表示した Recent blocks の画面](/manual/assets/product/ws-guardrails-events-20260813.webp)
__Recent blocks_ は入力・ツール結果・モデルの思考内容での検出を、機密の本文を表示せずに記録します。_

| 検査 | 防ぐ対象 | 入力するもの |
| --- | --- | --- |
| Jailbreak / Prompt Injection | アシスタントを騙す・乗っ取る試み（ドキュメント内の隠し指示を含む） | 不要（推奨） |
| Secrets & Credentials | メッセージ内の API キー・パスワード・トークン | 不要（推奨） |
| Personal Data (PII) | メール・電話番号などの個人情報（マスク） | 不要（推奨） |
| Toxic Language | 有害・差別的・嫌がらせの言葉 | 不要 |
| Profanity | 下品・卑猥な言葉 | 不要 |
| NSFW Text | 性的・職場に不適切なテキスト | 不要 |
| Toxic Language（多言語） | 日本語・ベトナム語を含む多言語の有害な言葉 | 不要 |
| Gibberish / Nonsense | 意味をなさない・文字化けした入力 | 不要 |
| Unusual / Manipulative Prompt | 誘導的・ソーシャルエンジニアリング的なプロンプト | 不要 |
| Banned Words | 許可しない単語・フレーズ | 単語リスト |
| Competitor Mentions | 指定した競合への言及 | 競合名 |
| Restrict to Topics | 許可したトピック以外の内容 | 許可トピック |

### 閲覧・編集できる権限

ガードレールの権限は 1 種類だけです。設定画面を開ける人は、そのまま変更もできます。閲覧のみの権限はなく、設定内容・検査の一覧・_Recent blocks_ の記録は、いずれもワークスペースの管理権限に含まれます。

| 役割 | ガードレールの操作 |
| --- | --- |
| 組織オーナー（Organization Owner） | 可 — 組織内のすべてのワークスペース |
| 組織管理者（Organization Admin） | 可 — 組織内のすべてのワークスペース |
| ワークスペース管理者（Workspace Admin） | 可 — 自分が管理するワークスペース |
| ワークスペースのメンバー（Workspace Member） | 不可 — _Guardrails_ の項目自体が表示されません |
| ワークスペースの管理権限を持たない組織メンバー | 不可 |

組織オーナーと組織管理者は、すべてのワークスペースで自動的に管理権限を持ちます。そのためどちらかを与えると、組織全体のガードレールを変更できる権限を渡すことになります。1 つのワークスペースだけに限定したい場合は、組織メンバーのままにして、そのワークスペースの管理者として追加してください。なお、お問い合わせ対応の際に SotaAgents のサポート担当がこの画面を確認する場合があります。

> [!NOTE]
> メニューを隠しているだけではありません
>
> サイドバーに項目が出ないのは、システム側で適用している判定をそのまま反映しているためです。ワークスペースの管理権限がない利用者の操作は拒否されるので、別の経路からガードレールを見たり変更したりすることはできません。

### プラットフォームが必須とする検査

上の表のうち 2 つは、初期状態でプラットフォーム必須です。一括スイッチがオフでも、強度が _Off_ でも、すべてのワークスペースで動作し、チェックボックスもありません。

| 検査 | 設定できる人 |
| --- | --- |
| Jailbreak / Prompt Injection | プラットフォーム — 常に有効（ツールや文書の出力の検査も含みます） |
| Secrets & Credentials | プラットフォーム — 常に有効 |
| Personal Data (PII) | 利用者 — ただしモデルの思考内容では、プラットフォームが必ず隠します |
| 残り 9 つの検査 | 利用者 — ワークスペースごとに、使う検査と強度を選べます |

モデルの思考内容もプラットフォームが管理します。どの検査を選んでいても、そこでは認証情報と個人情報が隠されます。また、必須の行はワークスペースの強度ではなくプラットフォーム側の強度に従います。そのため、ワークスペースを _Observe_ にしていても、必須の検査は遮断していることがあります。

必須の検査はご利用の環境の管理者が決める設定です。最終的な内容は設定画面で確認してください。_Enforced by the platform_ の下に並んでいるものは変更できず、チェックボックスが付いているものは利用者側で設定できます。この区画が表示されない場合、その環境ではプラットフォーム側の保護が無効になっており、12 個すべてをワークスペースで設定できます。

### 記録の保持期間

_Recent blocks_ の記録は、初期設定で **30 日間** 保持され、期間を過ぎた項目は自動的に削除されます。この期間はご利用の環境ごとの設定です。専用環境や自社運用の環境では別の値になっている場合があるため、監査などで正確な期間が必要なときは運用担当にご確認ください。

各記録には、日時、どの段階か（利用者のメッセージ、ツールの出力、モデルの思考内容）、どうなったか（遮断・マスク・記録のみ・判定できず）、一致した検査、そのときの強度が残ります。検出された本文そのものは保存されません。保存されるのは、本文の長さと照合用の短い符号、そして最大 280 文字のマスク済みの抜粋だけです。認証情報と個人情報の検出では、その抜粋も残しません。検査が見つけた内容が記録から漏れないようにするためです。

> [!NOTE]
> 記録は長期保管用ではなく、原因確認用です
>
> 直近の出来事について「どのメッセージが、どこで、どの検査で止まったか」を確認するための画面です。保持期間より長くガードレールの記録を残す必要がある場合は、期限が来る前に必要な分を控えてください。_Export rules (CSV)_ で出力されるのは設定内容であり、記録ではありません。

## 開発者ガイド

SotaAgents アプリの作成、テスト、デプロイ、リリース、App Store 公開までを一貫した流れで説明します。

### アプリでできること

SotaAgents アプリは、組織とワークスペース内でプラットフォームを拡張する、バージョン管理された Capability パッケージです。**Tool**、**Skill**、Native UI、tool-result renderer、hook、event、prompt、スコープ付きデータアクセスを提供できます。プラットフォームは identity、インストール、認可、environment 選択、asset 配信、監査を管理し、アプリは業務ロジックと固有データを管理します。

### なぜアプリという仕組みがあるのか

SotaAgents のアシスタントは一つですが、どんなアシスタントも御社の CAD 図面規格、法務レビュー手順、社内 ERP の API までは知りません。あらゆる業務領域に合わせて製品本体を肥大化させる代わりに、プラットフォームは意図的に「未完成」に設計されています。足りない capability を各チームが足す手段がアプリであり、プラットフォームの側がそれに合わせて形を変えます。法令文書レビュー、knowledge base、CAD 生成、Office 文書作成、Web 検索——同じ shell がこれらすべてを支えられるのは、その domain logic がどれも core に入っていないからです。

具体的には、アプリは `manifest.yaml` を含むディレクトリであり、計算処理・非公開 credential・外部 API・永続的な業務データが必要な場合には、自前で host する HTTP service を伴います。プラットフォームがコードを調べて機能を推測することはありません。manifest が宣言したものだけを、解決された organization・workspace・environment に対してのみ公開し、宣言のないものはすべて拒否します。

結果として二つのことが起こります。アシスタントは本来持ち得ない能力を獲得します——社内システムを照会・更新する **tool**、業務手順を教える **skill**、workspace 内で自社データを描画する **screen**。そしてチームは、SotaAgents 本体に一切手を入れずに、自分たちの release cadence・言語・runtime でそれらを出荷できます。

> [!NOTE]
> アプリは拡張の単位であり、plugin script ではありません。
>
> Version を持ち、組織単位でインストールされ、明示的な workspace override がない限りすべての workspace で既定 enabled となり、リクエストごとに exact environment へ解決されます。サードパーティの domain logic を first-party 機能の隣で安全に動かせるのはそのためです。

Tool

アシスタントが呼び出す型付き backend action。

Skill

アシスタントを導く再利用可能な指示と workflow。

Native UI

Workspace page、admin screen、inline view、artifact renderer。

App data

認可され、environment ごとに分離された storage/backend access。

![インストール済みアプリとカタログを表示する組織 App Store](/manual/assets/developer/app-store-catalog.webp)
_アプリは組織レベルで検出・インストールし、workspace では既定 enabled を継承し、必要に応じて明示的に上書きします。_

![Native workspace page として動作する Knowledge Base](/manual/assets/developer/app-workspace-native-ui.webp)
_Production アプリは platform の navigation、identity、access control を維持しながら完全な workspace experience を提供できます。_

![SotaAgents conversation 内で展開された Web Search tool result](/manual/assets/developer/web-search-tool-result.webp)
_App action の query、visual preview、source card が conversation 内に直接表示されます。_

![SotaAgents conversation の横で開いた Office App presentation artifact](/manual/assets/developer/slide-artifact.webp)
_Workspace panel に slide artifact を開いても、元の conversation と artifact card を同時に確認できます。_

### App experience が表示される場所

| Manifest surface | 用途 | 代表的な host |
| --- | --- | --- |
| `page` | Navigation と state を持つ継続 workflow。 | Workspace または admin route。 |
| `tool-view` | 一つの tool invocation と結果を conversation 内で表示。 | Tool result part。 |
| `message-part` | App 固有の構造化 message content を inline 表示。 | Conversation message part。 |
| `artifact` | 再表示、確認、export できる永続 output。 | Artifact panel。 |
| `card` | App content の compact summary または entry point。 | Host が提供する card slot。 |
| `composer-action` | Composer に隣接する compact action。 | `chat.composer.actions`。 |
| `composer-panel` | Active draft を読み取り、atomic に編集できる contextual UI。 | `chat.composer.panel`。 |

`useComposer` は意図的に `composer-panel` 内でのみ利用できます。`composer-action` は独立した surface であり、draft を直接編集する権限は持ちません。

> [!NOTE]
> Platform は常に exact environment を解決します。
>
> Tool、screen、asset、data request は Development、Staging、Production のいずれかに属し、別 environment への暗黙的 fallback はありません。

### Architecture philosophy

SotaAgents は **platform control plane** と **app data plane** を意図的に分離します。Platform は user、organization、workspace、installation、selected environment、exact artifact、capability を理解し、app backend は検索、CAD、専用 API、business rule など domain を理解します。

![SotaAgents が request を exact app environment に解決する architecture diagram](/manual/assets/developer/app-architecture.svg?v=2)
_一つの authority decision が exact artifact、UI bundle、backend、environment data を bind します。_

### App に専用 backend が必要な理由

- **独立 ownership：**Core に domain code を追加せず独自 cadence で ship。
- **Security boundary：**Credential と integration を server-side に置き、signed context だけを受け入れる。
- **Data boundary：**Domain に合う database、retention、residency、scaling を選択。
- **Operational isolation：**他 app と分離して scale、fail、recover。

> [!WARNING]
> 専用 backend は専用 identity system ではありません。
>
> Browser 由来の任意 actor/workspace/environment を信頼せず、signed Sota request の exact context を使用します。

### アシスタントはどのように tool を呼ぶのか

Manifest への tool 宣言は物語の半分にすぎません。ここから先が、その宣言を runtime にプラットフォームがどう扱うか——アプリを単なる host 済み web service 以上のものにしている部分です。

1. #### Tool が model に提示される

   Workspace が app surface を解決すると、公開済みの各 tool は `app_<appId>_<toolName>` という名前の、model が呼び出せる function 一つになります。Development と Staging は environment を挟み（`app_my-app_stg_example`）、Production は省くため、Production で model が学ぶ名前は簡潔に保たれます。model 向け名称が持てない文字——`documents.query` のようなドットを含む——はアンダースコアになり、64 文字を超える名前は短い hash 接尾辞を付けて切り詰められ、二つのアプリで衝突した場合は数字が付きます。model が読む description は manifest の `description` に `App: <appId>. Runtime tool: <name>.` を連結したものであり、`inputSchema` はそのまま parameter schema として model に渡されます。曖昧な description や緩い schema が即座に tool 選択の精度を落とすのは、model の判断材料がそれで全部だからです。

2. #### Platform が解決し認可する

   Request が SotaAgents を出る前に、arguments は input schema で検証され、organization、workspace、installation、environment、そして適用される exact artifact が解決されます。その artifact に公開されていない tool、あるいはその workspace にインストールされていないアプリは、ここで拒否されます——backend には一切到達しません。

3. #### Signed request が backend に届く

   Platform は、有効な environment 向けに解決された `service.baseUrl` の宣言済み path へ、server-to-server の HTTP request を送ります。Development では同じ request が `sota dev` の tunnel を通って手元のマシンに届きます。この経路に browser は介在しないため、backend が公開インターネットからユーザーに到達可能である必要はありません。

4. #### Backend が検証し、処理し、JSON を返す

   Token を検証し、domain の処理を行い、JSON を返します。非 2xx、JSON として不正な body、timeout はいずれも tool の失敗として扱われます。

5. #### 結果が conversation に戻る

   Platform は tool result を tool の output part として conversation に stream し、記録します。`surface: tool-view` の UI contribution が `toolNames` にその tool を含んでいれば、素の結果の代わりに React module が描画されます。model が見るのは同じ結果の簡潔な JSON 射影です。

### Platform が送る request

Body は envelope です。model の arguments は `body.input` に入れ子になっており、scaffold の route が `request.body` ではなく `request.body.body.input` を読むのはそのためです。

HTTP

```
POST https://my-app.example.com/tools/example
content-type: application/json
authorization: Bearer <invocation JWT>
x-sota-core-token: <delegated Core token>   # アプリが Core tool grants を宣言した場合のみ

{
  "requestId": "01K...",
  "organizationId": "6a66...",
  "workspaceId": "6a66...",
  "appId": "my-first-project-demo",
  "hook": { "type": "tool", "name": "example" },
  "body": {
    "input":   { "message": "hello" },
    "context": { "organizationId": "…", "workspaceId": "…", "userId": "…",
                 "conversationId": "…", "agentId": "…", "toolCallId": "…", "config": {} }
  }
}
```

> [!WARNING]
> 信頼するのは token であって envelope ではありません。
>
> Body 内の `organizationId`、`workspaceId`、`context` は log と debug のための便宜的な値です。認可判断はすべて、検証済み JWT の claim から行ってください。署名されているのはそちらだけです。

### Invocation token

`Authorization` header は、この 1 回の呼び出しのために発行された短命の EdDSA 署名 JWT を運びます。Backend は `<core origin>/.well-known/jwks.json` で公開される platform の公開鍵で検証します。アプリは Sota の秘密鍵を持たず、自ら token を発行することもありません。

| 項目 | 値 |
| --- | --- |
| Algorithm / `typ` | `EdDSA`（Ed25519）、header type `sota-invocation+jwt` |
| `iss` | `sota/invocation-token` |
| `aud` | 自身の `appId`。別アプリ向けの token は拒否します |
| 有効期間 | 60 秒、時刻ずれ許容 30 秒 |
| `oid` / `wid` | 呼び出しが属する organization と workspace |
| `sub` | Actor がいる呼び出しの実行ユーザー |
| `iid` | 互換用の opaque install identity。Prefix から environment を推測しません。 |
| `ae` / `aei` / `ag` | 正確な App Environment 名、environment identity、Backend Access Generation。3 claim が一つの resolved backend に認可を bind します。 |
| `aer` | 署名済み exact execution reference。Persist/replay 時は新しい artifact を resolve せず、この reference を保持します。 |
| `scp` | 現行 scope family は `tool:<name>`、`route:prompt:<name>`、`route:systemPrompt:<name>`、`event:<name>`、`route:artifact:<name>`、`route:resolver:<path>`、lifecycle route scope、`app:http` です。各 endpoint は、その surface に発行された exact scope を必ず要求します。 |
| `rid` | Envelope の `requestId`。Log 突き合わせ用 |

各 route には最小の scope を要求してください。`/tools/example` の handler が求めるべきは `tool:example` であり、それより広い権限ではありません。Scaffold の `src/backend/sota-auth.ts` に、issuer・audience・algorithm・type・有効期限・tenant claim・scope という一連の検証が、再利用可能な middleware として揃っています。

### Response の形

通常の JSON HTTP response を返します。Sota 専用の wrapper を組み立てる必要はありません。

| 結果 | Platform の扱い |
| --- | --- |
| 2xx ＋ JSON body | 成功。Body がそのまま tool result になります。 |
| 非 2xx | 失敗。Body が `{ "code": "…", "message": "…" }`（任意で `details`、`hint`）なら、汎用メッセージの代わりにその値がそのまま伝わります。成功を装った error body ではなく実際の status code を返してください。 |
| JSON として不正な body | `VALIDATION_ERROR` で失敗。 |
| Deadline 内に応答なし | `TIMEOUT` で失敗。 |

`outputSchema` は runtime の response に対しては検証されません。検証されるのは publish 時であり、そこで version 間の breaking change 検出に使われます。出力は境界で自分で検証してください。Schema は runtime の防御壁ではなく、consumer と renderer に対する約束としての contract です。

予約された 2 つの任意 key により、一つの結果が二つの読み手に対応できます。model 向けの簡潔な結論と renderer 向けの詳細 payload を同じ response に入れ、`_sota.modelOutput` で model にまったく別の射影を渡すか、`_sota.modelProjection.omitKeys` で renderer 専用 key を model の読む範囲から外します。model 可視の射影は約 32,000 文字で切り詰められるため、生の文書ではなく結論・ID・件数・citation に留めてください。

### Lifecycle と environment

![ライフサイクル図：development の live session が immutable Staging artifact になり、sota release がその同じ artifact を Production に promote する。data partition は分離され、visibility は独立して管理される](/manual/assets/developer/app-lifecycle.svg?v=2)
_Development は個人の live session — local UI/backend、選択した 1 workspace、immutable artifact なし。`sota deploy` が Staging artifact を packaging し、`sota release` がその同じ artifact を Production に promote します。Data partition は分離されたままで、visibility は独立して管理されます。_

| Environment | 作成 | 利用者 | データ |
| --- | --- | --- | --- |
| Development | `sota dev` | Live session owner かつ workspace member | 個人 Dev partition |
| Staging | `sota deploy` | Exact environment が install/enable 済みの owner/contributor | 独立 Staging partition |
| Production | `sota release` | Visibility と workspace enablement で許可された user | Production partition |

> [!WARNING]
> Release は code を移し、業務データは移しません。
>
> Staging data は Production に promote されません。両 binding が同じ外部 backend を使う場合、isolation はアプリ側の責任です。

![Staging、Production、App Store status を表示する App Registry](/manual/assets/developer/app-registry-lifecycle.webp)
_App Store listing は Production release と分離された governance state です。_

### Sota CLI

**Sota CLI** は正式な developer interface です。Project scaffold、manifest 検証、UI contract build、Development session、Staging artifact、Production promote を扱います。

ターミナル

```
curl -fsSL https://app.sotaagents.ai/cli/install.sh | sh
sota --version
sota login
sota whoami
sota update
```

Windows PowerShell:

PowerShell

```
irm https://app.sotaagents.ai/cli/install.ps1 | iex
```

### Command 一覧

インストール済み version の正確な一覧は `sota --help` で確認できます。すべての command が global option `--cwd <dir>`、`--origin <url>`、`--manifest <path>`、`--json`、`--verbose` を受け付けます。

| 分類 | Command | 内容 |
| --- | --- | --- |
| Session | `login`、`logout`、`whoami` | このマシンに、一つの origin に紐づく scope 付き app-developer session を許可します。`login --manual` は headless／リモート環境向けの copy/paste 認可です。 |
| Scaffold | `init [dir]`、`add [features…]` | Project を作成、または既存 project に capability を追加します。どちらも additive で、既存ファイルを保持し衝突を報告します。 |
| Config | `config set-origin <url>`、`config show`、`config set <key> <value>` | `.sota/config.json` を管理します。`set-origin --env <name>` は environment ごとの origin を保存し、`deploy -e`／`validate -e` がそれを選択します。 |
| Manifest | `manifest schema`、`manifest examples`、`manifest explain <topic>`、`manifest diff <left> <right>` | Server が検証に使う JSON Schema の出力、実例の表示、単一 field の解説、二つの manifest の差分。 |
| 検査 | `validate`、`build`、`contracts ensure`、`env template`、`env check` | Server 側 manifest preflight（offline 時は local lint）、build 済み output の packaging、App UI type contract の materialize、manifest の `env` 宣言からの `.env.example` 生成・確認。 |
| 開発 | `dev`、`dev status`、`dev stop` | Local backend とローカル build 済み asset に紐づく個人 Development session の公開・確認・停止。 |
| 出荷 | `deploy`、`release` | Immutable artifact を一つ build して Staging で動かし、Staging が動かしているその artifact をそのまま Production へ promote します。 |
| 参照 | `status`、`logs`、`workspaces`、`catalog`、`installed --org <id>`、`app info <slug>`、`app config` | Platform が保持する現状の読み取り：現在の environment、backend log、開発可能な workspace、app catalog、project 単位の app config。 |
| 保守 | `update`、`update skills`、`docs [topic]` | Binary の更新、app project の bundled development skill 更新、version 対応 documentation の表示。 |

現在の option には、exact schema major を取得する `manifest schema --version <major>`、Staging artifact を同じ command で Production に promote する `deploy --release`、log を exact app environment に絞る `logs --environment`／`--environment-id` も含まれます。

> [!NOTE]
> 別 deployment を対象にする
>
> Global `--origin` を使用します。例：`sota --origin https://v4.stg.sotaagents.ai login`。以後の lifecycle command でも同じ origin を使うか、`sota config set-origin` で一度保存してください。

> [!WARNING]
> CLI がアプリを build することはありません。
>
> `sota build` は既存の output を packaging するだけで、frontend／backend の build を置き換えません。`sota dev` も process の起動・停止を行いません。まず source を build し、その後 CLI に packaging・publish・tunnel を任せてください。

### Project 作成

ターミナル

```
sota init my-app --features all
cd my-app

# terminal 1 — 自分の watcher
npm run dev

# terminal 2 — Development session
npm run dev:sota
```

`sota init` は manifest schema v3 対応 scaffold を作ります。`--features` なしでは capability を対話選択でき、`--features admin-screen,skill,backend,tool,tool-result-ui`（または `all`）で事前指定できます。後から `sota add` で追加できます。

### Scaffold feature

| Feature | 追加されるもの | 同時に含まれる |
| --- | --- | --- |
| `admin-screen` | Local 開発用の watch build を備えた React + TypeScript + Vite の native page。 | — |
| `skill` | Content-backed な `SKILL.md` contribution。Backend は不要です。 | — |
| `backend` | Request log、Core JWT 検証、health route を備えた最小の Express service。 | — |
| `tool` | Agent 向け tool 一式：manifest entry、input/output JSON Schema、応答する backend route。 | `backend` |
| `tool-result-ui` | Tool に加えて、conversation 内でその結果の下に描画される React surface。 | `tool`、`backend` |

> [!NOTE]
> Scaffold は利便性であって要件ではありません。
>
> Express、npm、TypeScript を使っているのは広く理解されているからで、platform が要求しているからではありません。Platform の contract は素の HTTP と manifest だけです。宣言した route を提供でき invocation token を検証できる言語・runtime であれば、いずれも正規の app backend です。

### Template の構成

| Path | 用途 |
| --- | --- |
| `manifest.yaml` | Identity、version、contribution、runtime binding、health、locale、platform compatibility。 |
| `src/backend/` | 認証検証、health、tool route を含む service。 |
| `src/ui/` | UI slot 向け Native React module と style。 |
| `src/skills/` | Content-backed skill。 |
| `src/schemas/` | Tool input/output の JSON Schema。 |
| `src/locales/` | ローカライズ文字列。 |
| `.sota/app-ui-contracts/` | 生成済み UI contract。手動編集しません。 |
| `.agent/skills/` | Architecture、security、testing、tool、UI の開発 best practices。 |

### Manifest の説明

`manifest.yaml` はアプリと SotaAgents 間の宣言的 contract です。Identity、contribution、backend、load 可能な native module、platform compatibility を記述します。Server が再検証するため、client manifest は authority ではありません。未知の property は即座に拒否されます。正確な JSON Schema は `sota manifest schema`、個々の field の解説は `sota manifest explain contributes.tools` で確認してください。

Root field のうち `manifestSchemaVersion`、`appId`、`version`、`publisher`、`contributes` の 5 つが必須で、それ以外はすべて任意です。

YAML

```
manifestSchemaVersion: 3
appId: my-first-project-demo
version: 1.0.0
displayName: "My First Project Demo"
description: "SotaAgent app."
publisher:
  id: local-dev
  displayName: "Local Dev"
  contact: dev@local-dev.example

contributes:
  skills:
    - name: example
      description: Example content-backed skill.
      appendsTo: system
      content: src/skills/example
      timeoutMs: 3000
      failure_mode: skip
  tools:
    - name: example
      description: Example tool that echoes its input and verified tenant context.
      route: POST /tools/example
      inputSchema: src/schemas/tool-input.schema.json
      outputSchema: src/schemas/tool-output.schema.json
      timeoutMs: 15000
      failure_mode: abort
  ui:
    - id: admin-screen
      kind: nativeModule
      surface: page
      slot: admin.workspace.tab
      sectionId: my-first-project-demo
      label: Admin screen
      route: /admin/*
      module:
        entry: dist/ui/app.js
        export: AdminScreen
        styles: dist/ui/app.css

service:
  baseUrl: https://my-first-project-demo.example.com
health:
  url: https://my-first-project-demo.example.com/health
  intervalSeconds: 60
platform: ^1.2.0
locales:
  default: en
  files:
    en: src/locales/en.json
```

- **Identity** は安定値です。`appId` を永続的な public identifier として扱います。
- **Version** は artifact ごとに immutable です。Bytes を変更したら version を上げます。
- **Contribution** だけが platform に公開可能です。
- Environment overlay は `local`、`stg`、`prod` という任意の override です。Root service が hosted default、`local` は `sota dev` 用です。Global `--origin` は SotaAgents deployment を選び、各 command の `-e` は保存済み profile／overlay を選択します。

各 native UI surface と public runtime API は、この manifest reference の後に専用 page として説明します。

YAML

```
service:
  baseUrl: https://my-app.example.com
health:
  url: https://my-app.example.com/health
  intervalSeconds: 60

environments:
  local:
    service:
      baseUrl: http://127.0.0.1:8787
    health:
      url: http://127.0.0.1:8787/health
  stg:
    service:
      baseUrl: https://stg.my-app.example.com
  prod:
    service:
      baseUrl: https://my-app.example.com
```

> [!WARNING]
> environments.local
>
> Base manifest は deploy 可能なアプリを記述するものです。Root の `service` に `127.0.0.1` を書くと拒否されます。また deploy 用 base URL が `.invalid` のままなら、実際の host 済み backend が未設定ということです。

### Tool を宣言する

Tool は、アシスタントが backend に到達するための入口です。`contributes.tools` に一度宣言すれば、model に何が提示されるか、request がどう route されるか、どう認証されるか、どれだけ時間を使えるか——その他すべてを platform がその宣言から導きます。Schema は閉じているため、宣言にない key は validation で失敗します。

| Field | 必須 | 規則 |
| --- | --- | --- |
| `name` | 必須 | 安定した public identifier。先頭は小文字、以降は英数字とハイフン。ドットで区切ることもでき（例：`documents.query`）、各セグメントは最大 64 文字。Release 後は変更しないでください。Prompt、renderer、保存済み conversation がこの名前を参照します。 |
| `description` | 必須 | 空不可。tool を呼ぶかどうかを model が判断するときに読むテキストそのものです。いつ使うか、backend が何をするか、何が返るか、前提条件は何かを書いてください。名前の言い換えでは不十分です。 |
| `route` | 必須 | `METHOD /path` 形式。method は `GET`、`POST`、`PUT`、`PATCH`、`DELETE` のいずれかで、path は `/` 始まり。Path は有効な environment の `service.baseUrl` に対して解決され、その origin の外には出られません。`POST` を宣言してください。アシスタントの呼び出し経路は arguments を JSON body で送り、scaffold も各 system app も `POST /tools/<name>` を使います。 |
| `inputSchema` | 必須 | アプリ内の JSON Schema ファイルへの path、または inline の schema object。明示的な `required`、`additionalProperties: false`、上限のある string／array、既知の mode には enum を推奨します。 |
| `outputSchema` | 必須 | Input schema と同じ形式。結果が単純でも必須です。backend が守るべき contract を文書化します。 |
| `timeoutMs` | 任意 | 正の整数。Artifact 生成時に最大 30,000 ms へ clamp されます。必ず宣言してください。未宣言の tool は host 済み backend では wall-clock の上限を持たず、Development tunnel でのみ 10 分に制限されます。 |
| `failure_mode` | 任意 | `abort` または `skip`。Tool の既定は `abort` です。失敗を失敗として報告すべき場合は `abort`、その contribution が本当に任意で、無くてもアシスタントが誠実に回答できる場合にだけ `skip` を選びます。失敗した書き込みや重要な照会を、体裁の良い応答で隠さないでください。 |
| `searchHint` | 任意 | Tool を見つけやすくする追加キーワード。空不可。 |
| `undoable` | 任意 | Boolean。取り消し可能な action であることを示します。 |
| `configGate` | 任意 | App config の key。その config key が存在する場合にのみ tool が提示されます。 |

宣言が指す schema ファイルは通常の JSON Schema です。Compiler がそれらを解決して artifact に inline するため、参照されたファイルは build／deploy より前に存在している必要があります。Local の smoke test でその route を通らない場合でも同様です。

JSON

```
// src/schemas/tool-input.schema.json
{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "message": {
      "type": "string",
      "minLength": 1,
      "maxLength": 4000,
      "description": "Message for the example tool to echo."
    }
  },
  "required": ["message"]
}
```

Tool を一つでも宣言すると `service` が必須になります。Platform が送信先を知る必要があるためです。Tool 名は一つの manifest 内で一意でなければならず、`surface: tool-view` の UI contribution は `contributes.tools` に実在する名前を `toolNames` に列挙する必要があります。宣言していない tool に紐づく renderer は validator が拒否します。またインストール済みの 2 つのアプリが同じ tool 名の renderer を主張することはできず、後から入ったアプリが競合した名前を失います。

Platform がこの宣言をその後どう扱うか——model が見る名前、signed request、response の contract——は _Architecture philosophy_ を参照してください。

![Resolved surface overview を表示する Staging app detail](/manual/assets/developer/app-surface-overview.webp)
_Exact artifact に宣言された tool、skill、UI slot、prompt、grant だけが公開されます。_

### Workspace page

Workspace page は workspace navigation から開く、アプリ所有の完全な画面です。Core は install 済み lane の current app execution を resolve し、routing と mount boundary を所有して export component を描画します。Boundary 内の表示はアプリ所有であり、Core は artifact launcher、environment badge、use case 固有の control を挿入しません。

YAML

```
contributes:
  ui:
    - id: reports-page
      kind: nativeModule
      surface: page
      slot: workspace.nav
      sectionId: reports
      label: Reports
      icon: chart
      route: /reports/*
      module:
        entry: dist/ui/app.js
        export: ReportsPage
        styles: dist/ui/app.css
```

通常の entry には `workspace.nav`、section placement には `workspace.nav.section` を使います。Route は `/` から始め、`/*` で子 route を許可します。Navigation slot には route または `sectionId` が必要です。

TSX

```
import { useAppContext } from '@sota/platform';

type PageProps = { route?: string; subroute?: string };

export function ReportsPage({ route, subroute }: PageProps) {
  const { workspaceId, ui } = useAppContext();
  return (
    <main>
      <h1>Reports</h1>
      <button type="button" onClick={() => ui.openArtifact('reports.viewer')}>
        Open latest report
      </button>
      <small>Workspace: {workspaceId}</small>
      <small>Route: {subroute ?? route}</small>
    </main>
  );
}
```

Core は選択した app route を `route`/`subroute` props として渡します。App-local router の input に使い、exact execution は route から推測しません。Identity、locale、theme、backend access、lifecycle、host action は platform hook から取得します。

### User settings page

User settings page は Account Settings 内に表示されるアプリ所有のタブです。Core が明示的な active workspace を持ち、その workspace でアプリが install・enable・admit されている場合だけ表示されます。

YAML

```
contributes:
  ui:
    - id: user-settings
      kind: nativeModule
      surface: page
      slot: user.settings.tab
      label: Reports preferences
      icon: settings
      route: /reports/user-settings
      module:
        entry: dist/ui/app.js
        export: UserSettings
        styles: dist/ui/app.css
```

Core は projected page placement から exact contribution を mount し、semantic route を browser URL には書き込みません。選択中のタブだけが mount されるため、タブ切り替えや Settings の close で scoped request が abort され、disposer が実行されます。Unmount 後も draft が必要なら app 側で保存してください。Backend mutation は signed invocation identity を必ず authorize し、タブの表示を security boundary として扱わないでください。

### Admin page

Admin page は同じ native `page` primitive を workspace administration に配置したものです。App 設定と運用 control に使い、通常 member の workflow には使いません。

YAML

```
contributes:
  ui:
    - id: reports-admin
      kind: nativeModule
      surface: page
      slot: admin.workspace.tab
      sectionId: reports
      label: Reports settings
      route: /admin/reports/*
      roles: [OWNER, ADMIN]
      module:
        entry: dist/ui/app.js
        export: ReportsAdmin
        styles: dist/ui/app.css
```

`roles` を宣言し、backend でも authorization を必ず検証します。UI の非表示は security boundary ではありません。

TSX

```
import { useAppFetch } from '@sota/platform';

export function ReportsAdmin() {
  const appFetch = useAppFetch();
  async function save() {
    const response = await appFetch('/settings', {
      method: 'PUT',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ enabled: true }),
    });
    if (!response.ok) throw new Error('Could not save settings');
  }
  return <button type="button" onClick={save}>Enable reports</button>;
}
```

### Tool view

`tool-view` は同じアプリが宣言した tool call の表示を置換または拡張します。空でない `toolNames` で結び、Core は一つの `toolResult` prop を渡して state 変化中も同じ mount を維持します。

YAML

```
contributes:
  ui:
    - id: calendar-result
      kind: nativeModule
      surface: tool-view
      slot: chat.message.inline.below
      toolNames: [readCalendar]
      renderBeforeOutput: true
      module:
        entry: dist/ui/app.js
        export: CalendarResult
```

TSX

```
import type { ToolResultSurfaceProps } from '@sota/platform';

type Input = { from: string; to: string };
type Output = { events: Array<{ id: string; title: string }> };

export function CalendarResult({ toolResult }: ToolResultSurfaceProps<Input, Output>) {
  if (toolResult.state === 'input-streaming') return <p>Preparing…</p>;
  if (toolResult.state === 'output-pending') return <p>Waiting for an action…</p>;
  if (toolResult.state === 'output-error') return <p>{toolResult.errorText}</p>;
  if (toolResult.state === 'output-denied') return <p>Permission denied.</p>;
  if (toolResult.state !== 'output-available') return <p>Running…</p>;
  return <p>{toolResult.result?.events.length ?? 0} events</p>;
}
```

| State | Contract |
| --- | --- |
| `input-streaming` | `renderBeforeOutput` 時の best-effort な partial `unknown` input。 |
| `input-available`、approval state | Schema validation 済みの完全な input。 |
| `output-pending` | Deferred call。`deferred.operationId` と opaque app `data` を持てます。 |
| `output-available` | `result` は transport metadata を除いた app result。 |
| `output-error`、`output-denied` | Result を仮定せず失敗または denial を描画します。 |

`execution` は call を生成した app lane を示します。Payload の診断用 context であり、producer の historical artifact を load する指定ではありません。

### Message part

Native `message-part` は該当 chat message の下に mount される inline tool surface です。Tool view と同じ `ToolResultSurfaceProps`、state、producer lane context、`toolNames`、任意の `renderBeforeOutput` contract を使います。

YAML

```
contributes:
  ui:
    - id: source-summary
      kind: nativeModule
      surface: message-part
      slot: chat.message.inline.below
      toolNames: [searchSources]
      renderBeforeOutput: true
      module:
        entry: dist/ui/app.js
        export: SourceSummary
```

TSX

```
import type { ToolResultSurfaceProps } from '@sota/platform';

type SearchOutput = { sources: Array<{ title: string; url: string }> };

export function SourceSummary({ toolResult }: ToolResultSurfaceProps<unknown, SearchOutput>) {
  if (toolResult.state === 'output-pending') {
    return <aside aria-live="polite">Waiting for the app…</aside>;
  }
  if (toolResult.state !== 'output-available') return null;
  return <aside aria-label="Sources">{toolResult.result?.sources.map((source) => (
    <a key={source.url} href={source.url} rel="noreferrer" target="_blank">
      {source.title}
    </a>
  ))}</aside>;
}
```

> [!NOTE]
> Declarative message renderer とは別です。
>
> `kind: messageRenderer` は matched text を citation、mention、pill として装飾し、`surface: message-part` は named tool call に app React を load します。

### Artifact surface

Artifact surface は durable side-panel view の body を所有します。安定した app namespace の `artifactKind` を宣言し、Core は open 時にその app lane の current native module を resolve します。

YAML

```
contributes:
  ui:
    - id: report-viewer
      kind: nativeModule
      surface: artifact
      slot: artifact.slot.reports-viewer
      artifactKind: reports.viewer
      module:
        entry: dist/ui/app.js
        export: ReportViewer
        styles: dist/ui/app.css
```

TSX

```
import { useAppContext } from '@sota/platform';

type ArtifactProps = {
  artifact: { artifactKind: string; context?: Record<string, unknown> };
};

export function ReportViewer({ artifact }: ArtifactProps) {
  const { ui } = useAppContext();
  const title = typeof artifact.context?.title === 'string'
    ? artifact.context.title
    : 'Report';
  return <button type="button" onClick={ui.closeArtifact}>Close {title}</button>;
}
```

同じ app lane の surface から `ui.openArtifact('reports.viewer', context)` で開きます。Lane の現在の app が `artifact.context` を描画し、過去の release が作った payload との互換性は app が管理します。`core.*` namespace は予約済みです。

TSX

```
import { useAppContext } from '@sota/platform';

export function OpenReportButton({ reportId }: { reportId: string }) {
  const { ui } = useAppContext();
  return <button type="button" onClick={() => ui.openArtifact('reports.viewer', {
    reportId, title: 'Quarterly report',
  })}>Open report</button>;
}
```

`artifact.context` は利用前に検証します。Transport data であり、authoritative record は app backend から load します。

### Workspace card

`card` は workspace assistant 領域に置く compact app UI です。Card 固有 props はなく、context、data、action は platform hook から取得します。

YAML

```
contributes:
  ui:
    - id: reports-card
      kind: nativeModule
      surface: card
      slot: workspace.assistant-card
      module:
        entry: dist/ui/app.js
        export: ReportsCard
```

TSX

```
import { useAppContext } from '@sota/platform';

export function ReportsCard() {
  const { ui } = useAppContext();
  return <button type="button" onClick={() => ui.openArtifact('reports.viewer', {
    filter: 'needs-review',
  })}>Review reports</button>;
}
```

Page size を仮定せず host に合わせて responsive にします。大きな canvas には workspace page または artifact を使います。

### Composer action

`composer-action` は chat input control の横に置く compact な app-owned action です。

YAML

```
contributes:
  ui:
    - id: report-action
      kind: nativeModule
      surface: composer-action
      slot: chat.composer.actions
      module:
        entry: dist/ui/app.js
        export: ReportAction
```

TSX

```
import { useAppContext } from '@sota/platform';

export function ReportAction() {
  const { ui } = useAppContext();
  return <button type="button" onClick={() => ui.openArtifact('reports.viewer')}>Reports</button>;
}
```

`useComposer` はここでは使用できません。Draft を読み書きする UI は `composer-panel` として宣言し、Core private store へアクセスしません。

### Composer panel

`composer-panel` は composer 上部の contextual app UI で、public composer API に bind される唯一の surface です。Draft の観察と atomic edit、exact execution の pending deferred result、composer lock を利用できます。

YAML

```
contributes:
  ui:
    - id: report-panel
      kind: nativeModule
      surface: composer-panel
      slot: chat.composer.panel
      module:
        entry: dist/ui/app.js
        export: ReportPanel
```

TSX

```
import { useComposer } from '@sota/core/hooks';

export function ReportPanel() {
  const value = useComposer((composer) => composer.value);
  const applyEdit = useComposer((composer) => composer.applyEdit);
  if (!value.includes('/report')) return null;
  return <button type="button" onClick={() => applyEdit({
    mode: 'replace', content: [{ kind: 'text', text: 'Create a weekly report for ' }],
  })}>Use template</button>;
}
```

Slot は正確に `chat.composer.panel` とします。App 固有条件がなければ `null` を描画できます。Slash command と panel は独立 contribution です。

### useAppContext

`useAppContext()` は hosted native surface の中心 runtime API です。`@sota/platform` から import し、app surface provider の外では throw します。

TSX

```
import { useAppContext } from '@sota/platform';

export function RuntimeDetails() {
  const context = useAppContext();
  return (
    <dl>
      <dt>App</dt><dd>{context.appId}@{context.appVersion}</dd>
      <dt>Organization</dt><dd>{context.organizationId}</dd>
      <dt>Workspace</dt><dd>{context.workspaceId ?? 'none'}</dd>
      <dt>Surface</dt><dd>{context.surface}</dd>
    </dl>
  );
}
```

| Field | 意味 |
| --- | --- |
| `appId`、`appVersion` | この lane に現在選択されている app package。 |
| `organizationId`、`workspaceId` | 検証済み tenant context。 |
| `surface` | 現在の surface kind。Authorization には使用しません。 |
| `theme`、`locale`、`t` | 現在の host presentation と localization。 |
| `fetch` | `useAppFetch` と同じ scoped data-plane function。 |
| `lifecycle` | Mount-owned cancellation と cleanup。 |
| `ui` | Toast、navigation、artifact、lightbox などの host action。 |

値は server-resolved execution から stamp されます。URL や local storage から identity を再構築しません。

### useAppFetch

`useAppFetch()` は surface の authenticated data-plane fetcher を返します。App-relative path と通常の `RequestInit` を渡すと、Core が選択 environment の backend 配下へ resolve し、bearer credential と mount cancellation を付与し、期限切れ credential を一度だけ refresh します。

TSX

```
import { useState } from 'react';
import { useAppFetch } from '@sota/platform';

export function SaveSettingsButton() {
  const appFetch = useAppFetch();
  const [status, setStatus] = useState('idle');
  async function save() {
    setStatus('saving');
    const response = await appFetch('/settings', {
      method: 'PUT',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ digest: 'weekly' }),
    });
    if (!response.ok) {
      setStatus('error');
      return;
    }
    const saved = await response.json();
    setStatus(saved.digest === 'weekly' ? 'saved' : 'error');
  }
  return <button type="button" onClick={save}>{status}</button>;
}
```

返り値は標準 `Response` です。JSON parse と domain error は app logic です。Cross-origin URL と scoped base path の外へ出る path は拒否されます。Authorization header を自分で付与・保存しません。

| Case | Behavior |
| --- | --- |
| 通常 response | Non-2xx を含めそのまま返します。 |
| Credential expired | 同じ environment の descriptor を refresh して一度だけ retry します。 |
| Surface unmount | Request signal を abort します。 |
| One-shot stream body | Credential retry に備えて事前に tee します。 |

### useLocale

`useLocale()` は `{ locale, t }` を返します。`locale` は app surface に実際に load された locale、`t(key, values)` は宣言済み app message を読み named value を補間します。不足した app key は shell translator へ fallback します。

TSX

```
import { useLocale } from '@sota/platform';

export function Greeting({ name }: { name: string }) {
  const { locale, t } = useLocale();
  return <p lang={locale}>{t('greeting', { name })}</p>;
}
```

YAML

```yaml
locales:
  default: en
  files:
    en: src/locales/en.json
    ja: src/locales/ja.json
```

`src/locales/en.json`

JSON

```json
{ "greeting": "Hello, {{name}}" }
```

`src/locales/ja.json`

JSON

```json
{ "greeting": "こんにちは、{{name}}" }
```

選択 locale は app locale contract に従って fallback し、不足した app key は shell translator へ渡ります。両方にない重要 label には component fallback を用意します。

### useTheme

`useTheme()` は `'light'` または `'dark'` を返し host theme 変更時に re-render します。Read-only であり、app は workspace theme を変更しません。

TSX

```
import { useTheme } from '@sota/platform';

export function Preview() {
  const theme = useTheme();
  return <div className="preview" data-theme={theme}>Preview</div>;
}
```

コード

```css
.preview {
  color: var(--foreground);
  background: var(--background);
}

.preview[data-theme='dark'] .diagram {
  filter: brightness(0.9);
}
```

通常は native surface が継承する design token を優先します。

### Platform UI component

`@sota/platform/ui` は native app 向けの public component library です。Core token、theme、focus behavior、portal、accessibility default を継承します。Core source path や別 copy の Radix/Recharts ではなく、この entry point から import します。

| Group | Exports |
| --- | --- |
| Action／status | `Button`、`Badge`、`Spinner`、`Skeleton`、`buttonVariants`、`badgeVariants`。 |
| Content／layout | `Card`、`CardHeader`、`CardTitle`、`CardDescription`、`CardContent`、`CardFooter`、`Separator`、`ScrollArea`、`ScrollBar`。 |
| Form | `FormField`、`Label`、`Input`、`Textarea`、`Checkbox`、`Switch`、`Select`、`SelectContent`、`SelectGroup`、`SelectItem`、`SelectLabel`、`SelectSeparator`、`SelectTrigger`、`SelectValue`。 |
| Overlay | `Dialog`、`DialogClose`、`DialogContent`、`DialogDescription`、`DialogFooter`、`DialogHeader`、`DialogTitle`、`DialogTrigger`、`Popover`、`PopoverContent`、`PopoverTrigger`、`Tooltip`、`TooltipContent`、`TooltipProvider`、`TooltipTrigger`。Portal は app surface host 内に留まります。 |
| Navigation | `Tabs`、`TabsList`、`TabsTrigger`、`TabsContent`。 |
| Grounded prose | `CitationText` が `[n]` marker を source pill にします。 |
| Chart | `ChartContainer`、`ChartStyle`、`ChartTooltip`、`ChartTooltipContent`、`ChartLegend`、`ChartLegendContent`、`Area`、`AreaChart`、`Bar`、`BarChart`、`Line`、`LineChart`、`Pie`、`PieChart`、`RadialBar`、`RadialBarChart`、`CartesianGrid`、`XAxis`、`YAxis`、`ChartLabel`、`ChartLabelList`、`Cell`、`Sector`、`ReferenceLine`。 |

### Form と card

TSX

```
import { useState } from 'react';
import {
  Button, Card, CardContent, CardFooter, CardHeader, CardTitle,
  FormField, Input, Switch,
} from '@sota/platform/ui';

export function DigestSettings() {
  const [email, setEmail] = useState('');
  const [enabled, setEnabled] = useState(true);
  return (
    <form onSubmit={(event) => event.preventDefault()}><Card variant="flat">
      <CardHeader><CardTitle>Weekly digest</CardTitle></CardHeader>
      <CardContent>
        <FormField id="digest-email" label="Delivery email" required>
          <Input id="digest-email" type="email" value={email}
            onChange={(event) => setEmail(event.target.value)} required />
        </FormField>
        <Switch checked={enabled} onCheckedChange={setEnabled}
          aria-label="Enable weekly digest" />
      </CardContent>
      <CardFooter><Button type="submit" disabled={!email}>Save</Button></CardFooter>
    </Card></form>
  );
}
```

`Button` variant は `default`、`secondary`、`destructive`、`outline`、`link`、`ghost`。Size は `default`、`sm`、`lg`、`icon`、`icon-sm` で、`loading` prop も使えます。

### Dialog

TSX

```
import {
  Button, Dialog, DialogClose, DialogContent, DialogDescription,
  DialogFooter, DialogHeader, DialogTitle, DialogTrigger,
} from '@sota/platform/ui';

export function DeleteDialog() {
  return <Dialog>
    <DialogTrigger asChild><Button variant="destructive">Delete</Button></DialogTrigger>
    <DialogContent preset="confirm" size="sm">
      <DialogHeader>
        <DialogTitle>Delete report?</DialogTitle>
        <DialogDescription>This action cannot be undone.</DialogDescription>
      </DialogHeader>
      <DialogFooter>
        <DialogClose asChild><Button variant="outline">Cancel</Button></DialogClose>
        <Button variant="destructive">Delete</Button>
      </DialogFooter>
    </DialogContent>
  </Dialog>;
}
```

Preset は `modal`、`editor`、`confirm`、`command`、size は `sm` から `xl` です。`DialogTitle` と `DialogDescription` を必ず置きます。

### Citation と chart

TSX

```
import { CitationText } from '@sota/platform/ui';

export function AnswerWithSources() {
  return <CitationText text="Revenue grew by 12% [1]." citations={[{
    index: 1,
    url: 'https://example.com/q3',
    title: 'Q3 filing',
    snippet: 'Revenue increased twelve percent year over year.',
  }]} />;
}
```

TSX

```
import {
  Bar, BarChart, CartesianGrid, ChartContainer, ChartTooltip,
  ChartTooltipContent, XAxis, YAxis, type ChartConfig,
} from '@sota/platform/ui';

const chartConfig = {
  credits: { label: 'Credits', color: 'var(--chart-1)' },
} satisfies ChartConfig;
const data = [{ month: 'Jul', credits: 24 }, { month: 'Aug', credits: 31 }];

export function CreditChart() {
  return <ChartContainer config={chartConfig} className="min-h-48 w-full">
    <BarChart data={data}>
      <CartesianGrid vertical={false} />
      <XAxis dataKey="month" /><YAxis />
      <ChartTooltip content={<ChartTooltipContent />} />
      <Bar dataKey="credits" fill="var(--color-credits)" />
    </BarChart>
  </ChartContainer>;
}
```

Surface が使う primitive だけを import します。Generated declaration が install 済み Core version の exact prop reference です。

### Platform icon

`@sota/platform/icons` は安定 icon name `alert`、`check`、`chevronDown`、`chevronLeft`、`chevronRight`、`close`、`info`、`loading`、`search`、`settings`、`warning` を公開します。

TSX

```
import { Icon, PLATFORM_ICON_NAMES, type IconName } from '@sota/platform/icons';

export function StatusIcon({ name, label }: { name: IconName; label: string }) {
  return <span>
    <Icon name={name} size={16} strokeWidth={2} aria-hidden />
    <span>{label}</span>
  </span>;
}

console.log(PLATFORM_ICON_NAMES);
```

`Icon` は通常の SVG attribute も受け取ります。隣接 text が名前を持つ場合は `aria-hidden`、icon 単体なら `aria-label` を渡します。Closed name union により unavailable name は deploy 前に TypeScript error になります。

### Surface lifecycle

`useAppContext().lifecycle` は一つの surface mount の resource を所有し、unmount または exact runtime identity 変更時に cleanup します。

| API | 用途 |
| --- | --- |
| `signal` | Unmount 時に abort される `AbortSignal`。 |
| `onDispose(dispose)` | App cleanup を登録し unregister function を返します。 |
| `listen(target, type, listener, options?)` | Mount-owned event listener を追加し disposer を返します。 |

TSX

```
import { useEffect, useState } from 'react';
import { useAppContext } from '@sota/platform';

export function OnlineState() {
  const { lifecycle } = useAppContext();
  const [online, setOnline] = useState(navigator.onLine);
  useEffect(() => {
    const update = () => setOnline(navigator.onLine);
    const stopOnline = lifecycle.listen(window, 'online', update);
    const stopOffline = lifecycle.listen(window, 'offline', update);
    return () => {
      stopOnline();
      stopOffline();
    };
  }, [lifecycle]);
  return <p>{online ? 'Online' : 'Offline'}</p>;
}
```

TypeScript

```
import { useEffect } from 'react';
import { useAppContext } from '@sota/platform';

export function MountTimer() {
  const { lifecycle } = useAppContext();
  useEffect(() => {
    const timer = window.setInterval(() => console.log('tick'), 30_000);
    const unregister = lifecycle.onDispose(() => window.clearInterval(timer));
    return () => {
      window.clearInterval(timer);
      unregister();
    };
  }, [lifecycle]);
  return null;
}
```

Process-global listener や timer の代わりにこれらの primitive を使います。React cleanup が disposer を先に呼んでも、surface 消失時には Core が cleanup を保証します。

### Platform UI bridge

`useAppContext().ui` は app-owned UI から host-owned presentation を依頼する primitive です。Business workflow ではありません。

| API | 効果 |
| --- | --- |
| `toast(message, options?)` | Info、success、warning、error notice。 |
| `confirm(options)` | Host confirmation decision の promise。 |
| `navigate(to)` | Host router で移動。 |
| `openArtifact(kind, context?)` | 同じ app lane の現在の renderer で artifact を開きます。 |
| `closeArtifact()` | 存在する active artifact host を閉じます。 |
| `openImageLightbox(images, startIndex?)` | Caption と source attribution 対応の共通 image viewer。 |

TSX

```
import { useAppContext, useAppFetch } from '@sota/platform';

export function DeleteReportButton({ reportId }: { reportId: string }) {
  const appFetch = useAppFetch();
  const { ui } = useAppContext();

  async function remove() {
    const confirmed = await ui.confirm({
      title: 'Delete report?',
      description: 'This cannot be undone.',
      confirmLabel: 'Delete',
      destructive: true,
    });
    if (!confirmed) return;
    const response = await appFetch('/reports/' + encodeURIComponent(reportId), {
      method: 'DELETE',
    });
    ui.toast(response.ok ? 'Report deleted' : 'Delete failed', {
      kind: response.ok ? 'success' : 'error',
    });
  }

  return <button type="button" onClick={remove}>Delete</button>;
}
```

TSX

```
import { useAppContext } from '@sota/platform';

export function PreviewButton({ previewUrl }: { previewUrl: string }) {
  const { ui } = useAppContext();
  return <button type="button" onClick={() => ui.openImageLightbox([{
    url: previewUrl,
    alt: 'Report preview',
    caption: 'Page 1',
    sourceTitle: 'Quarterly report',
    sourceUrl: 'https://reports.example.com/q3',
  }], 0)}>Preview</button>;
}
```

現在の host が action を実行できない場合は安全な no-op になり得ます。Business state の authority は app backend に置きます。

### useComposer

`useComposer(selector)` は hosted `composer-panel` 内だけで利用でき、他では throw します。`@sota/core/hooks` から import し、component が必要な field だけを select します。

| Field | Contract |
| --- | --- |
| `value` | Current draft の plain-text view。 |
| `content` | Structured text と `app-reference` node。 |
| `references` | Resolved slash、conversation、lane-scoped app reference。 |
| `pendingToolResults` | Panel の exact app execution に属する deferred tool result。 |
| `applyEdit(edit)` | `replace`、`insert-at-cursor`、`append` の undoable transaction。 |
| `focus()` | Composer editor へ focus。 |
| `acquireLock()` | 保持中は send、draft edit、既存 message edit、queued auto-send を disable し、idempotent release function を返します。 |

TSX

```
import { useEffect } from 'react';
import { useComposer } from '@sota/core/hooks';

export function PendingActionPanel() {
  const pending = useComposer((composer) => composer.pendingToolResults);
  const acquireLock = useComposer((composer) => composer.acquireLock);
  const active = pending.find((item) => item.toolName === 'readCalendar');

  useEffect(() => {
    if (!active) return;
    return acquireLock();
  }, [acquireLock, active]);

  if (!active) return null;
  return <p>Complete the app action to continue.</p>;
}
```

Lock は reference-counted です。Core は surface unmount 時に自動 release しますが、effect から release function を返してください。Plain `value` から再構築せず structured `content` を保ちます。

TSX

```
import { useComposer } from '@sota/core/hooks';

export function InsertReportButton() {
  const applyEdit = useComposer((composer) => composer.applyEdit);
  return <button type="button" onClick={() => applyEdit({
    mode: 'insert-at-cursor',
    content: [
      { kind: 'text', text: 'Review ' },
      {
        kind: 'app-reference',
        referenceType: 'report',
        referenceId: 'report-42',
        label: 'Q3 report',
        fallbackText: 'Q3 report',
      },
    ],
  })}>Insert report</button>;
}
```

`pendingToolResults` は `operationId`、`toolCallId`、canonical `toolName`、`modelToolName`、optional opaque `data`、exact `execution` を持ちます。App data は runtime で narrow します。`pendingToolResults`/`acquireLock` は platform contract `1.3.0` 以降が必要です。

### Deferred tool result

App backend は user message を作らず、model に tool を再呼び出しさせずに現在の tool call result を defer できます。Core が理解するのは operation id と opaque app data だけで、login、approval、payment、device pairing などは app logic です。

JSON

```json
{
  "_sota": {
    "deferredToolResult": {
      "operationId": "app-defined-globally-unique-id",
      "data": { "anyAppOwnedValue": true }
    }
  }
}
```

Core は exact run、tool call、tool name、installation、environment を登録し、`output-pending` と exact panel の `pendingToolResults` を公開します。Model はまだ tool result を受け取りません。

YAML

```yaml
coreToolGrants:
  - tool: core.app-operations.complete
    scope: write
  # 長寿命 job callback token が必要な場合のみ:
  - tool: core.tokens.issueJobCallback
    scope: write
```

Callback は app backend から Core origin へ送ります。Bearer value は original invocation の `x-sota-core-token` header で受け取った delegated capability です。

コード

```
POST /v1/app-operations/app-defined-globally-unique-id/complete
Authorization: Bearer <delegated-token>
Content-Type: application/json

{
  "status": "completed",
  "result": { "events": [] }
}
```

Failure は任意の `error` と `status: "failed"` で返します。Completion は original tool result に atomic に結び付き、同じ agent run が続きます。Parallel call は個別 operation id を持ち、その step の全 call が settle 後に model が続行します。

JSON

```json
{
  "status": "failed",
  "error": {
    "code": "ACTION_NOT_COMPLETED",
    "message": "The requested action was not completed"
  }
}
```

- `core.app-operations.complete:write` を grant します。
- Operation id は trim 済み 1–200 文字で、tool call ごとに globally unique。Identical retry は idempotent です。
- 登録は deferred response 受信後なので `app_operation_not_found` を bounded backoff で retry します。
- 60 秒 delegation token より長い場合、original invocation が valid な間に job callback token へ交換し、安全に保存して `x-sota-job-id` を送ります。
- `data` は小さく secret を含めません。Core には opaque でも client-visible であり、app UI で shape を narrow します。
- 現在の primitive は live run に結び付きます。Stop／steer は pending operation を `operation_cancelled` にします。App expiry は failed completion で表現し、background job queue として使いません。

### UI contract helper

生成された `@sota/platform` は build contract metadata と typed descriptor helper も公開します。Manifest v3 が registration authority である点は変わりません。

| Export | Contract |
| --- | --- |
| `PLATFORM_API_VERSION` | Runtime に compile された public API version。 |
| `getAppUiContractHash()` | Installed UI declaration の exact hash。App runtime 外では throw。 |
| `assertCoreCompatibility(hash)` | 初期 native app との source compatibility 用 no-op。Exact hash は artifact identity であり compatibility gate ではありません。 |
| `defineAppExtension(descriptor)` | 非空 `id`/`appId` を検証して frozen typed copy を返します。Manifest にない contribution は登録しません。 |

### Type-only export

| Group | Types |
| --- | --- |
| Runtime context | `AppPlatformContextValue`、`AppLocale`、`AppTheme`、`AppSurfaceKind`、`AppLightboxImage`。 |
| Tool UI | `ToolResultSurfaceProps`、`ToolResultSurfaceValue`、`ToolResultSurfaceState`、`ToolResultSurfaceCommon`、`ToolResultSurfaceExecution`。 |
| Descriptor | `AppExtensionDescriptor`、`AppSurfaceSlot`、`NativeModuleSurfaceDescriptor`、`ToolResultSurfaceDescriptor`、`MessageDecorationDescriptor`、`ArtifactSurfaceDescriptor`、`ArtifactSurfaceRenderInput`。 |

TypeScript

```
import {
  PLATFORM_API_VERSION,
  defineAppExtension,
  getAppUiContractHash,
} from '@sota/platform';

const descriptor = defineAppExtension({ id: 'reports', appId: 'reports-app' });
console.log(PLATFORM_API_VERSION, getAppUiContractHash(), descriptor.id);
```

TypeScript

```
import type {
  AppPlatformContextValue,
  ToolResultSurfaceProps,
  ToolResultSurfaceState,
} from '@sota/platform';

export type RuntimeIdentity = Pick<AppPlatformContextValue, 'appId' | 'appVersion'>;
export type CalendarSurface = ToolResultSurfaceProps<
  { from: string; to: string },
  { events: unknown[] }
>;
export const terminalStates: readonly ToolResultSurfaceState[] = [
  'output-available', 'output-error', 'output-denied',
];
```

`.sota/app-ui-contracts/` は現在の CLI で再生成し、手動編集・別 project から copy しません。

> [!WARNING]
> 生成 declaration bundle は API catalog ではありません。
>
> App が利用できるのは文書化された `@sota/platform` export と `useComposer` です。`@sota/core/hooks` に偶然含まれる他の host declaration は、専用 developer API page がない限り internal です。

### Local 開発

Local 開発では、2 つのターミナルで 2 つの独立した process を動かします。**あなた**がアプリの watcher を所有し、**CLI** が Development session と、手元のマシンへ届く tunnel を所有します。Sota CLI があなたの process を起動・再起動・停止することは一切ありません。Session を止めたときも同様です。

ターミナル

```
# terminal 1 — アプリの watcher
npm run dev

# terminal 2 — Development session と tunnel
npm run dev:sota   # sota dev と同じ
```

1. #### Watcher を起動

   `npm run dev` を実行します。Backend と native UI の両方を含む scaffold では、この 1 コマンドで**両方**が動きます。`concurrently` が backend watcher と UI watch build を `backend`／`ui` というラベルで並行起動し、`--kill-others` により片方が落ちたら対で停止します。片側だけが動き続ける状態になりません。

2. #### Development を開く

   `sota dev` を実行して organization と workspace を選び、process を起動したままにします。CLI はまず local ですべてを準備し——manifest の compile、build 済み frontend output の検証、tunnel transport の確立——その後に session を 1 回の commit で公開します。準備中に失敗した場合、server 側には何も作られません。

3. #### 安全に反復

   CLI は compile 済み manifest の元になったすべてのファイル——manifest 本体、JSON Schema、locale ファイル、native asset、inline 化された skill 本文——を監視し、変更があれば個人 session へ再同期します。Compile error は diagnostics を表示するだけで、last-known-good manifest は置き換えません。15 秒ごとの heartbeat が session の lease を延長します。

4. #### 停止

   `sota dev stop` を実行するか、`sota dev` のターミナルで Ctrl-C を押します。Development app は消え、Core 管理のデータ cleanup が予約されます。あなたの frontend／backend process はそのまま動き続けます——CLI が終了時に明示的にそう表示します。

### UI と backend を個別に動かす

`npm run dev` は、独立して存在する 2 つの script をまとめた便宜的な wrapper にすぎません。片方だけ再起動したいとき、片方だけに debugger を接続したいとき、そして何より backend が Node.js の process でないときは、個別に実行してください。

| Script | 実際に動くもの | 備考 |
| --- | --- | --- |
| `npm run dev` | `concurrently --kill-others --names backend,ui "tsx watch src/backend/server.ts" "sota contracts ensure && vite build --watch"` | 両方を同時に。Backend のみ／UI のみの project ではその片方だけになります。 |
| `npm run dev:backend` | `tsx watch src/backend/server.ts` | アプリの HTTP service。Source 変更で再起動します。`PORT`（既定 `8787`）で listen します。 |
| `npm run dev:ui` | `sota contracts ensure && vite build --watch` | Dev server ではなく _watch build_ です。App UI type contract を更新し、変更のたびに `dist/ui/app.js` と `dist/ui/app.css` を build し直します。 |
| `npm run dev:sota` | `sota dev` | Development session、manifest 同期、tunnel。上の 2 つとは独立しています。 |

> [!NOTE]
> Local の UI server が存在しないのは意図的です。
>
> Native UI は `localhost` ではなく SotaAgents の host 内で動きます。`dev:ui` は build 済み module をディスク上で最新に保つだけでよく、その bytes をそのまま tunnel が platform に配ります。だからこそ、deploy 済み artifact に packaging された後もまったく同じファイルが動作します。

### 独自の backend runtime を使う

Scaffold が TypeScript と Express なのは広く理解されているからで、platform の要求ではありません。SotaAgents と backend の間の contract は素の HTTP と検証済み token だけなので、Go、Python、Java、Rust の service も一級の app backend です。SotaAgents の system app の一つは FastAPI の service で、まったく同じ invocation token を、同じ Core JWKS endpoint に対して Python で検証しています。

その場合、Node の backend script は単に使いません。自分の stack のやり方で service を起動し、UI があるなら native UI 用に `npm run dev:ui` を残し、local overlay を service の listen ポートに向けます。

ターミナル

```
# terminal 1 — 自分の言語で書いた backend
uvicorn app.main:app --reload --port 8787

# terminal 2 — native UI の watch build（UI がある場合のみ）
npm run dev:ui

# terminal 3 — Development session
sota dev
```

`sota dev` は Local Backend Endpoint を次の順で解決します：`--local-url` flag、manifest の `environments.local.service.baseUrl`、最後に使った endpoint（`.sota/dev.json` に記憶）。対話的なターミナルではいずれも無ければ入力を求め、そうでなければ `LOCAL_BACKEND_UNAVAILABLE` で失敗します。その後 CLI は約 1 秒ごとにその endpoint を polling し、`[backend] available`／`[backend] unavailable` を表示します。この確認は情報提供のみで、session の公開を妨げません。Backend が一時的に落ちても Development app は失われません。

> [!WARNING]
> Live session は個人用です。
>
> 1 developer・1 workspace に属します。再実行は自分の session だけを置換し、共有 Staging にはなりません。Staging と Production が tunnel に依存することはなく、host 済み backend を直接呼び出します。

### Validation と test

ターミナル

```
sota validate
npm run typecheck
npm run build
sota deploy --dry-run
```

- 各 tool の正常・不正・unauthorized・timeout input を確認。
- 全 UI slot/tool-result renderer を light/dark theme で開く。
- Entry、chunk、CSS、locale、AppData が platform 経由で load されることを確認。
- Owner、contributor、workspace admin、member、non-member をテスト。
- Environment 間で secret/data を意図せず共有しないことを確認。

### Staging deploy

Browser は developer laptop の source を安全かつ再現可能には load できません。Deploy は declared surface を immutable な content-addressed bytes に変換し、全 screen、tool-result renderer、locale loader、artifact consumer が同じものを解決できるようにします。

![Source project から immutable SotaAgents artifact への diagram](/manual/assets/developer/bundle-pipeline.svg?v=2)
_Upload artifact は package asset と resolved definition を含み、running backend、database、secret、operational data は含みません。_

ターミナル

```
sota validate
sota deploy --dry-run
sota deploy --description "Add grounded search results"
sota status
```

Deploy は deterministic に compile/pack/upload し、Core が authoritative definition を検証します。Staging pointer だけが新 artifact に移り、Production は変わりません。

> [!WARNING]
> Version は immutable です。
>
> 既存 version に異なる bytes を deploy すると `VERSION_IMMUTABLE_CONFLICT`。Version を上げ、breaking change では CLI が要求する acknowledgement と migration declaration を指定します。

Staging test には exact environment の install/enable、owner/contributor 権限、active workspace membership が必要です。

### Production release

ターミナル

```
sota release
sota status
```

Release は**現在の exact Staging artifact**を Production に promote します。Rebuild、Staging data copy、release approval は行いません。初回 Production は **Private**、以降は visibility と App Store eligibility を維持します。

- Test 済み artifact ID/version を確認。
- Production backend、health、secret、CORS、data store を確認。
- Install、enablement、tool、native UI、audit event を smoke-test。
- 既存 version を変更せず、新 version で roll forward。

### App Store 公開

Production release と App Store listing は別の判断です。Production は public catalog に出さず Private/Restricted にできます。

| Visibility | Discovery / install |
| --- | --- |
| Private | 管理専用。Install catalog に出ず、install 不可。 |
| Restricted | 明示した最大 50 組織に提供。 |
| Public / App Store | 初回 SotaAgents 運営チームによる eligibility 承認後、public catalog に表示。 |

1. Test 済み Production artifact を release。
2. _App Registry → My apps → app detail → Settings_ を開く。
3. Public App Store visibility を選び listing request を送信。
4. SotaAgents 運営チームは discovery eligibility だけを審査。承認は Production の release/置換を行いません。
5. 承認後は eligibility が revoke されない限り、owner が再申請なしで delist/relist できます。

### Best practices

### 小さく明確な capability

Tool は一つの責務、厳格な schema、有限 timeout、安全な failure mode を持たせます。

### Platform context を信頼

Signed request を検証し、任意 input から actor/workspace/environment を決めません。

### Portable UI

Generated contract と platform loader を使い、asset URL/token/navigation/fallback を自作しません。

### Exact version を観測

Secret を除き artifact/version、environment、request ID、tool name を記録します。

### Environment 分離

必要に応じ credential/data store を分離。Staging も実 org credit/audit context を使います。

### Roll forward

Deploy 済み version を変更せず、version up → validate → Staging test → release。

### Developer troubleshooting

| 症状 | 確認事項 |
| --- | --- |
| Native app entry が 401/403 | Asset を直接呼ばず platform mount を使用。Exact environment の install/enable と actor authorization を確認。 |
| Native app entry が 404 | Artifact に宣言した entry/chunk/CSS/locale が存在し、selected environment が exact artifact を指すか確認。 |
| AppData/tool unauthorized | Membership、Staging owner/contributor rule、enablement、signed request、environment credential を確認。 |
| Manifest change が反映されない | `local`/`stg`/`prod` overlay、validation、version increment を確認。 |
| Staging 成功、Production 失敗 | Source だけでなく binding、secret、health、CORS、external data store、install/visibility を比較。 |

有用な command：`sota status`、`sota logs`、`sota manifest diff <left> <right>`、`sota docs`。

## エンタープライズ統合

社内で既に使っているシステム — イントラネット、顧客ポータル、業務アプリ — に、自社のサインインのままアシスタントを組み込みます。

### 自社システムへの組み込み

SotaAgents は自社が所有するページの中で、フローティングバブルまたはインラインパネルとして動作します。ユーザーは_自社_のシステムにサインインしたままで、SotaAgents のログイン画面を見ることはありません。ユーザーが誰であるかは自社のバックエンドが保証し、プラットフォームはユーザーの入力ではなくその署名を信頼します。

[15 秒の動画: チケットへの署名、パネルのマウント、パートナーポータル内で動作するアシスタント](/manual/assets/video/enterprise-embed-1080p.mp4)
_15 秒、音声なし。バックエンドがリクエストに署名してチケットを受け取り、フロントエンドは 1 回の呼び出しでパネルをマウントし、アシスタントがパートナー自身のポータルの中に現れます — インライン、またはフローティングバブルとして。_

### 2 つの組み込み方式

| 方式 | 訪問者 | 用途 | 設定者 |
| --- | --- | --- | --- |
| Public Deployment (_Configure Embed_) | 匿名ゲスト。専用の Guest Credit pool を消費 | 公開サイト、マーケティングページ、プリセールスチャット | 組織の Owner / Admin — コード不要 |
| Embed SDK (署名付き handshake) | 組織のメンバーである実名ユーザー | イントラネット、顧客ポータル、社内ツール | 組織の Owner / Admin と開発チーム |

本ページは後者を扱います。前者は[ワークスペース](/ja/manual/admin-console/workspaces)を参照してください。

### 始める前に

- _Console → 組織 → API Keys_ で発行する **API key と secret**。secret は一度しか表示されません — [API キー](/ja/manual/admin-console/api-keys)を参照。
- embed を使う全員が、あらかじめ組織の**有効なメンバー**である必要があります。just-in-time のアカウント作成は行いません。未知のユーザーは作成されずに拒否されます。先に[招待](/ja/manual/admin-console/inviting-people)するか、SSO でプロビジョニングしてください。
- 自社で管理するバックエンド。secret はサーバー側で署名に使うものであり、ブラウザーに渡してはいけません。

### handshake の流れ

![シーケンス図: エンタープライズフロントエンドがエンタープライズバックエンドに ticket を要求し、バックエンドが SotaAgents embed API へのリクエストに署名し、返ってきた ticket を iframe が session cookie に交換し、サインアウトでその session が失効する](/manual/assets/developer/embed-flow.svg?v=2)
_3 者間の署名付きハンドシェイク。API secret が中央の列を離れることはなく、ブラウザーが持つのは 60 秒の ticket と、その後の分割された session cookie だけです。_

1. #### 自社ページが自社バックエンドに ticket を要求

   SDK が自社の ID 基盤と直接やり取りすることはありません。開発者が渡す `getTicket` 関数を呼び、その関数が自社のセッション cookie を付けて自社エンドポイントを呼びます。

2. #### 自社バックエンドが署名して ticket を発行

   セッションからユーザー identity を読み、API secret でリクエストに署名し、60 秒有効な単回使用 ticket を受け取ります。

3. #### iframe が ticket を session に交換

   SDK が ticket を SotaAgents フレームに渡し、フレームが自身の session に交換します。ticket は再利用できません。

4. #### SDK が自動で ticket を取り直す

   有効期限の直前、および 401 の後には、SDK が自動で手順 1 を繰り返します。意味を持つ有効期間は自社セッションだけで、同期すべきものはありません。

### バックエンドの責務

3 つあり、最初の 2 つが統合で最も間違えやすい箇所です。

1. #### サーバー側でユーザーを特定する

   既存のポータルの仕組み（SSO、OIDC、独自のセッションテーブル）をそのまま使います。`externalUserId` は**その人に対して恒久的に不変**である必要があります。SotaAgents ユーザーへの対応付けは一度だけ作られ、更新されることはありません。これは_自社側_で守るべき不変条件であり、SotaAgents 側で強制しているものではありません。既知の人物に新しい id が届いても**拒否されません**。SotaAgents は email で本人を突き合わせ、2 つ目の対応付けを黙って作成するため、古い対応付けは identity 失効の対象から外れたまま残ります。_拒否される_のは逆のケース、既存の id が別の email で届いた場合です。

2. #### ticket エンドポイントを用意する

   identity は必ず**セッション**から読み、リクエストボディからは読まないでください。ボディから読むと、サインイン済みの社員が同僚になりすました ticket を発行できてしまいます。以下の手順で呼び出しに署名し、ticket をブラウザーに返します。

3. #### SDK が判断できる status を返す

   SDK は **4xx を恒久的なエラー**として停止し、**5xx を再試行可能**として backoff します。自社セッション切れは `401`、有効なメンバーシップがない場合は `409`、SotaAgents に到達できない場合は `502` を返してください。

> [!WARNING]
> secret はサーバーに留める
>
> ブラウザーが受け取るのは短命な単回使用 ticket だけです。フロントエンドに配られた API secret は、組織内のあらゆる identity の ticket を発行できます。secret manager に保管し、source control には入れないでください。

### リクエストへの署名

手順はどの言語でも同じです。5 行の canonical string を組み立て、API secret で HMAC-SHA256 し、`v1=<小文字 hex>` として送ります。5 行は method、path、Unix タイムスタンプ（**秒**）、nonce、リクエストボディの SHA-256 で、`\n` で連結し、末尾に改行は付けません。

コード

```
POST
/api/embed/auth/tickets
1786800000
3f1c9a7e-5b02-4d6f-9a11-0c8e2d4b7f30
9b2a4c1d8e3f5a70b6c9d2e4f8a1b3c5d7e9f0a2b4c6d8e0f1a3b5c7d9e1f3a5
```

> [!WARNING]
> 実際に送るバイト列を hash する
>
> ボディの serialize は一度だけ行い、その同じ文字列を hash にも送信にも使ってください。2 回目のために再 serialize することが、どこでも検証できない署名になる最大の原因です。JSON エンコーダーが違えば、あるいは同じものを 2 回呼んだだけでも、キー順や空白が変わり得ます。

#### Node.js

```javascript
import { createHash, createHmac, randomUUID } from 'node:crypto';

const body = JSON.stringify({ externalUserId, email, name }); // serialize ONCE
const timestamp = String(Math.floor(Date.now() / 1000));
const nonce = randomUUID();
const bodyHash = createHash('sha256').update(body, 'utf8').digest('hex');

const canonical = ['POST', PATH, timestamp, nonce, bodyHash].join('\n');
const signature = 'v1=' + createHmac('sha256', apiSecret).update(canonical).digest('hex');
```

#### Python

```python
import hashlib, hmac, json, time, uuid

body = json.dumps({"externalUserId": external_user_id, "email": email})  # serialize ONCE
timestamp = str(int(time.time()))
nonce = str(uuid.uuid4())
body_hash = hashlib.sha256(body.encode("utf-8")).hexdigest()

canonical = "\n".join(["POST", PATH, timestamp, nonce, body_hash])
signature = "v1=" + hmac.new(
    api_secret.encode("utf-8"), canonical.encode("utf-8"), hashlib.sha256
).hexdigest()
```

#### Java

```java
String body = objectMapper.writeValueAsString(payload); // serialize ONCE
String timestamp = String.valueOf(Instant.now().getEpochSecond());
String nonce = UUID.randomUUID().toString();
String bodyHash = HexFormat.of().formatHex(
    MessageDigest.getInstance("SHA-256").digest(body.getBytes(StandardCharsets.UTF_8)));

String canonical = String.join("\n", "POST", PATH, timestamp, nonce, bodyHash);

Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
String signature = "v1=" + HexFormat.of().formatHex(
    mac.doFinal(canonical.getBytes(StandardCharsets.UTF_8)));
```

#### C#

```csharp
var body = JsonSerializer.Serialize(payload); // serialize ONCE
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
var nonce = Guid.NewGuid().ToString();
var bodyHash = Convert.ToHexString(
    SHA256.HashData(Encoding.UTF8.GetBytes(body))).ToLowerInvariant();

var canonical = string.Join("\n", "POST", Path, timestamp, nonce, bodyHash);

using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret));
var signature = "v1=" + Convert.ToHexString(
    hmac.ComputeHash(Encoding.UTF8.GetBytes(canonical))).ToLowerInvariant();
```

#### Go

```go
body, err := json.Marshal(payload) // serialize ONCE
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
nonce := uuid.NewString()
sum := sha256.Sum256(body)
bodyHash := hex.EncodeToString(sum[:])

canonical := strings.Join([]string{"POST", path, timestamp, nonce, bodyHash}, "\n")

mac := hmac.New(sha256.New, []byte(apiSecret))
mac.Write([]byte(canonical))
signature := "v1=" + hex.EncodeToString(mac.Sum(nil))
```

#### PHP

```php
$body = json_encode($payload); // serialize ONCE
$timestamp = (string) time();
$nonce = bin2hex(random_bytes(16));
$bodyHash = hash('sha256', $body);

$canonical = implode("\n", ['POST', $path, $timestamp, $nonce, $bodyHash]);
$signature = 'v1=' . hash_hmac('sha256', $canonical, $apiSecret);
```

### 実際に送られるリクエスト

どの言語で署名しても、SotaAgents が受け取るのはこの形です。timestamp と nonce のヘッダーは canonical string に入れたものと同じ値である必要があります。nonce は一度だけ受け付けられ、再送は 5 分間拒否されます。

HTTP

```
POST https://app.sotaagents.ai/api/embed/auth/tickets
content-type: application/json
x-sota-key: sota_ek_...
x-sota-timestamp: 1786800000
x-sota-nonce: 3f1c9a7e-5b02-4d6f-9a11-0c8e2d4b7f30
x-sota-signature: v1=4d5e...

{"externalUserId":"e-1042","email":"an.tran@company.com"}
```

| ヘッダー | 値 |
| --- | --- |
| `x-sota-key` | API key（`sota_ek_…`）。secret ではありません |
| `x-sota-timestamp` | 署名したものと同じ Unix 秒。5 分より古いリクエストは拒否されます |
| `x-sota-nonce` | リクエストごとに一意。重複は replay として扱われます |
| `x-sota-signature` | `v1=` に小文字 hex の HMAC を続けたもの |

SotaAgents は `201` と共通エンベロープ `{ success: true, data: { ticket, expiresAt }, timestamp }` を返します。**エンベロープを外してください。**内側の `data` をブラウザーに返します。SDK は最上位の `ticket` を読むため、エンベロープのままでは不正な ticket と見なされ、通信は `200` なのにパネルが永久に表示されない状態になります。エラー応答は_包まれません_。`{ statusCode, code, message }` がそのまま返るので、`code` は最上位から読んでください。ticket の有効期間は 60 秒で、交換は 1 回だけです。

**レート制限。**ticket の発行は **API key ごとに毎分 60 リクエスト**、**送信元 IP ごとに毎分 120 リクエスト**までです。iframe 内での ticket 交換は**毎分 10 回**までで、エンドユーザーの IP と ticket の両方を単位に数えます。超過すると `Retry-After` 付きの `429` が返ります。汎用の 4xx にまとめず、そのまま SDK に渡してください。SDK が backoff して再試行します。バックエンド全体が 1 つの送信元 IP を共有し、1 つのオフィス NAT の背後にいる全員が交換の枠を共有するため、サインインのピークをこの数値と突き合わせ、足りない場合は公開前にご相談ください。

### フロントエンドの責務

`<script src="https://app.sotaagents.ai/embed/sdk.js"></script>` を読み込んで初期化します。重要な点は 2 つ。ticket 取得の呼び出しに自社セッション cookie を付けること、そしてサインアウト時に先に SotaAgents セッションを失効させることです。

以下のサンプルの origin は例です。tenant ごとの embed origin は SotaAgents 担当から受け取ってください。production と staging では異なります。この origin、SDK スクリプトの URL、ticket API のベース URL は、コードではなく設定に置いてください。HTTPS でない `embedUrl` は SDK が拒否します。

TypeScript

```
const embed = window.SotaEmbedSDK.createSotaEmbed({
  embedUrl: 'https://app.sotaagents.ai/embed',
  mode: 'bubble',
  getTicket: async () => {
    const response = await fetch('/api/sota/embed-ticket', {
      method: 'POST',
      credentials: 'include',
    });
    if (!response.ok) {
      // Status rides along so the SDK can fast-fail a 401 or 409 instead of
      // retrying a permanent failure four times.
      throw Object.assign(new Error('ticket_failed'), { status: response.status });
    }
    return response.json(); // { ticket, expiresAt }
  },
});

// On sign-out: revoke the SotaAgents session BEFORE clearing your own.
const revoked = await embed.logout();
if (!revoked) console.warn('SotaAgents session may still be active');
await fetch('/api/logout', { method: 'POST', credentials: 'include' });
```

> [!WARNING]
> サインアウトの前に失効させる
>
> SotaAgents のセッションは embed のオリジンに存在するため、自社セッションを消しても影響しません。`logout()` を省くと、そのブラウザーで次にサインインした人が生きたセッションを引き継ぎ、前のユーザーの会話に入り込みます。先に失効させ、その後に自社セッションを消してください。失効を確認できなかった場合は `false` を返します。自社ポータルからのサインアウトはそのまま進めつつ、共用端末やキオスクではセッションがまだ生きている可能性をユーザーに伝えてください。

### 自社ブランドに合わせる

ここにある項目はすべて任意で、既定値はいずれも SotaAgents 標準のままです。何も設定しなければ見た目は今と変わりません。設定すれば、チャットは当社ではなく貴社の名前をまといます。

コード

```
createSotaEmbed({
  embedUrl: 'https://app.sotaagents.ai/embed',
  getTicket,

  // Inside the iframe
  language: 'vi',                  // 'en' | 'vi' | 'ja'
  branding: {
    logoUrl: 'https://intranet.acme.com/logo.svg',
    showUser: false,
    greeting: 'How can the Acme assistant help?',
    placeholder: 'Ask about policies, invoices, anything',
  },

  // The bubble chrome, drawn on your own page
  mode: 'bubble',
  title: 'Acme Assistant',
  primaryColor: '#0b5cff',
  position: 'bottom-left',
  width: 420,
  height: 640,
  openOnLoad: false,
});
```

**2 つの設置形態。**`mode` が取る値はちょうど 2 つです。既定は `'bubble'` で、SDK が自社ページ上に独自のランチャーとパネルを描画し、`container` は無視されます。`'inline'` は指定した要素に iframe を直接置きます。ランチャーもパネルもなく、`container` が必須で、無い場合は生成時に例外を投げます。見積もりに関わる違いがもう 1 つあります。bubble は iframe を遅延生成し、最初のクリックまで作らないため、誰かがチャットを開くまで認証は走りません。inline は読み込み時に生成するため、ticket エンドポイントの不具合はすぐ表面化し、ページ表示ごとに ticket を 1 枚消費します。

**チャット内部。** これらはサインイン後に届くのではなく iframe の URL に乗るため、ユーザーが最初に見るフレームからすでに貴社仕様です。SotaAgents のロゴが一瞬見えてから差し替わることはありません。

| オプション | 既定値 | 効果 |
| --- | --- | --- |
| `language` | ブラウザーに追従 | `en`、`vi`、`ja`（`vn` は `vi` として受け付けます）。固定ではなく初期値です。チャット内でユーザーが言語を切り替えた場合、そのセッションでは切り替え後の言語が保持されます |
| `branding.logoUrl` | SotaAgents ワードマーク | サイドバーと挨拶文の横に表示される自社ロゴ。絶対 `http(s)` URL である必要があり、それ以外は無視されて既定に戻ります |
| `branding.showLogo` | `true` | `false` でロゴを一切描画しません。`logoUrl` と併記した場合はこちらが優先されます |
| `branding.showUser` | `true` | `false` でサイドバー下部のサインイン中ユーザー欄を隠します。自社ページ側で誰がサインインしているか既に示している場合はこちらが適切です |
| `branding.greeting` | "How can I help you today?" | 新規チャット画面の一文 |
| `branding.placeholder` | "Ask anything" | 入力欄のプレースホルダー |

greeting と placeholder は 120 文字で切り詰められます。一文には十分で、入力欄を画面外へ押し出すには短い長さです。

**bubble の外枠。** SDK が iframe の外側、貴社ページ上に描画するランチャーとパネルです。`title` を除き `mode: 'inline'` では無視され、サイズは渡した `container` が、周囲の見た目は貴社ページが決めます。

| オプション | 既定値 | 効果 |
| --- | --- | --- |
| `title` | `SotaAgents` | パネルヘッダーの文字列。未設定ならヘッダーには操作ボタンだけが並びます。支援技術に向けた iframe の名前もこれが決め、そちらは `mode: 'inline'` でも有効なため、この表で唯一 bubble 専用ではない行です。未設定ならスクリーンリーダーはフレームを _SotaAgents_ と読み上げます。white-label するなら設定してください |
| `primaryColor` | `#2f6bff` | ランチャーとパネルヘッダー |
| `position` | `bottom-right` | または `bottom-left` |
| `width` / `height` | `400` / `620` | パネルのサイズ（px）。_Expand_ ではこれを超えて広がります |
| `zIndex` | `2147483000` | 自社の要素より下に置きたい場合は下げてください |
| `openOnLoad` | `false` | `true` でランチャーのクリックを待たずに読み込み時点でパネルを開きます |

iframe 自体に関わるものがもう 2 つあります。`allowMicrophone` は既定でオフで、音声入力に必要です。`sandbox` は既定の `allow-scripts allow-same-origin allow-forms allow-popups` を置き換えます。ここは HTML の慣習とは逆で、**`sandbox: ''` は最も厳しい設定ではなく、属性そのものを取り除きます**。iframe の分離もろとも失われます。厳しくしたい場合は、より狭いトークンの並びを渡してください。空文字列は決して渡さないでください。理由がない限りどちらも触らないでください。

> [!WARNING]
> ロゴは HTTPS で配信する
>
> チャットは HTTPS で動くため、ブラウザーは `http://` のロゴを黙って昇格させたうえでブロックします。自社のマークは消え、SotaAgents のマークが戻り、理由を示す失敗リクエストは network タブに現れません。ブランディングで最も多い落とし穴です。本番と同じ方式で配信されるページで確認してください。

### サードパーティ cookie

embed が自社ポータルと別サイトで動く場合、そのセッション cookie はサードパーティ cookie になります。

| ブラウザー | 挙動 | 結果 |
| --- | --- | --- |
| Chrome、Edge | サイトごとに分割して cookie を保持 | 完全な session |
| Firefox | 既定でサードパーティ cookie を分割 | 完全な session |
| Safari | サードパーティ cookie をブロック | 10 分間のトークンにフォールバックし、自動で再認証 |

フォールバックでも動作しますが、数分ごとに再認証が走ります。reverse proxy で自社サイトのサブドメイン（例: `ai.example.com`）から embed を配信すると cookie が first-party になり、どのブラウザーでもこの問題がなくなります。その際の注意は 2 点。proxy に `Set-Cookie` を書き換えさせないこと、そしてチャット応答は stream されるためバッファリングを無効にすることです。

### 公開前チェック

- secret は secret manager にあり、source control にはない。
- 対象ユーザー全員が組織の有効なメンバーである。
- ticket エンドポイントは identity をセッションからのみ読む。
- セッションを終了する全経路で、自社サインアウトの前に `logout()` が実行される。
- Workspace の credit 配分が十分である（組み込み会話も通常の会話と同じく credit を消費します）。
- embed を frame できるオリジンを自社ドメインに限定するよう、サポートに依頼する。

> [!NOTE]
> SDK の完全なリファレンス
>
> すべてのオプション、コールバック、エラーコードは Embed SDK integration guide に記載されており、動作する参照実装も付属します。SotaAgents の担当者にお問い合わせください。

## リファレンス

よくある問題のトラブルシューティング。

### トラブルシューティング

| 症状 | 考えられる原因 | 対処 |
| --- | --- | --- |
| 「Out of credit」 | 適用される pool または allocation が尽きています。 | Owner/Admin に allocation を確認してもらいます。Top-up や plan lifecycle の変更は SotaAgents 運営チームのみです。 |
| 「This organization is inactive」 | トライアルの期限切れ、または管理者による組織の一時停止です。 | Owner がアップグレードまたは再有効化します。 |
| サインインがリダイレクトを繰り返す | ブラウザに古いトークンが残っています。 | サインアウトし、対象ドメインのサイトデータを削除してから再度サインインします。 |
| 追加したドキュメントをアシスタントが使わない | Knowledge Base app/connector が未導入・未有効、未 index、または capability が未選択です。 | App/provider と indexing status を確認し、chat で Knowledge Base を明示します。 |
| `ORG_IP_DENIED` | 現在の address が有効な organization IP rule の外です。 | 許可 network に移動するか、org admin に CIDR rule 修正を依頼します。 |
| 以前は使えていたツールをアシスタントが使わなくなった | プロバイダー側でツール名や引数が変更されました。 | ワークスペース管理者が MCP サーバーの「Refresh tools」をクリックします。 |
| 「Tool call failed: not authorized」 | MCP サーバーの保存済みトークンが期限切れ、または失効しています。 | ワークスペース管理者がサーバーを切断し、再接続します。 |
| 招待メールが届かない | 迷惑メールに振り分けられたか、アドレスの入力ミスです。 | 招待を再送するか、招待リンクをコピーして直接共有します。 |
| ワークスペースは見えるが何も変更できない | 管理者権限のない Workspace Member です。 | 設定変更が必要な場合は、ワークスペース管理者に Workspace Admin の付与を依頼します。 |
| インストール済みアプリがワークスペースに表示されない | 対象 environment が利用不能またはアンインストール済み、workspace override で無効、あるいはロールにアクセス権がありません。 | 組織管理者にインストール済み environment の確認を依頼し、Workspace → Apps の override と自分のロールを確認します。 |
| Credit Logs に想定外のアプリ利用が記録されている | 想定していないワークスペースでアプリが有効になっています。 | ワークスペースの Apps タブを確認し、不要なアプリを無効化します。 |
