SDK v2 Phase 1: app-registered Kairo tools, end to end
Radin committed
- Author
- Radin · radin@coline.appAug 10, 2026 at 17:27
- Committer
- Radin · radin@coline.appAug 10, 2026 at 17:27
- Parents
- d99adcc76dc7
SDK v2 Phase 1: app-registered Kairo tools, end to end
Apps now contribute real tools to Kairo — schema + execute + approvals +
rendered result cards — via both execution paths from plan §10.
SDK (@colineapp/sdk/v2):
- Chat-card tree subset (tree/chat-card.ts): node allowlist, 120-node /
depth-6 / 20-row caps; validateChatCardTree + schema (open question #4
resolved).
- tool.invoke protocol payloads (server/tool-invoke.ts): capability
endpoint + per-invocation bearer token travel in the envelope; one wire
contract for hosted and external execution.
- HTTP capability transport (capabilities/http-client.ts): coline.* over
POST { operation, args }; client-context capabilities reject.
- createColineToolHandler (server/app-server.ts): external app backends
mount one handler — signature verify, input parse, execute with
capability-backed context, card validation.
Platform (apps/web):
- v2 registration: versions route accepts protocol-2 payloads
(registry-v2.ts); app_versions gains logic_bundle_js, api_base_url now
nullable (migration 0224 applied to coline-dev). Install grants are
protocol-agnostic (v1 or v2 permission vocab, subset-validated).
- Invocation tokens (lib/apps/invocation-tokens.ts): HMAC-bound
workspace/install/user/tool/effect claims, 5-min TTL.
- Capability endpoint POST /api/v1/apps/capability: token auth → unified
guard with effect ceiling → capability-ops.ts (workspace, members,
files CRUD + documents, search.index, notifications) with per-user
drive/file ACL enforcement.
- App tool loader (lib/kairo/app-tools.ts): active installs with granted
ai.tools materialize as AI SDK tools (jsonSchema inputs,
app_{key}_{tool} names, 40-tool cap), dispatched hosted (realtime
LOADER) or external (signed POST {baseUrl}/coline/tools) per the
manifest's hosting default/overrides. Merged into createKairoAgent
after agent-group filtering.
- Approvals: agent_tool_approval_effect enum extended with
app_write/app_destructive/app_external; shouldGateAppToolEffect (read
auto-runs, write follows session permission mode, destructive/external
always gate) rides the existing durable rows, stream event, decide
route, and approval bar unchanged.
Realtime (apps/realtime):
- POST /apps/tools/execute: internal-secret guarded; loads the app's
logic bundle in a Dynamic Worker with a bootstrap that resolves the
tool from the defineApp() export and proxies coline.* calls to the
capability endpoint. Network is always allowlist-gated (capability
host + manifest hosts); no unrestricted outbound mode.
Chat UI:
- App tool invocations render in an app-attributed card frame with a
client renderer for the chat-card subset; href actions are live,
custom actions disabled in transcripts. Deviation from plan §10.4
noted in the doc: the first-party tool-card switch was not bulk
migrated; app tools branch to their own renderer, and first-party
migration folds into Phase 2 UI consolidation.
Verified: sdk 75 tests green; web typecheck clean except the 4
pre-existing browser errors also on main; lib/apps + agent + versions
route tests 44 passing (new: invocation tokens, app approval policy);
realtime typecheck clean; kairo full-dir flakes reproduced identically
on main (pass in isolation); eslint clean on touched files.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>7 files changed+767−0