給 Custom App 的預建能力:SDK 全景
這是本手冊最重要的一章。
當您在 AI GO 上開發應用程式時,有一大類工作不需要做——資料庫連線、租戶隔離、權限檢查、ERP 業務邏輯、簽核流程、向量檢索、外部 API 的安全出口、金鑰保管、加解密。平台把這些預先建好,以 SDK 的形式交到您手上。
SDK 分兩側:伺服器端的 ctx 物件(在 Action 中使用)與前端的六支 TypeScript SDK。
伺服器端:ctx 物件
每個 Action 都是一個接收 ctx 的函式:
def execute(ctx):
...
ctx 上掛著平台的全部能力。
執行脈絡屬性
| 屬性 | 內容 |
|---|---|
ctx.params | 呼叫端傳入的參數 |
ctx.app_id | 執行中的應用程式識別碼 |
ctx.tenant_id | 所屬組織識別碼 |
ctx.action_name | 當前執行的 Action 名稱 |
ctx.env | 執行環境(online / dev) |
ctx.user_id | 觸發者的使用者識別碼 |
ctx.user_roles | 觸發者的角色名稱清單(唯讀快照) |
ctx.user_permissions | 觸發者的權限標籤清單(唯讀快照) |
判斷授權請用 user_permissions 而不是 user_roles——角色名稱可以被改名,權限標籤是穩定的識別。
ctx.db — 資料存取
存取兩類資料:ERP 內建表與自建表。
| 方法 | 用途 |
|---|---|
query(table, filters, order_by, limit, offset) | 查詢 ERP 表 |
insert(table, data) | 新增 ERP 表記錄 |
update(table, row_id, data) | 更新 ERP 表記錄 |
remove(table, row_id) | 刪除 ERP 表記錄 |
list_tables() | 列出組織的自建表 |
query_table(name, filters, ...) | 查詢自建表 |
insert_row(name, data) | 新增自建表記錄 |
update_row(name, row_id, data) | 更新自建表記錄 |
delete_row(name, row_id) | 刪除自建表記錄 |
典型場景:任何需要讀寫企業資料的地方。查詢支援完整的過濾、排序、分頁——不是只有「取全部」。
orders = ctx.db.query('sale_orders',
filters=[
{'column': 'state', 'op': 'eq', 'value': 'sale'},
{'column': 'amount_total', 'op': 'gte', 'value': 10000},
],
order_by=[{'column': 'created_at', 'direction': 'desc'}],
limit=50)
授權:讀取需 db.read / data_table.read,寫入需 db.write / data_table.write。ERP 表另外受引用宣告約束——沒宣告的表與欄位存取不到。
ctx.erp — 觸發業務引擎
這是最容易被低估的模組。它不是「寫一筆資料」,而是觸發平台預建的完整業務流程。
| 方法 | 觸發什麼 |
|---|---|
confirm_sale_order(id) | 確認銷售訂單(連動出貨與開票準備) |
confirm_purchase_order(id) | 確認採購訂單 |
create_invoice(order_id) | 從銷售訂單開立銷項發票。order_id 可傳清單——多張訂單合併開一張發票 |
create_bill(order_id) | 從採購訂單建立進項帳單。同樣支援清單合併 |
validate_picking(id) | 驗證揀貨單(連動庫存移動與存貨計價) |
post_move(id) | 過帳會計傳票 |
confirm_payment(id) | 確認收付款(連動自動沖銷) |
reconcile_payment(id) | 補跑已過帳付款的沖銷引擎 |
confirm_payroll_run(id) | 確認薪資結算批次(連動應付薪資傳票) |
cancel_payroll_run(id) | 撤銷薪資批次(自動產生沖銷分錄) |
典型場景:您做了一個「業務快速結單」的應用。使用者按下按鈕後,訂單確認、發票開立、庫存扣減、會計傳票——全部由一次 ctx.erp 呼叫連鎖完成,您不需要知道會計科目怎麼帶、稅率怎麼算。
合併開票值得特別說明:傳入訂單 id 清單時,會把清單內所有訂單的明細彙總進同一張發票(要求同客戶、同組織)。這解掉了「月結客戶要合併開票」這個常見需求。
授權:各方法對應獨立的 scope(如 erp.sale_order.confirm),全部屬於高風險等級。
ctx.approval — 簽核
| 方法 | 用途 |
|---|---|
list_pending() | 取得觸發者本人的待簽核清單 |
get_record_status(res_model, res_id) | 查某筆記錄的簽核狀態與各關卡明細 |
approve(request_line_id, comment) | 以觸發者身分核准一層 |
reject(request_line_id, comment) | 以觸發者身分駁回 |
cancel(request_id, reason) | 取消簽核申請(限申請人本人、限進行中) |
典型場景:在您的部門工具裡做一個「我的待辦」面板,讓主管不必登入主控台就能完成簽核。
重要語意:這些方法綁使用者身分。approve 會驗證觸發者是否為該關卡的合格審核人,不是就拒絕。最後一關通過時會自動執行被攔截的原操作。
授權:讀取需 approval.read(低風險),決定需 approval.decide(高風險)。
ctx.knowledge — 企業知識檢索
| 方法 | 用途 |
|---|---|
search(query, top_k, score_threshold) | 向量檢索,回傳片段與相關度分數 |
get_content(file_id) | 取單一知識檔案的完整解析文字 |
典型場景:做一個內部問答助理。檢索企業規章與產品文件取得脈絡,再用您自己的模型金鑰產生回答。
設計要點:這是純檢索、不生成——不呼叫任何語言模型,回傳原文片段。生成留給您自己的邏輯與金鑰,成本與模型選擇由您掌控。檢索結果自動套用檔案級存取政策(見第 6 章)。
授權:knowledge.read,高風險等級。
ctx.http — 呼叫外部 API
| 方法 | 用途 |
|---|---|
call(service, path, method, body, headers, params) | 透過已授權的外部服務呼叫 API |
fetch(url, ...) | 抓取任意公開網址(仍受安全限制) |
典型場景:串接物流查詢、簡訊網關、發票加值中心、您公司既有的內部系統。
兩個容易踩到的地方:
- 第三個位置參數是
method(字串),不是 body。要送 body 請用具名參數。 call不拋例外,回傳{status, headers, data}——請務必檢查status。失敗時data會帶error_type、error與fix(一句可直接轉述給使用者的修復指引)。
resp = ctx.http.call('logistics', '/track', method='POST',
body={'no': ctx.params['tracking_no']})
if resp['status'] != 200:
return ctx.response.json({'error': resp['data'].get('fix')})
授權:http,高風險等級,且外部網域須經白名單授權。
ctx.messaging — 通訊中心
| 方法 | 用途 |
|---|---|
list_channels() / add_channel() / update_channel() / remove_channel() | 管理通訊渠道 |
inject_inbound() | 注入外部進來的訊息 |
save_ai_outbound() | 儲存 AI 產生的回覆 |
get_ai_config() | 讀取 AI 回覆設定 |
典型場景:在您的應用裡做一個客服對話介面,把外部渠道(如通訊軟體)的訊息接進來,與 CRM 客戶資料綁定,讓營運同仁在同一個畫面內回覆。
授權:讀取需 messaging.read(低風險),寫入需 messaging.write,渠道管理需 messaging.channel(均為高風險)。
ctx.secrets — 金鑰保管
| 方法 | 用途 |
|---|---|
get(key_name) | 取得金鑰值 |
list_keys() | 列出可用的金鑰名稱 |
典型場景:您的應用需要呼叫第三方服務或自己的模型 API。金鑰存放在 App Secrets 中,不會出現在原始碼裡,也不會傳到前端。
授權:secret.read,高風險等級。
ctx.crypto — 加解密與簽章
| 方法 | 用途 |
|---|---|
hash(algorithm, data) | 雜湊(sha256 等) |
hmac_sign(key_name, data) | HMAC 簽章(金鑰名而非金鑰值) |
base64_encode(data) / base64_decode(data) | Base64 編解碼 |
aes_encrypt(key_name, plaintext) | AES-256 加密 |
aes_decrypt(key_name, ciphertext, iv) | AES-256 解密 |
典型場景:驗證 Webhook 來源的簽章、產生對外 API 需要的簽名、加密儲存敏感欄位。
注意 hmac_sign 與 AES 方法接受的是金鑰名稱而不是金鑰值——實際的金鑰值永遠不經過您的程式碼。
授權:crypto,低風險等級。
ctx.mcp — 外部工具協定
| 方法 | 用途 |
|---|---|
execute(task, wait=True) | 同步執行 MCP 任務 |
trigger(task) | 非同步觸發,回傳任務識別碼 |
get_status(task_id) | 查詢非同步任務狀態 |
授權:mcp,高風險等級。
ctx.response 與 ctx.csv — 回應控制
| 方法 | 用途 |
|---|---|
ctx.response.json(data) | 回傳 JSON |
ctx.response.file(content, filename, mime) | 回傳檔案下載 |
ctx.csv.export(rows, columns, filename) | 一行匯出 CSV |
這兩個模組在執行環境本地處理,不需要 scope 授權。
前端 SDK
前端有六支平台提供的 TypeScript SDK,放在 src/ 底下,開箱即用。
src/db.ts — ERP 表存取
在前端直接查詢與寫入已引用的 ERP 表,語意與 ctx.db 對應。適合列表頁、詳情頁這類直接的資料呈現。
src/api.ts — 自建表存取
存取組織的自建表。同樣支援過濾、排序、分頁。
src/action.ts — 呼叫伺服器端 Action
前端呼叫 Action 的官方管道。凡是需要金鑰、需要高權限、或不該讓使用者看到邏輯的操作,都應該放進 Action 再由這裡呼叫。
import { callAction } from './action';
const result = await callAction('confirm_orders', { ids: selectedIds });
src/approval.ts — 簽核(Internal 專屬)
取得待簽核清單、查詢簽核狀態、執行核准與駁回。可以直接組出簽核面板。
src/user.ts — 使用者脈絡(Internal 專屬)
取得當前使用者的角色與權限標籤,用來決定介面上顯示什麼:
import { getUser } from './user';
const user = await getUser();
if (user.permissions.includes('accounting.write')) {
// 顯示過帳按鈕
}
注意:前端的權限判斷是體驗優化,不是安全邊界。真正的授權在伺服器端執行——前端藏起來的按鈕,直接呼叫 API 一樣會被擋。
src/auth.ts — 登入註冊(External 專屬)
External App 的使用者註冊、登入、登出與密碼修改流程。
授權模型一覽
每個 SDK 方法都對應一個 scope(能力群)。應用程式必須宣告需要哪些 scope,由管理員核可後才生效。
| 風險等級 | Scope | 核可方式 |
|---|---|---|
| 低風險 | db.read、data_table.read、messaging.read、approval.read、crypto | 管理員核可 |
| 高風險 | db.write、data_table.write、erp.*、approval.decide、approval.cancel、knowledge.read、messaging.write、messaging.channel、http、mcp、secret.read | 管理員核可 + 擁有者當場密碼再驗證 |
Scope 是能力群的開關;細粒度的邊界另有其他機制——ERP 表看引用宣告、外部服務看網域白名單、金鑰看可用清單。兩層疊加。
每一次 SDK 呼叫都會留下稽核紀錄。詳見第 10 章。