Triết lý kiến trúc
Trong trang này
SotaAgents chủ động tách platform control plane khỏi app data plane. Platform biết user, organization, workspace, installation, selected environment, exact artifact và quyền đã cấp. Backend của app hiểu domain: tìm tài liệu, tạo CAD, gọi API riêng hay áp dụng business rules.
Tại sao app cần backend riêng?#
- Ownership độc lập: ship business logic theo nhịp riêng mà không nhét domain code vào Core.
- Security boundary: giữ credentials và third-party integration ở server; chỉ nhận signed platform context.
- Data boundary: tự chọn database, retention, residency và scaling theo domain.
- Operational isolation: app scale, fail và recover mà không kéo theo app khác.
Không tin actor/workspace/environment tùy ý từ browser. Hãy verify signed Sota request và dùng exact context platform đã chọn.
Trợ lý gọi tool của bạn như thế nào?#
Khai báo tool trong manifest mới là một nửa câu chuyện. Đây là những gì nền tảng làm với khai báo đó lúc runtime — phần khiến một app không chỉ là một web service được host.
Tool được đưa cho model
Khi workspace resolve app surface, mỗi tool đã publish trở thành một function model gọi được, tên app_<appId>_<toolName>. Development và Staging chèn thêm environment (app_my-app_stg_example); Production bỏ qua phần đó nên tên model học được ở Production luôn gọn. Ký tự mà tên model-facing không mang được — kể cả dấu chấm trong tên kiểu documents.query — chuyển thành gạch dưới; tên dài quá 64 ký tự bị cắt và thêm hậu tố hash ngắn; hai app trùng tên thì thêm hậu tố số. Description model đọc là description trong manifest của bạn, nối thêm App: <appId>. Runtime tool: <name>., còn inputSchema được đưa nguyên văn cho model làm parameter schema. Vì vậy description mơ hồ hay schema lỏng lẻo làm giảm chất lượng chọn tool ngay lập tức: đó là toàn bộ căn cứ để model quyết định.
Nền tảng resolve và authorize
Trước khi có request nào rời SotaAgents, arguments được validate theo input schema của bạn, và nền tảng resolve organization, workspace, installation, environment cùng đúng một artifact áp dụng. Tool không được publish trong artifact đó, hoặc app chưa cài cho workspace đó, bị từ chối ngay tại đây — backend của bạn không hề bị gọi tới.
Một signed request tới backend của bạn
Nền tảng gửi HTTP request server-to-server tới service.baseUrl đã resolve cho environment đang dùng, tại path bạn khai báo. Ở Development, chính request đó đi qua tunnel của sota dev về máy bạn. Browser không nằm trong đường đi này, nên backend của bạn không cần user truy cập được từ internet công cộng.
Backend verify, xử lý và trả JSON
Verify token, làm phần việc nghiệp vụ, trả JSON. Response non-2xx, body không phải JSON hợp lệ, hoặc timeout đều bị coi là tool thất bại.
Kết quả quay lại conversation
Nền tảng stream tool result vào conversation dưới dạng output part của tool, lưu lại, và nếu có UI contribution khai báo surface: tool-view với tool này trong toolNames thì render React module của bạn thay cho kết quả thô. Model nhìn thấy một bản JSON gọn của cùng kết quả đó.
Request nền tảng gửi đi#
Body là một envelope. Arguments của model nằm lồng ở body.input — đó là lý do route trong scaffold đọc request.body.body.input chứ không phải request.body.
POST https://my-app.example.com/tools/example
content-type: application/json
authorization: Bearer <invocation JWT>
x-sota-core-token: <delegated Core token> # chỉ khi app khai báo 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": {} }
}
}Các field organizationId, workspaceId và context trong body chỉ để tiện log và debug. Mọi quyết định authorization phải lấy từ claims đã verify trong JWT, vì chỉ chúng mới được ký.
Invocation token#
Header Authorization mang một JWT ngắn hạn ký bằng EdDSA, mint riêng cho lần gọi này. Backend của bạn verify nó bằng public key của nền tảng, công bố tại <core origin>/.well-known/jwks.json. App không giữ private key của Sota và không bao giờ tự mint token.
| Thuộc tính | Giá trị |
|---|---|
Algorithm / typ | EdDSA (Ed25519), header type sota-invocation+jwt |
iss | sota/invocation-token |
aud | appId của bạn — hãy từ chối token mint cho app khác |
| Thời hạn | 60 giây, chấp nhận lệch đồng hồ 30 giây |
oid / wid | Organization và workspace của lần gọi |
sub | User thực hiện, khi lần gọi có actor |
iid | Compatibility install identity dạng opaque; không suy ra Development/Staging/Production từ prefix. |
ae / aei / ag | Tên App Environment, environment identity và Backend Access Generation chính xác. Ba claim đi cùng nhau để bind quyền vào đúng backend đã resolve. |
aer | Execution reference chính xác đã ký. Công việc persist/replay phải giữ reference này thay vì resolve artifact mới hơn. |
scp | Các họ scope hiện tại gồm tool:<name>, route:prompt:<name>, route:systemPrompt:<name>, event:<name>, route:artifact:<name>, route:resolver:<path>, scope route lifecycle và app:http. Mỗi endpoint phải yêu cầu đúng scope chính xác được cấp cho bề mặt đó. |
rid | requestId trong envelope, để đối chiếu log |
Mỗi route hãy yêu cầu scope hẹp nhất: handler /tools/example nên đòi tool:example, không rộng hơn. File src/backend/sota-auth.ts trong scaffold có sẵn toàn bộ bước kiểm tra — issuer, audience, algorithm, type, hạn dùng, tenant claims và scope — trong một middleware dùng lại được.
Response phải trông như thế nào#
Trả JSON HTTP bình thường. Không có wrapper riêng nào của Sota phải dựng.
| Kết quả | Nền tảng xử lý |
|---|---|
| 2xx kèm body JSON | Thành công. Body trở thành tool result. |
| Non-2xx | Thất bại. Nếu body là { "code": "…", "message": "…" } — có thể kèm details và hint — đúng các giá trị đó được mang đi thay cho thông báo chung chung. Hãy trả status code thật thay vì body lỗi đội lốt thành công. |
| Body không phải JSON hợp lệ | Thất bại với VALIDATION_ERROR. |
| Không kịp trả lời trong deadline | Thất bại với TIMEOUT. |
outputSchema không được kiểm tra với response lúc runtime — nó được kiểm tra khi publish, nơi nó dùng để phát hiện breaking change giữa các version. Hãy tự validate output ở boundary; schema là contract bạn cam kết với consumer và renderer, không phải một lớp chặn lúc chạy.
Hai reserved key tùy chọn cho phép một kết quả phục vụ hai đối tượng. Đặt kết luận gọn cho model và payload đầy đủ cho renderer trong cùng một response, rồi dùng _sota.modelOutput để đưa cho model một bản chiếu hoàn toàn khác, hoặc _sota.modelProjection.omitKeys để loại bỏ các key chỉ dành cho renderer khỏi phần model đọc. Bản chiếu model-visible bị cắt ở khoảng 32.000 ký tự, nên hãy giữ nó ở mức kết luận, id, số đếm và citation thay vì tài liệu thô.