核心概念
Aitroop 應用的技術結構參考:每一個欄位、每一種類型、每一個選項。可加入書籤作為查閱手冊。
應用定義
一個應用是持久化在 app_def 中的 JSON 文件。你不需要自己撰寫 JSON,這由 agent 完成,但了解它包含什麼會讓其他一切變得清晰。頂層結構如下:
"id": string, // 自動產生,"app_..."
"name": string, // "公司簡報"
"description": string, // 一句話摘要
"icon": string, // emoji,例如 "🏢"
"tags": string[], // ["research", "b2b"]
"status": "draft" | "published" | "archived",
"version": number, // 單調遞增;每次成功儲存時遞增
"input_schema": AppInput[], // 表單
"stages": AppStage[], // 要做什麼,按順序
"artifact_schema": AppArtifactDef[], // 要產出什麼
"resources": { skills: string[], connects: string[] },
"examples": AppExample[] // 可選的預填範例
}
簡寫形式的公式:
AppInput:表單欄位
input_schema 中的每一項都是使用者填寫的一個表單欄位。完整類型如下:
"id": string, // snake_case,例如 "company_name"
"label": string, // 顯示在欄位上方
"type": AppInputType, // 見下方表格
"required": boolean, // 預設 false;為空時阻止執行
"placeholder": string, // 可選提示,顯示在欄位內
"default": unknown, // 可選的預填值
"dynamic_default":string, // "{{today}}" 等 —— 於執行時解析
"description": string, // 顯示在下方的說明文字
"options": { label, value }[], // select/multiselect/radio 必填
"show_if": AppInputConditionalRule, // 條件顯示
"min" | "max" | "step": number // 用於 number/slider
}
11 種輸入類型
伺服器會根據固定列舉驗證 type;提交未知類型會回傳 400。完整清單:
| 類型 | UI | 使用情境 | 額外欄位 |
|---|---|---|---|
text | 單行文字框 | 短識別字,名稱、URL、ID。 | , |
textarea | 多行文字框 | 長指令、描述、待處理的內容。 | , |
number | 數字輸入 | 計數、閾值、價格。 | min、max、step |
slider | 數字滑桿 | 有界範圍,注重感覺而非精確度。 | min、max、step |
select | 單選下拉 | 3-10 個固定選項,僅允許選一項。 | options(必填) |
multiselect | 多選下拉 | 3-10 個固定選項,允許多選。 | options(必填) |
radio | 單選按鈕群組 | 2-4 個選項,需要一次性全部呈現。 | options(必填) |
boolean | 切換 / 核取方塊 | 是 / 否旗標、選用功能。 | , |
date | 日期選擇器 | "截止日期"、"錨定日期"。 | , |
daterange | 兩個日期選擇器 | 區間報表,"從 X 到 Y"。 | , |
file | 檔案上傳按鈕 | 使用者每次執行都上傳新檔案(CSV、PDF、圖片)。 | , |
動態預設值
dynamic_default 是一個固定列舉,不是範本語言。選用其中之一會在執行時填入欄位,而不需要靜態預設值。適合排程任務中需要可滑動錨點的情境。
| 取值 | 解析為 |
|---|---|
today | 工作區時區下的今天。 |
yesterday | 今天的前一天。 |
last7days | 以今天為終點的 7 天視窗(搭配 daterange 使用)。 |
last30days | 以今天為終點的 30 天視窗。 |
thisMonth | 本月 1 日至今天。 |
lastMonth | 上月 1 日至上月最後一天。 |
範例:一個 3 欄位的表單
{ "id": "company_name", "label": "Company name",
"type": "text", "required": true,
"placeholder": "Acme Corp" },
{ "id": "tone", "label": "Tone",
"type": "select", "default": "executive",
"options": [
{ "label": "Executive", "value": "executive" },
{ "label": "Engineering", "value": "eng" },
{ "label": "Sales", "value": "sales" }
] },
{ "id": "include_competitors", "label": "Include competitors?",
"type": "boolean", "default": true }
]
required。對於與時間相關的輸入,使用 dynamic_default({{today}}、{{last_week_start}}),這樣排程執行根本不需要任何輸入。AppStage:實際執行的內容
stages 中的每一項都是工作流程中的一步。各階段按順序執行;每個階段都可以讀取先前階段產生的產物。
"id": string, // snake_case,例如 "research"
"name": string, // 顯示名稱
"stage_type": "agent" | "script" | "human", // 預設 "agent"
"goal": string, // 含 {{refs}} 的指令
"system_prompt": string, // 可選的附加上下文
"model": string, // 預設 "claude-sonnet-4-6"
"timeout_ms": number, // 預設 180000(3 分鐘)
"skills": string[], // 階段級技能清單(覆蓋應用級)
"connects": string[], // 階段級連接清單
"artifact_defs": AppArtifactDef[],// 此階段產生的產物
// 當 stage_type == "script" 時:
"script_lang": "python" | "node",
"script_code": string,
// 當 stage_type == "human" 時:
"human_message": string // 展示給審批者的內容
}
比較三種階段類型
agent 預設 | script | human | |
|---|---|---|---|
| 執行什麼 | Claude,具備完整推理與工具調用 | Python 或 Node 程式碼,無 LLM | 等待真人 |
| 適用情境 | 研究、起草、摘要,任何模糊任務 | 精確轉換,過濾 CSV、去重、格式化日期 | 審批關卡、"挑出最好的 N 個" |
| 延遲 | 20 秒 - 10 分鐘 | 通常 < 1 秒 | 取決於真人耗時 |
| 成本來源 | LLM token + 沙盒時長 | 僅沙盒時長 | 零運算成本 |
| 確定性? | 否(LLM 的隨機性) | 是,同樣輸入,同樣輸出 | 否(人的變異性) |
撰寫 goal 欄位
goal 就是 agent 的指令。在階段執行之前,執行器會用正規表示式 /{{([^}]+)}}/g 走訪 goal,並將每個 {{key}} 替換為 execution.input[key]。未匹配的引用會原樣保留,並不會報錯,但也不會被替換,所以請仔細拼寫輸入的 id。
| 引用 | 解析為 |
|---|---|
{{company_name}} | 使用者在 company_name 輸入欄位填入的值。 |
{{include_competitors}} | 布林值的字串形式("true" / "false")。 |
{{date_range}} | 一個 daterange 輸入在字串化時會呈現為其 JSON 形式。 |
goal 範本不支援的內容。這裡沒有 {{today}}、沒有 {{user.email}}、沒有 {{#if x}}...{{/if}},並且,關鍵是,沒有 {{ stages.X.Y }}。範本展開器只看表單值。對於時間相關的錨點,請改用輸入欄位上的 dynamic_default。對於上一階段的輸出,請見下面的多階段應用,執行器會自動把它們注入到 system prompt。一個真實範例:
Research {{company_name}} ({{company_url}}) and write a comprehensive
competitive analysis covering:
1. Business model and revenue streams
2. Key products/services
3. Target customers and ICP
4. Recent news and strategic moves
5. Strengths, weaknesses, opportunities, threats
If {{include_competitors}} is true, also include
the top 3–5 direct competitors with a one-paragraph profile each.
Produce a Markdown report titled "{{company_name}} Competitive
Analysis" under a ## Competitive Analysis heading.一個好的 goal 應該是:
- 具體:指明要用哪些輸入以及如何使用它們。
- 關注輸出:指明產物 ID 與格式。
- 可執行:使用祈使動詞("研究"、"撰寫"、"分析")。
- 結構化:一個帶編號小節的 10 行 goal 幾乎總是優於 2 行的版本。
AppArtifactDef:每個階段的產出
{
"id": string, // snake_case,例如 "final_report"
"title": string, // 顯示名稱
"format": ArtifactFormat, // 見下方表格
"language": string, // 用於 format="code",例如 "python"
"description": string
}支援七種格式:
format適用 預覽 markdown報告、簡報、草稿 以 GFM 渲染,支援表格、程式碼圍欄、Mermaid。 code原始碼,單檔案或目錄樹 語法高亮,多檔案輸出時附帶檔案樹。 html渲染頁面、儀表板、簡報 沙盒化的 iframe;允許腳本但被隔離。 json用於下游系統的結構化資料 可折疊樹,附類型資訊。 csv表格資料,線索、交易 可排序、可篩選的試算表檢視。 image產生的圖片、圖表、示意圖 支援縮放與平移。PNG / JPEG / SVG / WebP。 file其他任何內容,PDF、ZIP、音訊、影片 按類型自適應:PDF 內嵌預覽、音訊播放器、ZIP 檔案清單。
所有產物都存放在 S3(如果你是自架則放在 R2)中,位置為 app_artifact.s3_key,並記錄 MIME 類型與位元組大小。它們會在應用的整個生命週期中保留;刪除的應用封存在 30 天內仍可復原。
Resources:應用所需的技能與連接
"resources": {
"skills": ["web-search", "pdf-extract"],
"connects": [
{ "type": "specific", "id": "hubspot", "is_required": true },
{ "type": "category", "id": "email", "is_required": true,
"label": "Any inbox we can send from" }
]
}技能是 agent 可以調用的能力模組(網頁搜尋、PDF 擷取、圖像生成),詳見 技能。連接是應用所需的 OAuth 橋樑。Aitroop 以兩層分類來組織連接:
type: "specific":以 connect_definition.id 鎖定單一提供方(例如 github、hubspot、gmail)。僅適配某一種整合時使用。type: "category":接受 connect_category 內的任一提供方(例如 email、storage、crm)。只要使用者授權了該類別下的至少一個提供方,應用就視為滿足。當應用與具體提供方無關時("任意信箱"、"任意 CRM")使用。
舊的形式 "connects": ["hubspot", "github"] 仍然可用,應用執行時每個字串都會被視為 { type: "specific", id: «string», is_required: true }。應用建構器在新建應用時會寫入更豐富的形式。
資源可以在應用級宣告(如上),也可以按階段宣告(在 stage.skills / stage.connects 下)。按階段範圍化是讓多階段應用更安全的方式,給階段 1 只配置 web-search,給階段 2 只配置 CRM 連接,以此類推。請見 連接 了解完整的提供方目錄與滿足模型。
執行記錄:應用真正執行的時刻
一次執行記錄是一次走完應用所有階段的過程。它就是那個帶有狀態、階段日誌、耗時和最終產物集合的實體。
{
"id": "exec_...",
"app_id": "app_...",
"status": "pending" | "running" | "completed" | "failed" | "cancelled",
"input": { ...form values },
"is_test": boolean,
"duration_ms": number,
"start_from_stage_index": number, // 用於恢復
"prior_execution_id": string | null // 恢復時使用
}執行中的每個階段都會有自己的 app_stage_log 列,包含狀態、耗時、session ID(可據此開啟為對話)、展開後的 goal 以及任何錯誤。
兩個層級的狀態列舉並不一致:
欄位 可能取值 app_execution.statuspending · running · completed · failed · cancelledapp_stage_log.statuspending · running · waiting · completed · failed · skippedapp_human_gate.statuspending · approved · rejected
當一個 human 階段在等待時,階段日誌會進入 waiting;父執行仍維持 running。當執行帶 start_from_stage_index > 0 恢復時,它們也會進入 skipped:較早的階段不會重新執行。請見 執行記錄 了解完整生命週期、除錯流程與 SSE 串流。
沙盒:agent 實際工作的地方
每一次對話和每一個應用階段都執行在一個沙盒中:一個隔離的執行環境,擁有自己的檔案系統、自己的行程和對外網路。agent 可以 pip install、執行 shell 指令、寫入檔案、抓取 URL,執行結束時,沙盒會被銷毀。
統一在 ISandbox 介面下提供三種後端,再由一個路由器在它們之間挑選:
host:直接在 Aitroop 伺服器行程中執行。僅用於自架開發環境;DATABASE_URL、JWT_SECRET、E2B_API_KEY 與 S3 憑證等敏感變數會從子行程環境中剝離。e2b:來自 E2B 的 Firecracker 微型虛擬機。Aitroop 託管版的預設選項。daytona:來自 Daytona 的託管開發容器。適合重負載 / 長時間階段。router:按使用者分派到上述三者之一的選擇器(用於把特權使用者路由到 host)。
無論使用哪個提供方,每個沙盒都暴露相同的目錄佈局,根目錄是沙盒使用者的 home 目錄:
~/.aitroop/ ← Aitroop 工作目錄
~/.aitroop/run-agent-config.json ← 每次執行的設定
~/.aitroop/run-agent ← 二進位(遠端模式下上傳)
~/.aitroop/skills/{name}/{version}/ ← 不可變的技能快取(與 S3 鏡像)
~/.claude/skills/{name} ← 符號連結 → 快取(永遠啟用的核心技能)
~/.aitroop/app_skills/{appId}/.claude/skills/ ← --add-dir 目標(應用專屬技能)
{projectDir} ← agent 讀寫檔案的地方同一次執行中的所有階段共享同一個沙盒,所以階段 2 可以讀取階段 1 寫入的內容。不同的執行使用不同的沙盒,不會跨執行洩漏。實務上你會遇到的常數:SANDBOX_IDLE_TIMEOUT_MS = 5 分鐘、SANDBOX_KEEPALIVE_INTERVAL_MS = 30 秒,以及上限 AGENT_RUN_TIMEOUT_MS = 7 天。請見 沙盒 了解完整的運行模型。
多階段應用
當一個工作流程天然有彼此銜接的步驟時,就定義多個階段。各階段按順序執行。每個階段在兩個地方都能看到前序階段的產物,但都不透過 goal 範本:
- 共享的沙盒檔案系統。一次執行中的所有階段都在同一個沙盒中執行(沙盒)。階段 1 寫入的檔案,階段 2 仍然可以讀到。
- system prompt 中自動注入的
## Previous Stage Outputs 區塊。在階段 N 執行之前,執行器會載入階段 0..N-1 產生的所有產物,把每個產物渲染為 ### {{title}}\n{{content}},並將這一段拼接到 system prompt 之前。agent 把它們當作一般上下文閱讀,不需要在 goal 中手動引用。
App: Cold Outreach Pipeline
stages: [
{ id: "find", stage_type: "agent",
goal: "Find companies matching {{icp}}...",
artifact_defs: [{ id: "leads", title: "Leads", format: "csv" }] },
{ id: "enrich", stage_type: "agent",
goal: "Read the Leads CSV from the previous stage and add
a verified email and recent news per row...",
artifact_defs: [{ id: "enriched", title: "Enriched Leads", format: "csv" }] },
{ id: "review", stage_type: "human",
human_message: "Review the enriched leads. Remove rows
you don't want to contact." },
{ id: "draft", stage_type: "agent",
goal: "Draft personalized outreach for the approved leads...",
artifact_defs: [{ id: "drafts", title: "Drafts", format: "markdown" }] }
]注意兩個 agent 階段之間夾著一個 human 階段,這就是人在迴圈(human-in-the-loop)模式。執行在此處暫停,平台會在 app_human_gate 中建立一列,狀態為 pending,階段日誌切換為 waiting。只有當 gate 被設為 approved 時下一個階段才會執行(設為 rejected 時則維持暫停)。
會話與訊息佇列
所有與 agent 的對話,無論是自由聊天、應用階段,還是排程任務的一次觸發,都發生在一個會話中。一個會話是一個穩定的容器,擁有自己的 Claude 對話 ID、自己的有序訊息日誌,以及自己的狀態追蹤佇列。在 app_session.session_type 中持久化有三種形態:
session_type 由誰建立 生命週期 出現位置 chat使用者,"+ 新對話"。 除非封存/刪除否則永久保留。 側邊欄、搜尋、歷史。 app_stage應用執行器在某個 agent 階段開始時建立。 綁定到父執行。永久存放作為稽核,可透過在對話中除錯瀏覽。 執行詳情頁,每個階段日誌都帶有 session_id。 scheduled某個 send_message 排程任務的第一次觸發。 之後該任務的每次觸發都重複使用,設計上就保持連續性。 從任務列連結而來的單個 "[Scheduled] {name}" 會話。
在每個會話中,每一次使用者回合都是 app_message 中的一列。這些列不是「發完就忘」,它們要走一個小型狀態機,因為 agent worker 池可能是多實例的,同一個會話必須串列化它的分派:
pending → dispatching → sent
dispatching → failed (5 次以上嘗試後)app_message 上重要的欄位:
position:每個會話內的整數,單調遞增。決定相同優先級列之間的順序。DAO 在插入列時原子地分配此值。priority:64 位元排序鍵。優先級越高越先分派;預設為實際時鐘時間,所以兩條沒有明確優先級的訊息按到達順序執行。attempts:每次嘗試分派時遞增。5 次失敗後,列進入 failed,使用者可見訊息顯示錯誤。dispatched_at:worker 認領該列時設定;與 15 分鐘過期閾值搭配驅動恢復輪詢。mode:自由形式的標籤,表示這條訊息是什麼類型(用於 UI 中路由格式化)。last_error:最近一次失敗原因,跨重試保留。
worker 透過 SELECT … FOR UPDATE SKIP LOCKED 並按 priority DESC, position ASC 排序來認領工作,因此兩個實例永遠不會搶到同一列。一個部分唯一索引,在 session_id 上的 uq_app_message_inflight,WHERE 條件為 status = 'dispatching' AND role = 'user':在資料庫層強制「每個會話最多一條在途使用者訊息」。如果某列在 dispatching 狀態停留超過 900 秒(worker 崩潰、節點遺失),恢復輪詢器會將其重設為 pending,以便另一個 worker 接手。
分派是如何流轉的
機制有兩層:行程內的 QueueController 與 Postgres 的 NOTIFY 頻道 queue_dispatch。當一條新訊息入佇列時,寫入端實例會在本地廣播 queue_updated 事件,並發出 pg_notify('queue_dispatch', '{sessionId}|{originInstanceId}')。監聽同一頻道的其他實例會忽略自己的回聲,並接手工作,因此分派在叢集範圍內是事件驅動的,再輔以 60 秒的輪詢作為漏掉通知時的後備。
shared-session 旗標
預設情況下,每個應用階段都會得到自己的會話。當 RunAppRequest.shared_session 為 true 時,執行器會為整次執行建立一個會話,並在每個 agent 階段重複使用其 session_id。可見差異:在執行上點擊在對話中除錯會開啟一個包含每個階段訊息的單一對話,而不是每個階段一個對話。在你希望以敘事方式閱讀整次執行時有用;其他情境很少需要。
ask_user 模式
agent 偶爾需要在執行中向使用者提問(一個歧義、一段缺失的輸入)。發出一個 ask_user 工具呼叫會暫停 agent 當前回合,將問題在對話 UI 中呈現,並等待回覆。平台會在下一次 tick 時把回覆作為工具結果回傳,所以從模型視角看,agent 的「我問過了,這是答案」只是一次普通的對話步驟。這與 human 階段(在執行級別對整個流水線設置關卡)不同;ask_user 完全是會話內部行為。
agent runner 協定
每個 agent 階段和每次對話回合最終都透過一個名為 run-agent 的 Go 二進位執行。伺服器把一個 JSON 設定交給該二進位,並按行讀取它的 stdout。每一行就是一個事件,這是一個穩定的 JSONL 協定,你會在日誌、SSE 負載以及對話 UI 的推理軌跡中看到它的引用。
轉發的事件
這些事件會在到達時被推送到 UI。線上欄位名稱使用 camelCase 以方便 JS;runner 的 snake_case 會自動轉換(tool_id → toolId、is_error → isError 等)。
事件 含義 text_deltaagent 正在寫出可見文字。按 token 串流輸出。 thinking_delta隱藏的推理內容。僅在軌跡面板中顯示。 tool_startagent 正在呼叫一個工具。攜帶 toolId、toolName 和參數。 tool_result工具返回。攜帶 toolId、輸出與 isError。 subtask_start / subtask_progress / subtask_doneagent 衍生了一個嵌套任務(Task 工具 / 子 agent)。 ask_useragent 在繼續之前需要一個問題被回答,見上文。 context_usage週期性的 token 用量遙測(輸入/輸出/快取命中)。 session_info攜帶本次回合背後的 Claude 對話 ID;用於恢復。 system平台級訊息(例如權限提示、重試)。 erroragent 端錯誤;本回合失敗。 done回合乾淨地完成。
內部事件(永不轉發)
三個以 __runner_*__ 命名的事件只被伺服器消費,它們是簿記,不是使用者可見的狀態:
事件 用途 __runner_heartbeat__保活 ping。即使沒有 token 在串流,也告訴監督者子行程仍存活。 __runner_done__子行程乾淨退出。讓監督者把正常結束和崩潰區分開。 __runner_error__子行程崩潰;攜帶捕獲到的 stderr。觸發 session-expired / sandbox-not-found 分類(見下文)。
錯誤分類
並非每一種 runner 失敗都一樣。伺服器會把捕獲到的錯誤訊息歸類到以下五個桶之一,桶決定了恢復策略:
類別 觸發條件 恢復 session_expired背後的 Claude 對話被退役或輪換。 開啟新的 Claude 對話;保留 Aitroop 會話列。 sandbox_not_found沙盒容器已死或被回收。 驅逐快取的沙盒並新建一個;本回合重試一次。 network傳輸錯誤,ECONNRESET、ETIMEDOUT。 退避後重試。 connectiongRPC / MCP 協定級錯誤。 把錯誤暴露出來;由使用者明確重試。 unknown其他任何情況。 以原始錯誤把回合標記為失敗。
執行設定裡有什麼
伺服器為每個回合建立一份 RunAgentConfig,並在呼叫二進位之前寫入沙盒中的 ~/.aitroop/run-agent-config.json。要點欄位:
prompt:實際的使用者訊息(或階段展開後的 goal)。options.model:Claude 模型 ID;若階段未鎖定則預設為 claude-sonnet-4-6。options.resume:存在時表示恢復一個既有的 Claude 對話。伺服器從會話的 agent_session_id 讀取。options.allowedTools:runner 向模型暴露的精選工具集(通常 8 個:Read、Edit、Bash、Glob、Grep、Write、Task,以及 Aitroop MCP 集合)。options.permissionMode:固定為 'bypassPermissions';平台在沙盒邊界強制權限,而不是互動式詢問。options.mcpServers:Aitroop 自研的 MCP 伺服器,加上應用 / 階段請求的其他 MCP。options.env:process.env 中所有以 SANDBOX_ENV_ 開頭的變數都會被轉發並去掉前綴,再加上 AT_USER_TOKEN(使用者的 JWT)被注入,以便沙盒內的伺服器端呼叫能通過認證。options.oauthToken / 代理模式:要麼是 Anthropic OAuth token,要麼在設定了代理時使用一個指向代理的 ANTHROPIC_BASE_URL,並以使用者的 JWT 作為 bearer。平台在每次呼叫時快照一次,保證一次回合內的所有重試都使用相同憑證。
應用是如何被建立出來的
你不需要手寫應用 JSON。這由 agent 完成。流程:
- 你在對話中告訴 agent:「建立一個應用,讓它……」
- agent 啟用
aitroop-app-create 技能(應用建構器)。 - 必要時應用建構器會問 1-5 個釐清問題。
- 它設計完整的 AppDef(輸入、階段、產物、資源)。
- 它驗證設計,每個 ID 唯一、每個
{{ref}} 可解析、goal 足夠具體。 - 它呼叫
POST /api/apps 來儲存。 - 它回報應用 ID 並提議進一步打磨。
要編輯既有的應用,你可以說類似 「更新我的『公司簡報』應用,加入招聘資料」,應用建構器會拉取目前版本、修改它,然後呼叫 PUT /api/apps/{id}。
常見錯誤
- goal 過於模糊:「做點研究」太過寬泛。請指明資訊來源、深度、輸出格式。
- 缺少產物:一個沒有
artifact_defs 的應用不會產生任何可見輸出。 - 必填項太多:使用者會放棄需要長表單的應用。能預設就預設。
- 逾時設得太短:重度研究階段需要 5-10 分鐘。把
timeout_ms 調到 600000。 - 輸入類型選錯:長文字用
textarea,短識別字用 text,3-6 個固定選項用 select。 - 過度拆分:把本是一個想法的任務拆成 4 個階段。只有當工作天然有可分離的步驟時才使用多階段。
速查詞表
術語 含義 應用(App) 一份儲存好的工作流程 JSON 文件,包含表單、階段與產物。 AppInput 一個表單欄位。支援 11 種類型,見輸入類型表。 階段(Stage) 工作流程中的一步。類型:agent、script、human。 goal 階段內 agent 的指令字串。以 {{id}} 引用輸入。 產物(Artifact) 階段產出的交付物。帶類型(markdown、csv 等)。 技能(Skill) agent 可以調用的能力(web-search、pdf-extract 等)。 連接(Connect) 到外部服務的 OAuth 整合(google、github、hubspot)。 Resources 應用宣告所需的技能與連接。 執行記錄(Execution) 一次應用的執行。帶有狀態、階段日誌與產物。 階段日誌(Stage log) 一次執行中按階段的紀錄,狀態、耗時、錯誤、會話。 Human gate 等待人工通過 / 拒絕 / 編輯的暫停執行。 沙盒(Sandbox) 每次對話或應用執行所在的隔離執行環境。三種提供方:host / e2b / daytona。 會話(Session) 承載訊息序列的對話容器。類型:chat / app_stage / scheduled。 訊息(Message) app_message 中的一列。位於分派佇列中,具有狀態機與優先級。Runner 實際驅動一次 Claude 回合的 run-agent 二進位。向伺服器回傳 JSONL 事件。 工作區(Workspace) 帳戶容器,包含應用、連接與執行歷史。 Org 位於使用者之上的團隊層。共享應用、共享帳單、成員角色。