概要
Shannonは、永続的なストレージのためにPostgreSQLとpgvector拡張を使用しています。データベースは2つのスキーマに整理されています:auth- 認証、マルチテナンシー、およびセキュリティpublic- コアアプリケーションテーブル(タスク、エージェント、セッション)
拡張機能: uuid-ossp, pg_trgm, btree_gin, pgcrypto
エンティティリレーションシップ図
スキーマ: auth (認証とマルチテナンシー)
auth.tenants
目的: マルチテナントの組織管理| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT gen_random_uuid() | テナント識別子 |
| name | VARCHAR(255) | NOT NULL | 組織名 |
| slug | VARCHAR(100) | UNIQUE, NOT NULL | URLセーフ識別子 |
| plan | VARCHAR(50) | DEFAULT ‘free’ | サブスクリプションプラン(free, pro, enterprise) |
| token_limit | INTEGER | DEFAULT 10000 | 月間トークン許容量 |
| monthly_token_usage | INTEGER | DEFAULT 0 | 現在の月の使用量 |
| rate_limit_per_hour | INTEGER | DEFAULT 1000 | APIレート制限 |
| is_active | BOOLEAN | DEFAULT true | テナントのステータス |
| created_at | TIMESTAMP | DEFAULT NOW() | 作成時間 |
| updated_at | TIMESTAMP | DEFAULT NOW() | 最終更新時間 |
| metadata | JSONB | DEFAULT '' | 追加のテナントデータ |
slugに対する主キー(UNIQUE)
auth.users
目的: ユーザー認証とプロフィール管理| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT gen_random_uuid() | ユーザー識別子 |
| VARCHAR(255) | UNIQUE, NOT NULL | ユーザーのメール | |
| username | VARCHAR(100) | UNIQUE, NOT NULL | ユーザー名 |
| password_hash | VARCHAR(255) | NOT NULL | Bcryptパスワードハッシュ |
| full_name | VARCHAR(255) | フルネーム | |
| tenant_id | UUID | FK → auth.tenants, NOT NULL | 組織 |
| role | VARCHAR(50) | DEFAULT ‘user’ | 役割(user, admin, owner) |
| is_active | BOOLEAN | DEFAULT true | アカウントのステータス |
| is_verified | BOOLEAN | DEFAULT false | メール確認 |
| email_verified_at | TIMESTAMP | 確認タイムスタンプ | |
| created_at | TIMESTAMP | DEFAULT NOW() | アカウント作成 |
| updated_at | TIMESTAMP | DEFAULT NOW() | 最終更新 |
| last_login | TIMESTAMP | 最終ログイン時間 | |
| metadata | JSONB | DEFAULT '' | 追加のユーザーデータ |
idx_users_emailON (email)idx_users_usernameON (username)idx_users_tenant_idON (tenant_id)
auth.api_keys
目的: プログラムによるアクセスのためのAPIキー管理| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT gen_random_uuid() | キー識別子 |
| key_hash | VARCHAR(255) | UNIQUE, NOT NULL | キーのSHA256ハッシュ |
| key_prefix | VARCHAR(20) | NOT NULL | 最初の8文字(表示用) |
| user_id | UUID | FK → auth.users | キーの所有者 |
| tenant_id | UUID | FK → auth.tenants, NOT NULL | 組織 |
| name | VARCHAR(100) | NOT NULL | キー名/説明 |
| description | TEXT | 詳細な説明 | |
| scopes | TEXT[] | DEFAULT […] | 権限配列 |
| rate_limit_per_hour | INTEGER | DEFAULT 1000 | キー固有のレート制限 |
| last_used | TIMESTAMP | 最終使用タイムスタンプ | |
| expires_at | TIMESTAMP | 有効期限 | |
| is_active | BOOLEAN | DEFAULT true | キーステータス |
| created_at | TIMESTAMP | DEFAULT NOW() | 作成時間 |
| metadata | JSONB | DEFAULT '' | 追加のキーデータ |
idx_api_keys_tenant_idON (tenant_id)idx_api_keys_key_prefixON (key_prefix)
tasks:run: タスク実行を許可tasks:read: タスクのステータスと結果の読み取りを許可sessions:manage: セッションの管理を許可
auth.refresh_tokens
目的: JWTリフレッシュトークンの保存と取り消し| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT gen_random_uuid() | トークン識別子 |
| token_hash | VARCHAR(255) | UNIQUE, NOT NULL | SHA256ハッシュ |
| user_id | UUID | FK → auth.users | トークン所有者 |
| tenant_id | UUID | FK → auth.tenants, NOT NULL | 組織 |
| expires_at | TIMESTAMP | NOT NULL | 有効期限 |
| revoked | BOOLEAN | DEFAULT false | 取り消しステータス |
| revoked_at | TIMESTAMP | 取り消し時間 | |
| ip_address | INET | クライアントIP | |
| user_agent | TEXT | クライアントユーザーエージェント | |
| created_at | TIMESTAMP | DEFAULT NOW() | 作成時間 |
idx_refresh_tokens_user_idON (user_id)idx_refresh_tokens_token_hashON (token_hash)
auth.audit_logs
目的: セキュリティイベントの監査トレイル| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT gen_random_uuid() | ログエントリID |
| event_type | VARCHAR(100) | NOT NULL | イベントタイプ |
| user_id | UUID | FK → auth.users | ユーザー(nullable) |
| tenant_id | UUID | FK → auth.tenants | テナント(nullable) |
| ip_address | INET | クライアントIP | |
| user_agent | TEXT | クライアントユーザーエージェント | |
| details | JSONB | DEFAULT '' | イベント詳細 |
| created_at | TIMESTAMP | DEFAULT NOW() | イベント時間 |
idx_audit_logs_user_idON (user_id)idx_audit_logs_tenant_idON (tenant_id)idx_audit_logs_event_typeON (event_type)idx_audit_logs_created_atON (created_at)
login- ユーザーログインlogout- ユーザーログアウトapi_key_created- APIキー生成permission_changed- ロール/権限の変更
スキーマ: public (コアアプリケーション)
users
目的: アプリケーションユーザープロファイル(レガシー、auth.usersにリンク)| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | ユーザー識別子 |
| external_id | VARCHAR(255) | UNIQUE, NOT NULL | 外部システムID |
| VARCHAR(255) | メールアドレス | ||
| tenant_id | UUID | テナント参照 | |
| metadata | JSONB | DEFAULT '' | ユーザーメタデータ |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | 作成時間 |
| updated_at | TIMESTAMPTZ | DEFAULT NOW() | 最終更新 |
idx_users_tenant_idON (tenant_id)idx_users_external_idON (external_id)
auth.usersを使用するべきです。
sessions
目的: ユーザーセッション管理とコンテキスト| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | セッション識別子 |
| user_id | UUID | FK → users | セッション所有者 |
| tenant_id | UUID | テナント参照 | |
| context | JSONB | DEFAULT '' | セッションコンテキストデータ |
| token_budget | INTEGER | DEFAULT 10000 | トークン割り当て |
| tokens_used | INTEGER | DEFAULT 0 | 消費トークン |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | セッション開始 |
| updated_at | TIMESTAMPTZ | DEFAULT NOW() | 最終活動 |
| expires_at | TIMESTAMPTZ | 有効期限 | |
| deleted_at | TIMESTAMPTZ | DEFAULT NULL | ソフト削除のタイムスタンプ |
| deleted_by | UUID | DEFAULT NULL | セッションを削除したユーザー |
idx_sessions_user_idON (user_id)idx_sessions_tenant_idON (tenant_id)idx_sessions_expires_atON (expires_at)idx_sessions_external_idON ((context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULLidx_sessions_user_external_idUNIQUE ON (user_id, (context->>‘external_id’)) WHERE context->>‘external_id’ IS NOT NULL AND deleted_at IS NULLidx_sessions_not_deletedON (id) WHERE deleted_at IS NULLidx_sessions_deleted_atON (deleted_at) WHERE deleted_at IS NOT NULL
- 外部ID(非UUIDセッションID)は
context->>'external_id'に保存され、二重IDの検索を可能にします。 deleted_atカラムによるソフト削除のサポート -deleted_atがNULLでないセッションは削除されたと見なされます。
task_executions
目的: タスク/ワークフローの実行履歴とメトリクス| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | タスク識別子 |
| workflow_id | VARCHAR(255) | UNIQUE, NOT NULL | Temporal ワークフロー ID |
| user_id | UUID | FK → users | タスク作成者 |
| tenant_id | UUID | テナント参照 | |
| session_id | VARCHAR(255) | セッション識別子 | |
| query | TEXT | NOT NULL | タスククエリ/プロンプト |
| mode | VARCHAR(50) | 実行モード (SIMPLE, STANDARD, COMPLEX) | |
| status | VARCHAR(50) | NOT NULL | タスクのステータス |
| started_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | 開始時間 |
| completed_at | TIMESTAMPTZ | 完了時間 | |
| result | TEXT | 最終結果 | |
| response | JSONB | DEFAULT '' | 構造化されたレスポンス |
| error_message | TEXT | エラー詳細 | |
| total_tokens | INTEGER | DEFAULT 0 | 使用トークン総数 |
| prompt_tokens | INTEGER | DEFAULT 0 | 入力トークン |
| completion_tokens | INTEGER | DEFAULT 0 | 出力トークン |
| total_cost_usd | DECIMAL(10,6) | DEFAULT 0 | 総コスト |
| duration_ms | INTEGER | 実行時間 (ms) | |
| agents_used | INTEGER | DEFAULT 0 | 使用されたエージェント数 |
| tools_invoked | INTEGER | DEFAULT 0 | ツール呼び出し数 |
| cache_hits | INTEGER | DEFAULT 0 | キャッシュヒット数 |
| complexity_score | DECIMAL(3,2) | 複雑さ (0.0-1.0) | |
| metadata | JSONB | 追加メタデータ | |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | レコード作成 |
idx_task_user_sessionON (user_id, session_id)idx_task_created_atON (created_at DESC)idx_task_statusON (status)idx_task_workflow_idON (workflow_id)idx_task_executions_tenant_idON (tenant_id)idx_task_executions_session_idON (session_id)
RUNNING- タスク進行中COMPLETED- タスクが正常に完了FAILED- タスクがエラーで失敗CANCELLED- ユーザーによってタスクがキャンセル
agent_executions
目的: タスク内の個々のエージェント実行の詳細| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | 実行 ID |
| task_execution_id | UUID | FK → task_executions | 親タスク |
| agent_id | VARCHAR(255) | NOT NULL | エージェント識別子 |
| execution_order | INTEGER | NOT NULL | 実行順序 |
| input | TEXT | NOT NULL | エージェント入力 |
| output | TEXT | エージェント出力 | |
| mode | VARCHAR(50) | 実行モード | |
| state | VARCHAR(50) | FSM ステート | |
| tokens_used | INTEGER | DEFAULT 0 | 消費トークン |
| cost_usd | DECIMAL(10,6) | DEFAULT 0 | 実行コスト |
| model_used | VARCHAR(100) | LLM モデル | |
| duration_ms | INTEGER | 実行時間 | |
| memory_used_mb | INTEGER | メモリ使用量 | |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | 開始時間 |
| completed_at | TIMESTAMPTZ | 完了時間 |
idx_agent_task_executionON (task_execution_id)idx_agent_created_atON (created_at DESC)idx_agent_stateON (state)
IDLE- エージェントアイドルANALYZING- 入力を分析中PLANNING- 実行を計画中RETRIEVING- 情報を取得中EXECUTING- タスクを実行中VALIDATING- 結果を検証中SYNTHESIZING- レスポンスを合成中COMPLETED- 実行完了FAILED- 実行失敗
tool_executions
目的: ツール呼び出し履歴とパフォーマンス| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | 実行 ID |
| agent_execution_id | UUID | FK → agent_executions | 親エージェント |
| task_execution_id | UUID | FK → task_executions | 親タスク |
| tool_name | VARCHAR(255) | NOT NULL | ツール識別子 |
| tool_version | VARCHAR(50) | ツールバージョン | |
| category | VARCHAR(100) | ツールカテゴリ | |
| input_params | JSONB | 入力パラメータ | |
| output | JSONB | ツール出力 | |
| success | BOOLEAN | DEFAULT true | 成功ステータス |
| error_message | TEXT | エラー詳細 | |
| duration_ms | INTEGER | 実行時間 | |
| tokens_consumed | INTEGER | DEFAULT 0 | 使用トークン |
| sandboxed | BOOLEAN | DEFAULT true | WASI サンドボックス使用 |
| memory_used_mb | INTEGER | メモリ使用量 | |
| executed_at | TIMESTAMPTZ | DEFAULT NOW() | 実行時間 |
idx_tool_nameON (tool_name)idx_tool_executed_atON (executed_at DESC)idx_tool_task_executionON (task_execution_id)idx_tool_successON (success)
search- 検索およびルックアップツールcalculation- 数学的および計算ツールfile- ファイルシステム操作api- API 呼び出しおよび統合code- コード実行および分析
event_logs
目的: 監査およびリプレイのためのイベントストレージ| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | イベントID |
| workflow_id | VARCHAR(255) | NOT NULL | ワークフロー識別子 |
| task_id | UUID | タスク参照(nullable) | |
| type | VARCHAR(100) | NOT NULL | イベントタイプ |
| agent_id | VARCHAR(255) | エージェント識別子 | |
| message | TEXT | イベントメッセージ | |
| payload | JSONB | DEFAULT '' | イベントペイロード |
| timestamp | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | イベント時間 |
| seq | BIGINT | シーケンス番号 | |
| stream_id | VARCHAR(64) | RedisストリームID | |
| created_at | TIMESTAMPTZ | NOT NULL, DEFAULT NOW() | レコード作成 |
idx_event_logs_workflow_idON (workflow_id)idx_event_logs_task_idON (task_id)idx_event_logs_typeON (type)idx_event_logs_tsON (timestamp DESC)idx_event_logs_seqON (workflow_id, seq)idx_event_logs_workflow_tsON (workflow_id, timestamp DESC)uq_event_logs_wf_type_seqUNIQUE ON (workflow_id, type, seq) WHERE seq IS NOT NULL
task.started- タスク実行開始task.completed- タスク実行完了agent.thinking- エージェント処理中tool.called- ツール呼び出し
token_usage
目的: タスクごとの詳細なトークン使用状況の追跡| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | レコードID |
| user_id | UUID | FK → users | ユーザー |
| task_id | UUID | FK → task_executions | タスク |
| provider | VARCHAR(50) | NOT NULL | LLMプロバイダー |
| model | VARCHAR(255) | NOT NULL | モデル名 |
| prompt_tokens | INTEGER | NOT NULL | 入力トークン |
| completion_tokens | INTEGER | NOT NULL | 出力トークン |
| total_tokens | INTEGER | NOT NULL | 合計トークン |
| cost_usd | DECIMAL(10,6) | NOT NULL | USDでのコスト |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | レコード時間 |
idx_token_usage_user_idON (user_id)idx_token_usage_created_atON (created_at DESC)idx_token_usage_provider_modelON (provider, model)idx_token_usage_task_idON (task_id)
usage_daily_aggregates
目的: 事前計算された日次使用統計| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
| id | UUID | PK, DEFAULT uuid_generate_v4() | レコードID |
| user_id | UUID | FK → users | ユーザー |
| date | DATE | NOT NULL | 集計日 |
| total_tasks | INTEGER | DEFAULT 0 | 合計タスク数 |
| successful_tasks | INTEGER | DEFAULT 0 | 成功数 |
| failed_tasks | INTEGER | DEFAULT 0 | 失敗数 |
| total_tokens | INTEGER | DEFAULT 0 | 合計トークン |
| total_cost_usd | DECIMAL(10,6) | DEFAULT 0 | 合計コスト |
| model_usage | JSONB | モデル分布 | |
| tools_invoked | INTEGER | DEFAULT 0 | ツール呼び出し数 |
| tool_distribution | JSONB | ツール使用分布 | |
| avg_duration_ms | INTEGER | 平均タスク時間 | |
| cache_hit_rate | DECIMAL(3,2) | キャッシュヒット率 | |
| created_at | TIMESTAMPTZ | DEFAULT NOW() | レコード時間 |
idx_usage_daily_user_dateON (user_id, date)idx_usage_daily_dateON (date DESC)
追加テーブル
tool_calls
目的: レガシーツール呼び出しの追跡(代わりに tool_executions を使用)prompts
目的: プロンプトのバージョン管理とA/Bテストlearning_cases
目的: 強化学習ケースのストレージsession_archives
目的: Redisからの長期セッションスナップショットaudit_logs (public)
目的: アプリケーション監査トレイル(auth.audit_logsとは別)データベース関数
update_updated_at_column()
目的: 行の変更時にupdated_at を自動的に更新
使用法: users および sessions テーブルにトリガーとして添付
update_daily_aggregate(user_id, date)
目的: ユーザーのために日次使用集計を更新または作成 使用法: タスク完了時にトリガーを介して自動的に呼び出されるtrigger_update_daily_aggregate()
目的: タスクのステータス変更時に集計を更新するトリガー関数 使用法: task_executions の INSERT/UPDATE 時に自動的に発火サンプルクエリ
タスク分析
コスト分析
パフォーマンス監視
ベストプラクティス
1. インデックス作成
常にインデックスを使用するべき:- 外部キー列 (user_id, tenant_id, task_execution_id など)
- 頻繁にフィルタリングされる列 (status, created_at, expires_at)
- JSONB クエリ (context->>‘external_id’)
- 時間ベースのクエリ (created_at DESC)
2. パーティショニング
高ボリュームのテーブルにはパーティショニングを検討:3. データ保持
推奨ポリシー:event_logs: 90日 (高ボリューム、アーカイブ可能)task_executions: 1年 (古いデータをアーカイブ)audit_logs: 2年 (コンプライアンス)token_usage: 日次集計、90日後に生データをアーカイブ