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 を理解します。
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。
Browser 由来の任意 actor/workspace/environment を信頼せず、signed Sota request の exact context を使用します。
アシスタントはどのように tool を呼ぶのか#
Manifest への tool 宣言は物語の半分にすぎません。ここから先が、その宣言を runtime にプラットフォームがどう扱うか——アプリを単なる host 済み web service 以上のものにしている部分です。
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 の判断材料がそれで全部だからです。
Platform が解決し認可する
Request が SotaAgents を出る前に、arguments は input schema で検証され、organization、workspace、installation、environment、そして適用される exact artifact が解決されます。その artifact に公開されていない tool、あるいはその workspace にインストールされていないアプリは、ここで拒否されます——backend には一切到達しません。
Signed request が backend に届く
Platform は、有効な environment 向けに解決された service.baseUrl の宣言済み path へ、server-to-server の HTTP request を送ります。Development では同じ request が sota dev の tunnel を通って手元のマシンに届きます。この経路に browser は介在しないため、backend が公開インターネットからユーザーに到達可能である必要はありません。
Backend が検証し、処理し、JSON を返す
Token を検証し、domain の処理を行い、JSON を返します。非 2xx、JSON として不正な body、timeout はいずれも tool の失敗として扱われます。
結果が 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 を読むのはそのためです。
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": {} }
}
}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 に留めてください。