objectstack-ai について
objectstack-ai は、ObjectStack アプリ向けの AI スキルとツールの定義方法を説明します。AI メタデータを作成する開発者向けで、オープン版ではアプリ内エージェントの実行環境ではなく、MCP 経由で外部エージェントにアプリを公開します。
主な機能
- 01ツールと指示を含むスキルの定義
- 02プログラムによる発動条件の設定
- 03明示的に有効化したアクションのツール化
- 04MCP による ObjectStack アプリの公開
- 05ナレッジソースとアダプターの設定
- 06スキル内のツール参照の検証
活用シーン
- 01ObjectStack アプリ向けスキルの作成
- 02外部エージェントへのアプリ操作の公開
- 03外部エージェントによるアプリデータと操作への接続
- 04インデックス対象のナレッジソースの設定
MCP 対応
説明されている @objectstack/mcp プラグインは、スキーマの確認、レコード操作、明示的に有効化した業務アクションなどを MCP 経由で公開します。呼び出しには OAuth スコープ、呼び出し元の権限、行レベルセキュリティが適用されます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ objectstack-ai/ objectstack --skill objectstack-aiインストール後、Claude Code で/objectstack-aiを入力して読み込まれたか確認します。
同梱ファイルevals/skills-tools-knowledge.jsonreferences/_index.md
詳細
AI エージェント設計 — ObjectStack AI Protocol
エディションの境界。☁️ はクラウド/Enterprise 向けの機能を示しており、以下では繰り返し明記しません。 UI 内の AI ランタイム —
ask/buildエージェント、製品内チャット、/api/v1/ai/*(@objectstack/service-ai)— はクラウド/EE で提供され、オープンなフレームワークには含まれません。@objectstack/spec/aiの スキーマ はオープンなままなので、いずれの場合も*.skill.ts/*.tool.tsをソースとして作成できますが、実行できるのはクラウド/EE ホストのみです。オープンエディションには製品内エージェントはありません。代わりに、以下の MCP を使って独自の AI にアプリを公開し、AI コーディングエージェント(Claude Code、Cursor)を使って ソースモードでメタデータを作成してください。
Agent → Skill → Tool
│ │ │
│ │ └─ Atomic operation (query, action, flow, API call)
│ └─ Capability bundle with instructions & trigger conditions
└─ Autonomous actor with role, instructions, and guardrails
エージェントはプラットフォーム内部のものです(☁️ ask / build。下部のリファレンスセクションを参照してください)。スキルが利用の起点です — スキルを作成してプラットフォームを拡張し、スキル内でツールを指定して利用します。
スキルの設定
スキルは、専用の指示とトリガー条件を備えた、名前付きのツールのセットです。
| 必須 | 型 | 説明 |
|---|---|---|
name | snake_case | 一意のスキル ID(/^[a-z_][a-z0-9_]*$/) |
label | string | 表示名 |
tools | string[] | このスキルが提供するツール名(末尾のワイルドカードを使用できます。例:action_*)— すべての名前が解決可能である必要があります。以下の解決手順を参照してください |
| 任意 | 用途 |
|---|---|
surface | 'ask' | 'build' | 'both' — このスキルを割り当てるプラットフォームエージェント(デフォルトは 'ask')。ロード時に resolveActiveSkills で検証されます。不適合な割り当てはロード時に即座にエラーになります(ADR-0063 §3) |
description | スキルの機能 — エージェントはこれを読んで、いつスキルを使うか判断します |
instructions | このスキルのコンテキスト向けのプロンプトガイダンス。オープンエディションが読み取る唯一のフィールドです。@objectstack/mcp はこれを MCP の prompts プリミティブに投影するため、instructions が空のスキル、または active: false のスキルは、プロンプトとして一覧表示されません |
triggerConditions | プログラムによる有効化ルール(以下を参照) |
active | 有効かどうか(デフォルトは true) |
スキルに
permissionsキーはありません — 何も制限していなかったため、17.0.0 で削除されました。制限は エージェント(defineAgentのaccess/permissions。チャットルートで適用)またはツールが呼び出すアクションで設定してください(ADR-0066)。
ツール名の指定:解決手順
skill.tools[] の各エントリーは、3 つのソースの和集合に対して解決されます(packages/lint/src/validate-ai-tool-references.ts の collectToolUniverse)。
stack.tools[].name— 独自のスタックが宣言するレコード。ADR-0109 により、デフォルトのサードパーティー向けパスでは 何も宣言しません(下記の ツールのメタデータ を参照)。PLATFORM_PROVIDED_TOOL_NAMES—packages/spec/src/system/constants/platform-tool-names.tsのPLATFORM_TOOLS_BY_PACKAGEからフラット化された、静的に登録されたプラットフォームツール。service-aiのデータ/ナレッジツールと、service-ai-studioのスキーマ/メタデータ/パッケージツールが含まれます。正確な一覧はこのファイルを参照してください。これは lint ルールが照合するレジストリです。action_<name>— 独自のスタックで AI に公開されている各アクションに対するツールです(PLATFORM_TOOL_FAMILY_PREFIXES)。アプリの機能には デフォルトでこのパスを使います。
3 つのソースのいずれにも名前がない場合は、ai-skill-tool-unresolved が発生します(警告、ADR-0078 によりアドバイザリーを優先)。このルールは、監査済みのあるアプリで、6 つのスキルにわたって架空のツールが 10 個定義されていたにもかかわらず、validate / lint を問題なく通過し、実際には備えていない能力があると主張するコパイロットになってしまったことを受けて設けられました。
スキルの例
import { defineSkill } from '@objectstack/spec';
export default defineSkill({
name: 'case_management',
label: 'Case Management',
description: 'Triage, query, and escalate support cases.',
instructions: `
When managing cases:
- Always check for duplicate cases before creating a new one.
- Set priority by customer tier: Enterprise → High, Pro → Medium, Free → Low.
- Escalated cases must summarise the actions already taken.
`,
// Every name resolves: two platform tools (rung 2) plus one action tool
// materialised from this stack's own `escalate_case` Action (rung 3).
tools: ['query_records', 'get_record', 'action_escalate_case'],
triggerConditions: [
{ field: 'objectName', operator: 'eq', value: 'support_case' },
],
active: true,
});
トリガー条件
各条件は { field, operator, value } で、同じ階層の条件とは AND で結合されます。
value の形式は operator に連動します。形式が一致しない場合は、型変換されずに
解析エラーになります(packages/spec/src/ai/skill.zod.ts:37-51, 139-202)。
| 演算子 | 意味 | value に必要な形式 |
|---|---|---|
eq | 等しい | 文字列。配列は参照の同一性で判定されるため、一致しません |
neq | 等しくない | 文字列。配列の場合は常に実行されます |
in | リスト内にある | 配列(空の [] も使用可能で、有効な述語です) |
not_in | リスト内にない | 配列 |
contains | 部分文字列、または配列のサブセット | どちらでも可 — 両方の形式が実行されます |
フレーズには一致しません。ルーティングには triggerConditions を使用し、
自然言語による意図は、モデルが読み取る description / instructions に記述します。
AI ツールとしてのアクション — デフォルトの方法 ☁️
通常、アクションを呼び出すためのツール定義を手作業で作成する必要はありません。
defineObject({ actions: [...] }) を使ってオブジェクトに追加した Action は、
明示的に有効化した場合に限り、action_<actionName> という名前のツールになります。
有効化には ai.exposed: true(デフォルトは false)と、40 文字以上の
ai.description が必要です。これらがない場合、解析時に拒否されます(ADR-0011)。
registerActionsAsTools() は有効化されたアクションを走査します。
ツール公開が自動的に行われることはなく、無効化用のキーもありません。
次の 3 種類のアクションはヘッドレスでディスパッチされます。
action.type | ディスパッチ | 接続方法 |
|---|---|---|
script | IDataEngine.executeAction(object, target, ctx) — Studio の行ツールバーと同じ | なし |
api | action.target への HTTP 呼び出し(デフォルトでは fetch ベース) | AIServicePlugin({ apiActionBaseUrl, apiActionHeaders }) またはカスタムの apiClient |
flow | IAutomationService.execute(target, { triggerData }) | カーネルに登録された automation サービス |
有効化されていてもスキップされるアクション: UI 専用の種類(url、modal、form)。
また、危険なバリアント(宣言された mode: 'delete' / variant: 'danger' のみ。
confirmText はダイアログの文言であり、破壊的な操作を示すものではありません。
ai.requiresConfirmation はいずれの場合も優先されます)もスキップされます。
ただし、プラグインが enableActionApproval: true で実行されている場合は、
代わりに承認キューに送られます。
type:'api' のリクエストボディの組み立て順(後の値が優先されます):ユーザーパラメーター
→ recordIdParam(recordIdField を使用。デフォルトは 'id')→ bodyExtra。
bodyShape: { wrap: 'data' } を指定すると、ユーザーパラメーターを data の下にネストし、
recordIdParam はフラットなままにします。
人間参加型の承認。 AIServicePlugin({ enableActionApproval: true })(デフォルトは
false)を指定すると、危険なアクションを実行する代わりに ai_pending_actions の行を
保存し、{ status: 'pending_approval', pendingActionId } を返します。オペレーターは
Studio の AI Pending Actions インボックス、または
GET/POST /api/v1/ai/pending-actions/... を通じて承認または却下します。
どのアクションが保留されるかは、上記のスキップルールだけで決まります。
actionSkipReason(action, ctx) と actionRequiresApproval(action)(@objectstack/service-ai から
提供)は、どちらの判定にも使用できます。Studio の「AI exposure」診断でも同じ判定条件が使われます。
MCP — オープンエディションの AI パス
@objectstack/mcp は Model Context Protocol 経由でアプリを公開するため、
外部エージェント(Claude、Cursor、Codex、…)が クラウドライセンスなしで
アプリを読み取り、操作できます。(外部 MCP サーバーを利用する受信側の姉妹パッケージは
@objectstack/connector-mcp です。)
import { MCPServerPlugin } from '@objectstack/mcp';
kernel.use(new MCPServerPlugin());
HTTP エンドポイントはデフォルトで有効で、ランタイムディスパッチャーによってリクエストごとに
POST /api/v1/mcp で提供されます。起動するものはありません(無効にするには
OS_MCP_SERVER_ENABLED=false を指定します)。長時間稼働する stdio トランスポートには
独自のスイッチがあり、デフォルトでは無効です。
autoStart: true にするか、OS_MCP_STDIO_ENABLED=true を指定します。
(OS_MCP_SERVER_ENABLED=true でも起動しますが、非推奨であり、起動時に警告が表示されます。)
クライアントから見えるツールは、registerObjectTools / registerActionTools によって登録されます。
各ツール群は呼び出し元の OAuth スコープによって制御され、すべての呼び出しは呼び出し元の権限と
行レベルセキュリティに従います。
| ツール | 内容 |
|---|---|
list_objects, describe_object | スキーマのイントロスペクション(デフォルトではシステムオブジェクトを除外) |
query_records, get_record | 読み取り — フィルター、フィールド選択、並べ替え、ページネーション |
aggregate_records | GROUP BY 集計。データブリッジが aggregate を実装している場合にのみ登録 |
validate_expression | 数式をメタデータに登録する前に、ビルドに即した CEL チェックを実行 |
create_record, update_record, delete_record | 書き込み。delete_record には破壊的操作の注釈があります |
list_actions, run_action | AI に公開するビジネスアクション — 上記と同じ ai.exposed オプトイン |
ナレッジソース(RAG)
RAG のプリミティブは KnowledgeSource(@objectstack/spec/ai の KnowledgeSourceSchema)です。これは、インデックス対象と、処理を担う IKnowledgeAdapter の ID を組み合わせる宣言的なメタデータです。これらを登録する defineStack コレクションはありません。実行時に登録され、☁️
search_knowledge ツールによって、登録済みソースがエージェントに公開されます。
接続方法(オープンパッケージ)。 @objectstack/service-knowledge の KnowledgeServicePlugin({ sources }) が、カーネルに IKnowledgeService を登録し、起動時に各ソースを登録します(service.registerSource は後からでも使用できます)。adapter ID はアダプタープラグインに対応します。たとえば、@objectstack/knowledge-memory('memory'、開発/テスト用)や @objectstack/knowledge-ragflow('ragflow')です。アダプターがない場合、その ID は解決できません。
| プロパティ | 用途 |
|---|---|
id | スネークケースのソース ID |
label / description | 表示用メタデータ |
adapter | アダプター ID(例:'ragflow'、'memory')。IKnowledgeService.registerAdapter で解決されます |
adapterConfig | アダプター固有の設定(サービスからは内容を解釈しません) |
source | インデックス対象。kind によって 'object' | 'file' | 'http' に判別されます |
embedding | 省略可能な EmbeddingModelSchema 参照(provider、model、dimensions)。埋め込みを内部で管理するアダプター(RAGFlow、Dify、Vectara)は無視する場合があります |
vectorStore | 省略可能な VectorStoreSchema 参照(provider、collection)。同じ注意事項が適用されます |
refresh | onRecordChange(オブジェクトソースでは既定で true)と省略可能な cron(外部スケジューラー用。自動スケジュールはされません) |
aiExposed | search_knowledge でこのソースをエージェントに公開するかどうか(既定値は true)。false にすると、インデックスには登録されますが、エージェントから検索できません |
source.kind | フィールド | 適切な運用 |
|---|---|---|
object | object、contentFields[](最小 1 件。* = 読み取り可能なテキストフィールドすべて)、metadataFields?、where?(ObjectQL の where 構文) | where で下書きやアーカイブ済みのレコードをインデックス対象から除外します。contentFields には意味のあるテキストだけを指定し(システムフィールドや ID は含めないでください。* の使用は控えてください)、クエリ時に絞り込みに使う項目(status、owner_id、tags)を metadataFields に含めます |
file | prefix(ストレージのプレフィックス。例:kb/handbooks/)、mimeTypes? | バケット全体をインデックスするのではなく、プレフィックスを絞り込みます |
http | urls[]、userAgent? | URL を明示的に列挙してください。クローラーはありません |
import { KnowledgeSourceSchema, type KnowledgeSource } from '@objectstack/spec/ai';
export const supportKb: KnowledgeSource = KnowledgeSourceSchema.parse({
id: 'support_kb',
label: 'Support Knowledge Base',
adapter: 'ragflow', // or 'memory' for dev/test
source: {
kind: 'object',
object: 'kb_article',
contentFields: ['title', 'body'], // concatenated into document content
metadataFields: ['category', 'owner_id'], // projected for search-time filtering
where: { published: true }, // index published articles only
},
refresh: { onRecordChange: true }, // re-index on record.* events
});
チャンク分割、top-K、スコアしきい値、リランカーはプラットフォームのメタデータではありません。 仕様では意図的に対象外とされています(
embedding.zod.ts)。これらは アダプター(adapterConfig)またはアプリケーションコードに属します。プラットフォームが扱うのは 埋め込みとベクトルのプリミティブのみであるため、任意の RAG 戦略をその上に構築できます。
ツールのメタデータ(defineTool)— デフォルトの方法ではありません
デフォルトでは、ツールレコードを宣言しません。 スキルでは、プラットフォームツールまたは action_<name>(上記の段階)を指定します。ADR-0109 によると、stack.tools レコードは「AI 向けの提示を洗練する場合にのみ存在し(フェーズ 2:LLM の説明、パラメーターの絞り込み、フローへの公開)、それが実装されるまではランタイムから読み取られることはない」とされています(packages/spec/src/stack.zod.ts:595-602)。既存の機能の提示方法を洗練する場合に限って作成してください。機能を追加したり、何かを実行可能にしたりするために作成してはいけません。ToolSchema には handler / implementation フィールドがなく、メタデータで記述されたツールを読み込むフレームワーク実行機能もありません。
ToolSchema は厳密です。不明なキー(誤字や廃止済みのキー)は、黙って削除されるのではなく、解析エラーになります。name / label / description と JSON Schema の parameters オブジェクトは必須です。objectName と outputSchema は任意です(⚠️ 試験的な機能です。ツールレコードでは参照されません。代わりにスキーマをアクションの ai.outputSchema として宣言してください。AI ランタイム ☁️ は、適合しない結果を返さないことでこれを強制します)。プロトコル 17 で廃止された category、permissions、active、builtIn(いずれも記述可能でしたが機能しませんでした)は、requiresConfirmation に続いて廃止されました。各項目のエラーメッセージには代替手段が示されます。
ツールに許可する操作は、基盤となるアクション(action.requiredPermissions、ADR-0066)またはツールが操作するオブジェクトで制限します。ツールを無効にするには、そのツールを参照しているスキルから削除します。分類はアクション(action.ai.category)に指定します。これは有効ですが、一覧表示専用です。ツールには引き継がれますが、モデルには送信されません。
モデルの設定
サンプリングパラメーターはエージェントの model(AIModelConfigSchema)に設定します。エージェントにトップレベルの temperature / maxTokens はありません(packages/spec/src/ai/agent.zod.ts:36-40)。
| キー | 仕様 |
|---|---|
provider | インライン列挙型 openai | azure_openai | anthropic | local(デフォルトは openai)。モデルレジストリのエントリー(ModelProviderSchema)では、より多くの値を使用できます。google、cohere、huggingface、custom も指定できます |
model | 自由形式の文字列。プロバイダー固有のモデル名です |
temperature | min(0).max(2)、デフォルトは 0.7。0~2 の範囲外は解析エラーになります |
maxTokens / topP | 任意の数値です。スキーマによる上限はありません |
よくある落とし穴
guardrailsをゲートだと誤解する。guardrailsは AI ランタイム ☁️ がユーザーのターンごとに適用します。トークン数や時間の制限、ブロック対象のツール名やカテゴリの拒否などを設定できますが、これは制限であり、承認ではありません。memoryも AI ランタイム ☁️ が適用します。長期メモが想起され、振り返りに利用されます。longTerm.enabledが true の場合、maxEntriesとreflectionIntervalは必須です。選択可能なストレージバックエンドはありません。こちらもゲートではありません。強制されるゲートには、enableActionApproval: true(承認キュー ☁️)、アクションのai.requiresConfirmation、または MCP ツールのバインディングにあるapproval: 'always'を使用してください。AI メタデータの編集には、すでにゲートが設けられています。人間が公開する必要のあるドラフトとして反映されます(ADR-0033)。⚠️ ツールのrequiresConfirmationは削除されました(ADR-0033 §2)。実行経路で読み取られないため、処理を一時停止させる効果はありません。ToolSchemaは厳密なので、現在これを記述すると解析に失敗します。requireApprovalForフィールドはありません。- すべてをインデックス化する。
whereフィルターと厳選したcontentFieldsを設定していないナレッジソースは、ドラフトや定型文でインデックスを埋め尽くし、検索結果の精度を下げます。ソースの整理はメタデータで行い、関連性の調整はアダプターで行います。
アプリ AI の設計図
| レイヤー | ファイル | パターン |
|---|---|---|
| 再利用可能なスキル | src/skills/lead-qualification.skill.ts | defineSkill — instructions + トリガー条件 + すべての名前が解決されるツールセット。surface を選択します |
| ナレッジソース | src/knowledge/sales-kb.ts | KnowledgeSourceSchema のメタデータ。起動時に KnowledgeServicePlugin({ sources }) を介して登録します |
| 一元登録 | defineStack({ skills: [...] }) | agents / tools / skills は AI スタックのコレクションとして唯一のものです。ナレッジソースは含まれず、エージェントはプラットフォームから提供され、tools はデフォルトの方法ではありません |
メタデータアプリのデフォルト:ビジネス機能をスキルに集約し、 ビジネスロジックをAI に公開するアクションとして公開し、ドメイン知識を ナレッジソース経由で連携します。
プラットフォームエージェント — 参考情報のみ ☁️
agent タイプはサードパーティには非公開です(allowRuntimeCreate:false、
allowEnvironmentOverlay:false。ADR-0063 §2)。また、os g agent は廃止されています。スタックが定義したエージェントは listAgents() でフィルタリングされ、loadAgent() では明示的に拒否され、チャットでは 404 になります。プラットフォームを拡張するには、エージェントを追加するのではなく、スキルを追加します。AgentSchema の全フィールド一覧は
references/_index.md を参照してください。
ランタイムに搭載されるエージェントは、利用サーフェスに紐づくちょうど 2 つです。ユーザーが一覧から選ぶのではなく、利用中のサーフェスによってエージェントが選択されます。ask はデータプロダクト(≈ Claude Chat)で、レコードの対話型の読み取り/クエリ/探索と、アプリが公開するビジネスアクションの実行を行います。エンドユーザー向けで、RLS の範囲内に制限され、正規 ID は ask(ASK_AGENT_NAME)です。また、app.defaultAgent が固定されていないすべてのアプリで、暗黙的にコパイロットとして使われます。build はオーサリングプロダクト(≈ Claude Code)で、計画 → ドラフト → 検証 → 公開の手順でメタデータをエージェント的に作成します。ビルダー向けで、ガバナンスによる制御があり、Studio が app.defaultAgent を通じて固定します。ターンごとのインテント分類器はありません。ask に build 向けのリクエストが届いた場合は、断って適切な先へ誘導します。オーサリングに黙って振り替えることはありません(ADR-0063 §1/§5)。data_chat→ask と
metadata_assistant→build は、古いブックマークや永続化された agent_id 向けにエイリアステーブルを通じて解決されます。これらは正式な用語ではありません。常に ask/build と記述してください。
エージェントのツールセットは、サーフェスに互換性のあるスキルのツールの和集合です。グローバルなフォールスルーはないため(ADR-0064)、ask は構造上オーサリングできません。スキルを無効化すると(active: false)、そのスキルを参照するすべてのエージェントから、その機能が取り消されます。組み込みスキルは次のとおりです。
| スキル | surface | 担当 |
|---|---|---|
schema_reader | both | list_objects、describe_object、query_data |
data_explorer | ask | query_records、get_record、aggregate_data、visualize_data |
actions_executor | ask | action_*(オブジェクトが公開するビジネスアクション) |
metadata_authoring + solution_design | build | メタデータのドラフト/検証/公開 + ブループリントの提案/適用 |
4 つともクラウドランタイム向けのスキルです。オープンエディションではいずれも解決されないため、独自スキルの surface/tools/triggerConditions はクラウド向けに定義します。そこでこれらが機能することはありません。MCP が提供するのは instructions です。
チャートを描画する組み込み機能は visualize_data のみです(インラインの data-chart パート)。これは分析サービス(IAnalyticsService)が接続されている場合に限り、自動登録されます。query_data/aggregate_data が返すのは数値であり、チャートではありません。
AgentSchema の 2 つのキーは、レガシーオプションではなく廃止済みのキーです。どちらを定義しても、移行方法を含むパースエラーになります
(packages/spec/src/ai/agent.zod.ts:234, :251)。
| 廃止されたキー | プロトコル 17 で削除 — 理由と置き換え方法 |
|---|---|
agent.tools | インライン枠では、サーフェスを確認せず、完全なレジストリに対して名前を解決していました。単なる名前変更ではありません。移行ではこのキーを削除し、列挙されていた各ツールを名前で指定します。それぞれをスキルで再宣言してください(ADR-0064) |
agent.knowledge | エージェントにソース/インデックスを宣言しても、検索対象の範囲は制限されませんでした。search_knowledge はモデルのツール呼び出し引数から sourceIds を取得します。ナレッジサービス/ソースのレベルで制限し、意図するグラウンディングは instructions に記述してください |
作業の検証
*.skill.ts/*.tool.ts を定義した後、完了を報告する前に、作成時のゲートを実行してください。
os validate # Zod schema + CEL predicate validation + bindings (no artifact)
# or: os build # the same gates, plus emits dist/
これにより、スキル/ツールのメタデータがプロトコルに準拠していることを確認できます。このドメインに CEL の使用箇所はありません。モデルレジストリの promptTemplate.system/.user は template 方言({{var}})を使用します。ToolSchema に式フィールドは一切ありません。スキャフォールド済みプロジェクトでは、ゲートは npm run validate です。objectstack-platform の 作業の検証を参照してください。
参考資料
Zod スキーマの一覧(各スキーマの1行の説明付き)は、references/_index.md を参照してください。各スキーマから node_modules/@objectstack/spec/src/ 内の該当箇所に移動できます。フィールドの正確な形式を確認するには、必ずソースを Read してください。プロパティ名を記憶に頼ってはいけません。