Ito ay isang machine translation ng orihinal na dokumentong Ingles. Sa kaganapan ng anumang salungatan sa pagitan ng pagsasaling ito at ng orihinal na bersyong Ingles, ang bersyong Ingles ang mangingibabaw. Basahin ang orihinal na bersyong Ingles


Public API

Ang Caiioo ay may kasamang REST API na nagbibigay-daan sa iyong kontrolin ang lahat sa pamamagitan ng program: magpatakbo ng mga agent, mamahala ng mga tool, mag-iskedyul ng mga gawain, at iba pa. Ang API ay nakatira sa parehong lokal na server na nagpapatakbo sa desktop app at browser bridge.

Base URL: http://localhost:3847/v1

Authentication: Dalawang paraan upang mag-authenticate, parehong nakadepende sa API toggle sa mga setting:

Para sa mga panlabas na consumer (scripts, integrations, curl): Magtakda ng API access token sa Mga Setting > API Access, pagkatapos ay gamitin ito bilang Bearer token:

curl -H \"Authorization: Bearer YOUR_API_TOKEN\" http://localhost:3847/v1/providers

Para sa lokal na app (awtomatiko): Ang Caiioo desktop app, mga browser extension, at mga mobile app ay awtomatikong nag-a-authenticate sa pamamagitan ng umiiral na relay auth header (x-relay-auth; ang mga HTTP header ay case-insensitive). Walang manu-manong setup na kailangan — ang app ang bahala rito sa likod ng mga eksena. Ang mga relay-auth request ay lumalampas sa Enable Public API toggle dahil pinagkakatiwalaan na ang mga ito; tanging ang mga bearer-token request ang nakadepende sa toggle.

Setup:

  1. Buksan ang Caiioo Mga Setting > API Access
  2. I-toggle ang Enable Public API sa on
  3. Magtakda ng isang API access token (anumang string na pipiliin mo — ituring itong parang password)
  4. Gamitin ang token na iyon sa lahat ng API request

Ang API ay available sa localhost at sa pamamagitan ng private relay. Suriin ang GET /v1/auth/info (walang auth na kailangan) para sa kasalukuyang status at mga tagubilin sa setup.

Mga limitasyon sa rate: bawat /v1/* request ay may rate-limit bawat client IP — 100 GET requests bawat minuto para sa pagbabasa at 30 write requests bawat minuto (POST / PATCH / DELETE) na pinagsama. Ang mga request na lampas sa limitasyon ay makakakuha ng 429. Ang mga webhook delivery (POST /v1/webhooks/:id) ay hindi bearer-authed at hindi sakop ng mga limitasyong ito.

Mga Profile

Ang isang device ay maaaring maglaman ng maraming profile ng user (hal. personal + trabaho). Pinapayagan ng API ang mga panlabas na script na suriin ang mga available na profile at lumipat sa aktibong profile bago gumawa ng ibang trabaho. Ang paggawa, pag-update, at pagbura ng profile ay sadyang hindi inilantad sa public API — ang mga flow na iyon ay para sa onboarding UI ng app.

Ilista ang mga profile:

GET /v1/profiles

Nagbabalik ng { profiles: [...] } na may isang entry bawat hindi naburang profile. Kasama sa bawat entry ang id, name, email, avatarUrl, tier, accessibleModes, license, organization, preferences, onboardingComplete, createdAt, lastAccessedAt. Ang mga field na may token (serviceCredentials, oauthConnections) at sync internals (vectorClock, lastModifiedBy) ay tinanggal. Gamitin ang /v1/connectors para suriin ang mga koneksyon sa OAuth.

Kunin ang aktibong profile:

GET /v1/profiles/active

Nagbabalik ng { profile } para sa profile na kasalukuyang ginagamit ng server na ito. Lahat ng /v1/* resources na sakop ng isang profile (threads, attachments, settings, skills) ay gumagana laban dito.

Lumipat ng aktibong profile:

PUT /v1/profiles/active
Content-Type: application/json

{ "profileId": "user-uuid-mula-sa-listahan" }

Nagbabalik ng { profile } para sa bagong aktibong profile. Nagbabalik ng 404 kung ang ID ay hindi kilalang profile.

Mga Provider at Modelo

Alamin kung aling mga LLM provider ang naka-configure at kung anong mga modelo ang available.

I-list ang mga provider:

GET /v1/providers

Nagbabalik ng bawat sinusuportahang uri ng provider. Sa kasalukuyan: anthropic, openai, google, openrouter, ollama, poe, mlx, perplexity, baseten, cloudflare. Ang bawat entry ay may kasamang type, displayName, icon, requiresApiKey, hasApiKey, at isang capabilities object na may mga flag sa ibaba.

Capability flag Kahulugan
supportsVision Ang provider ay tumatanggap ng mga image input
supportsPdfFile Ang provider ay tumatanggap ng raw PDF file content blocks natively
supportsToolCalling Ang provider ay sumusuporta sa function/tool calling
supportsStreaming Ang provider ay nag-i-stream ng mga token nang paunti-unti
supportsExtendedThinking Ang provider ay naglalantad ng reasoning/thinking budget
supportsPromptCaching Ang provider ay sumusuporta sa mga prompt-cache directive
nativeReasoningBlocks Ang provider ay naglalabas ng thinking bilang native message blocks (kumpara sa text)
requiresThoughtSignature Ang provider ay nangangailangan ng signed thought tokens para i-echo pabalik

Ang mga capability flag ay sumasalamin sa readonly capabilities field ng bawat provider class (tingnan ang src/shared/providers/*-provider.ts) at bini-validate ng isang drift sentinel test — tawagan ang endpoint na ito sa runtime sa halip na i-hardcode ang matrix.

Mga tala para sa mga BYOK provider:

  • Ang perplexity ay naglalantad ng na-curate na listahan ng mga Sonar model (walang pampublikong /models endpoint ang Perplexity).
  • Ang cloudflare (AI Gateway) ay BYOK + multi-vendor; ang listahan ng modelo ay tinutukoy ng iyong gateway configuration at ibinabalik bilang isang empty array ng /v1/providers/cloudflare/models. Gamitin ang iyong sariling gateway catalog.

I-list ang mga modelo para sa isang provider:

GET /v1/providers/openrouter/models

Nagbabalik ng model catalog para sa provider na iyon. Ang bawat modelo ay may kasamang id, displayName, at contextLength kung available. Nagbabalik ng 503 kapag ang provider ay walang API key o hindi maabot ang upstream catalog nito.

Flat catalog sa lahat ng provider:

GET /v1/models

Pinagsasama ang mga modelo mula sa bawat naka-configure na provider sa isang listahan. Ang mga provider na walang API key ay lalaktawan at ililista sa warnings.

Mga Agent

Ang mga agent ang puso ng caiioo. Ang bawat agent ay isang Mode — isang na-configure na personalidad na may sariling system prompt, mga tool, variable, at skills.

Ilista ang lahat ng agent:

GET /v1/agents

Nagbabalik ng mga builtin agent (Shopping, Workplace, General) at anumang custom agent na iyong ginawa. Ang bawat isa ay naka-tag ng source: \"builtin\" o source: \"custom\".

Gumawa ng custom agent:

POST /v1/agents
Content-Type: application/json

{
  \"id\": \"my-research-agent\",
  \"branding\": {
    \"name\": \"Research Agent\",
    \"description\": \"Naghahanap sa web at nagbubuod ng mga natuklasan\"
  },
  \"defaultSettings\": {
    \"systemPrompt\": \"Isa kang research assistant. Palaging magbanggit ng mga pinagmulan.\",
    \"enabledTools\": { \"web_browsing\": true, \"search_tools\": true }
  },
  \"settingLevels\": {}
}

Nagbabalik ng 201 kasama ang ginawang agent. Isang vector clock ang awtomatikong ikinakabit para sa sync.

I-update ang isang agent:

PATCH /v1/agents/my-research-agent
Content-Type: application/json

{ \"branding\": { \"name\": \"Research Agent\", \"description\": \"Na-update na paglalarawan\" } }

Isinasama ang patch sa umiiral na agent at itinataas ang vector clock. Ang mga builtin agent ay nagbabalik ng 403 — ang mga ito ay read-only.

Mag-delete ng agent:

DELETE /v1/agents/my-research-agent

Soft-delete sa pamamagitan ng tombstone (nag-si-sync sa mga device). Nagbabalik ng 204.

Pagpapatakbo ng mga Agent

Ito ang pangunahing kaganapan — i-invoke ang isang agent upang magproseso ng mensahe.

Request body — mga sinusuportahang field

Field Kinakailangan Paglalarawan
agentId oo Builtin mode ID (hal. general) o isang custom agent ID
input.message oo Teksto ng mensahe ng user
input.attachments hindi Array ng mga attachment ID (na-upload na sa pamamagitan ng /v1/attachments) na ilalakip sa turn na ito
input.variables hindi Mga variable override bawat pagtakbo na isasama sa variable resolver ng agent
input.tabContext hindi Free-form string na inilalagay bilang page-context (ginagamit ng browser bridge)
input.messageId hindi Message ID na ibinigay ng client — kapaki-pakinabang para sa dedup kung mag-retry ka
threadId hindi Umiiral na thread na ipagpapatuloy. Kung lalaktawan, isang bagong thread ang gagawin at ibabalik
mode hindi "sync" o "async". Ang default ay "async"

Synchronous Mode

Maghintay para sa buong tugon:

POST /v1/runs
Content-Type: application/json

{
  "agentId": "general",
  "input": { "message": "Ano ang lagay ng panahon sa Paris ngayon?" },
  "mode": "sync"
}

Nagbabalik ng 200 na may { content, usage, status: "completed" } pagkatapos matapos ng agent. Kung magkaroon ng error ang agent, nagbabalik ng 500 na may { error, status: "error" }. Ang mga sync run ay nag-ta-time out pagkalipas ng 5 minuto na may status: "error" kung walang terminal event na natanggap — gamitin ang async + SSE para sa anumang bagay na maaaring magtagal.

Asynchronous Mode

Fire and forget — kapaki-pakinabang para sa mga gawaing matagal matapos:

POST /v1/runs
Content-Type: application/json

{
  "agentId": "my-research-agent",
  "input": { "message": "Sumulat ng 2000-salitang pagsusuri tungkol sa mga trend sa renewable energy" },
  "mode": "async"
}

Nagbabalik agad ng 202 na may { runId, threadId, status: "running" }.

Mag-poll para sa status:

GET /v1/runs/{runId}

Nagbabalik ng { run: { runId, threadId, agentId, status, createdAt, content?, usage?, error? } }. Ang status ay isa sa mga sumusunod: running, completed, error, o cancelled.

I-stream ang mga event sa real time (SSE):

GET /v1/runs/{runId}/events

Nagbabalik ng isang text/event-stream kasama ang bawat event ng agent habang nangyayari ito: GENERATION_STARTED, STREAMING_CONTENT, mga tool call, aktibidad ng subagent, at ang terminal event (GENERATION_COMPLETE, GENERATION_ERROR, o GENERATION_CANCELLED).

Pagkatapos ng terminal event, ang server ay naglalabas ng isang huling SSE frame na may event: terminal at isang walang lamang data payload bilang isang malinaw na end-of-stream sentinel, pagkatapos ay isasara ang koneksyon. Dapat ituring ng mga client ang pagtanggap sa frame na iyon (o ang pagsasara ng koneksyon) bilang hudyat upang huminto sa pagbabasa.

Kung mag-subscribe ka pagkatapos matapos ang pagtakbo, muling ipe-play ng server ang isang frame na may uri na RUN_SNAPSHOT na naglalaman ng buong huling record, na susundan ng event: terminal sentinel, pagkatapos ay isasara.

I-cancel ang isang pagtakbo:

POST /v1/runs/{runId}/cancel

Nagbabalik ng { run: { ..., status: "cancelled" } }.

Threads

Ang mga Threads ay mga pag-uusap. Ang bawat pagtakbo ng agent ay nangyayari sa loob ng isang thread, at ang mga threads ay nananatili sa iba't ibang session. Pinapayagan ka ng API na ilista, basahin, likhain, at pamahalaan ang mga threads sa paraang programmatiko.

Ilista ang lahat ng threads (metadata lamang):

GET /v1/threads

Nagbabalik ng { threads: [...] } para sa kasalukuyang profile kung saan tinanggal ang messages (gamitin ang detail endpoint kapag kailangan mo ang mga ito). Ang lahat ng iba pang field ay napananatili — id, title, createdAt, updatedAt, modeId, archived, usage stats, pati na rin ang subAgentHistories, anonymizerSnapshot, threadToolApprovals, threadVariables, threadToolOverrides, messagingBinding, scheduledTaskId kapag nakatakda. (Ang mas mayamang payload ay eksklusibo sa API — ang WebSocket sidebar broadcast ay gumagamit ng mas limitadong strip upang manatili sa ilalim ng mga limitasyon sa transportasyon.)

Kunin ang isang thread kasama ang buong messages:

GET /v1/threads/{id}

Nagbabalik ng kumpletong thread kasama ang messages array nito — bawat mensahe ng user, tugon ng assistant, tool call, at resulta ng tool.

Kunin lamang ang mga mensahe:

GET /v1/threads/{id}/messages

Nagbabalik lamang ng messages array — mas magaan kaysa sa buong thread object kapag ang pag-uusap lamang ang kailangan mo.

Lumikha ng isang thread:

POST /v1/threads
Content-Type: application/json

{ "title": "Research project", "modeId": "general" }

Nagbabalik ng 201 kasama ang { thread }. Ang bagong thread ay agad na lalabas sa sidebar (sa pamamagitan ng WebSocket broadcast). Hindi kailanman pinapalitan ng API ang active thread ng app sa paglikha — tawagan ang PUT /v1/threads/active nang hiwalay kung gusto mo iyon.

I-update ang isang thread:

PATCH /v1/threads/{id}
Content-Type: application/json

{ "title": "Renamed project", "archived": true }

Mga field na maaaring i-update: title, modeId, archived, lastUsedModel. Ang mga pagbabago ay ibino-broadcast sa sidebar sa real time.

I-delete ang isang thread:

DELETE /v1/threads/{id}

Soft-delete sa thread (tombstone para sa sync). Nagbabalik ng 204. Ang mga deleted threads ay mapupunta sa trash at maaaring ma-recover hanggang sa ma-empty ang trash.

Active thread:

GET /v1/threads/active            # Nagbabalik ng { threadId }
PUT /v1/threads/active            # Body: { "threadId": "..." }

Pamamahala ng trash:

GET /v1/threads/trash/count       # Nagbabalik ng { count }
POST /v1/threads/trash/empty      # Nagbabalik ng { deletedCount, protectedCount }

Ang mga protected threads (pinanatili sa pamamagitan ng data retention toggle) ay hindi kasama sa pag-empty ng trash.

Pagpapatuloy ng pag-uusap sa pamamagitan ng API: Upang magpadala ng follow-up na mensahe sa isang umiiral na thread, gamitin ang POST /v1/runs kasama ang ID ng thread:

POST /v1/runs
Content-Type: application/json

{
  "agentId": "general",
  "threadId": "existing-thread-id",
  "input": { "message": "Follow up on that last point" },
  "mode": "sync"
}

Makikita ng agent ang buong kasaysayan ng pag-uusap mula sa thread.

Mga Attachment

Ang mga attachment ay mga file na nakaugnay sa mga thread — mga screenshot, PDF, dokumento, in-upload na larawan, at mga ginawang artifact. Hinahayaan ka ng API na i-list, i-upload, i-download, at pamahalaan ang mga ito.

I-list ang lahat ng attachment (metadata lang):

GET /v1/attachments

Ibinabalik ang metadata ng attachment para sa kasalukuyang profile. Ang mabibigat na field (dataUrl, extractedContent, extractedImages) ay tinatanggal — gamitin ang detail o content endpoint para sa mga iyon.

I-list ang mga attachment para sa isang partikular na thread:

GET /v1/threads/{threadId}/attachments

Kunin ang metadata ng attachment:

GET /v1/attachments/{id}

Ibinabalik ang buong metadata kasama ang extractedContent (OCR text, parsed markdown), contentType, fileName, size, at isang hasContent flag. Ang raw binary ay HINDI kasama — gamitin ang /content endpoint para doon.

I-download ang binary ng attachment:

GET /v1/attachments/{id}/content

Ibinabalik ang raw file na may tamang Content-Type at Content-Disposition header. I-pipe ito sa isang file:

curl -o output.pdf \
  -H "Authorization: Bearer $API_TOKEN" \
  http://localhost:3847/v1/attachments/{id}/content

Mag-upload ng attachment:

POST /v1/attachments
Content-Type: application/json

{
  "threadId": "thread-id",
  "type": "user_upload",
  "contentType": "application/pdf",
  "fileName": "report.pdf",
  "description": "Quarterly report",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ..."
}

Ang dataUrl ay isang base64-encoded data URL. Ibinabalik ang 201 kasama ang bagong attachment ID. Ang attachment ay nakaugnay sa tinukoy na thread.

I-update ang metadata ng attachment:

PATCH /v1/attachments/{id}
Content-Type: application/json

{ "description": "Na-update na paglalarawan", "fileName": "new-name.pdf" }

I-delete ang isang attachment:

DELETE /v1/attachments/{id}

Soft-delete sa pamamagitan ng tombstone. Ibinabalik ang 204.

MCP Servers

Pamahalaan ang iyong mga koneksyon sa MCP (Model Context Protocol) server — ang mga server na nagbibigay sa mga agent ng access sa mga external tool at data source.

Ilista ang mga naka-configure na server:

GET /v1/mcp-servers

Ibinabalik ang lahat ng MCP server config para sa kasalukuyang profile. Ang mga sensitibong field (authToken, env, credentialId) ay tinatanggal mula sa tugon.

Kunin ang config ng isang server:

GET /v1/mcp-servers/{id}

Magdagdag ng bagong MCP server:

POST /v1/mcp-servers
Content-Type: application/json

{
  "id": "my-server",
  "name": "My MCP Server",
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"],
  "serverType": "local"
}

Para sa mga remote HTTP server, gamitin ang "url" sa halip na "command":

{
  "id": "remote-server",
  "name": "Remote API",
  "url": "https://my-mcp-server.example.com/sse",
  "serverType": "remote"
}

Mga tinatanggap na opsyonal na field sa POST: command, args, env, url, description, transportType, authType, authToken, authHeader, headers, specType, specPath, timeoutMs, credentialId, oauthConnectionId, approval. Ang mga field na pinamamahalaan ng server (customOAuth, hubPackageId, profileId, connectorId, teamPublished, teamOrgId, vectorClock, ...) ay hindi maaaring i-set sa pamamagitan ng API.

I-update ang isang server:

PATCH /v1/mcp-servers/{id}
Content-Type: application/json

{ "name": "Renamed Server", "args": ["-y", "@mcp/server-v2"] }

Ang mga patchable na field ay katulad ng POST allowlist (kabilang ang credentialId at oauthConnectionId — kapaki-pakinabang para sa pag-rotate ng isang OAuth connection nang hindi kailangang mag-delete-and-recreate). Ang mga field na pinamamahalaan ng server ay mananatiling read-only.

I-enable/i-disable ang isang server:

POST /v1/mcp-servers/{id}/toggle
Content-Type: application/json

{ "enabled": false }

I-delete ang isang server:

DELETE /v1/mcp-servers/{id}

Pamamahala ng Proseso

Para sa mga lokal na (stdio) MCP server, maaari mong pamahalaan ang proseso ng server nang direkta.

Ilista ang mga tumatakbong proseso:

GET /v1/mcp-servers/processes

Ibinabalik ang mga tumatakbong proseso ng server kasama ang pid, startedAt, at status na running.

Simulan ang isang server:

POST /v1/mcp-servers/{id}/start

Binabasa ang command/args/env mula sa server config at sinisimulan ang proseso. Ibinabalik ang status ng proseso.

Ihinto ang isang server:

POST /v1/mcp-servers/{id}/stop

Maayos na pinapatay ang proseso ng server (SIGTERM na may fallback sa SIGKILL).

Tumawag ng JSON-RPC method nang direkta:

POST /v1/mcp-servers/{id}/call
Content-Type: application/json

{ "method": "tools/list", "params": {} }

Nagpapadala ng raw JSON-RPC 2.0 request sa server at ibinabalik ang resulta. Kapaki-pakinabang para sa debugging o pagtawag sa mga method na hindi nakalantad sa pamamagitan ng tools API.

Tools & Toolkits

I-browse at i-invoke ang mga tool na ginagamit ng mga agent — web browsing, search, calendar, Gmail, Slate, at iba pa.

I-list ang mga toolkit (naka-grupo):

GET /v1/toolkits

Nagbabalik ng mga embedded tool na naka-grupo ayon sa kategorya (Productivity, Search, Utilities, atbp.) at anumang konektadong MCP server bilang hiwalay na mga toolkit, bawat isa ay may listahan ng kanilang mga action.

I-list ang lahat ng tool (flat):

GET /v1/tools
GET /v1/tools?source=embedded   # Builtin tools lamang
GET /v1/tools?source=mcp        # MCP server tools lamang

Kunin ang mga detalye ng tool kasama ang input schema:

GET /v1/tools/calculator

Nagbabalik ng { tool: { name, displayName, description, source, category, inputSchema, actions?, requiredTier?, requiredRuntimes?, riskTier?, riskExplanation?, requiresApproval? } }.

Field Kahulugan
inputSchema JSON Schema para sa input ng tool — i-validate bago i-invoke
actions Opsyonal na mga sub-action (hal. Slate read/write); bawat isa ay may id, displayName, description, opsyonal na requiredTier
requiredTier Minimum na tier ng user (free kung wala). Ang public-API invocation ay tatanggi sa anumang higit sa free
requiredRuntimes Mga platform kung saan available ang tool na ito (macos, ios, atbp.); laktawan ⇒ kahit saan
riskTier Risk sa pahintulot: low (default), medium, high
riskExplanation Dahilan na nababasa ng tao kung bakit mataas ang riskTier
requiresApproval true kapag kailangan ng tool ng pag-apruba ng user sa bawat tawag — tinatanggihan ito ng public-API invocation

I-invoke ang isang tool nang direkta:

POST /v1/tools/calculator/invoke
Content-Type: application/json

{ "input": { "expression": "sqrt(144) + 3^2" }, "threadId": "optional-thread-id" }

Nagbabalik ng { result }. Ang input ay vine-verify laban sa schema ng tool — ang invalid na input ay nagbabalik ng 422 kasama ang mga detalye. Magpasa ng opsyonal na threadId kung kailangan ng tool ng thread-scoped context (hal. paghahanap ng attachment).

Gating — kung ano ang tinatanggihan ng public API:

  • Tier-gated tools (metadata.requiredTier !== 'free') → 403. Sinusuri ng agent loop ang tier laban sa session ng user; ang public API ay walang dalang tier context, kaya ang konserbatibong polisiya ay tumanggi. Gamitin ang POST /v1/runs kasama ang isang agent na may tamang tier sa halip.
  • Approval-required tools (metadata.approval.requiresApproval === true) → 403. Walang tao sa loop para tanungin. I-invoke sa pamamagitan ng POST /v1/runs (na nagpapakita ng prompt sa user) o i-set ang tool approval mode sa approve_all sa app para lumaktaw.
  • Remote MCP tools501 na may gabay na gamitin ang /v1/runs (kinakailangan ng mga ito ang agent subprocess transport).

Vision at mga tool na gumagamit ng imahe: i-upload muna sa pamamagitan ng POST /v1/attachments, pagkatapos ay ipasa ang ibinalik na attachment ID sa loob ng input (hal. { "input": { "attachment_id": "att_abc", "prompt": "Ano ang nasa imaheng ito?" } }). Binabasa ng tool ang binary mula sa storage sa pamamagitan ng threadId; hindi mo ipapasa ang mga byte nang inline.

Mga Connector

Mamahala ng mga OAuth integration — Google, Microsoft, GitHub, Notion, Slack, at iba pa.

Mag-browse ng mga available na integration:

GET /v1/connectors/catalog

Ibinabalik ang lahat ng rehistradong OAuth provider kasama ang kanilang pangalan, kategorya, at default scopes.

Ilista ang iyong mga konektadong account:

GET /v1/connectors

Ibinabalik ang mga aktibong koneksyon para sa kasalukuyang profile. Ang mga token ay hindi kailanman ipinapakita — metadata lamang (provider, email, status, scopes, timestamps).

Kumuha ng iisang koneksyon:

GET /v1/connectors/{id}

Ibinabalik ang metadata para sa isang koneksyon (provider, email, status, scopes, timestamps). Ang mga token ay hindi kailanman ipinapakita.

Suriin ang kalusugan ng koneksyon:

POST /v1/connectors/{id}/test

Ibinabalik ang { health: { status, isTokenExpired, canRefresh } }.

Mag-alis ng koneksyon:

DELETE /v1/connectors/{id}

Ang paggawa ng mga bagong koneksyon ay nangangailangan ng interactive na OAuth flow sa pamamagitan ng app UI o ng mga /auth/* na ruta.

Mga Trigger

Mag-iskedyul ng mga agent na awtomatikong tatakbo — mga pang-araw-araw na briefing, lingguhang ulat, at pagsubaybay na batay sa agwat.

Bawat trigger ay may kind discriminator: schedule (default — gumagana sa orasan), webhook (gumagana kapag ang isang panlabas na serbisyo ay nag-POST sa webhook path), o messaging (gumagana mula sa isang konektadong messaging adapter — hal. mga papasok na mensahe sa Slack/Discord na tumutugma sa isang channel filter).

Ilista ang mga trigger:

GET /v1/triggers

Nagbabalik ng { triggers: [...] }. Kasama sa bawat entry ang kind nito, iskedyul, at mga field na partikular sa uri (hal. webhookSecret/webhookPath para sa mga webhook trigger, messagingAdapterId/messagingChannelFilter para sa mga messaging trigger).

Kumuha ng isang trigger:

GET /v1/triggers/{id}

Gumawa ng naka-iskedyul na trigger:

POST /v1/triggers
Content-Type: application/json

{
  "name": "Morning Briefing",
  "prompt": "I-summarize ang aking mga hindi nabasang email at kalendaryo ngayong araw",
  "modeId": "general",
  "schedule": { "type": "daily", "time": "08:00" }
}

Mga suportadong uri ng iskedyul:

  • { "type": "interval", "minutes": 60 } — bawat N minuto (min 15, max 1440)
  • { "type": "daily", "time": "09:00" } — araw-araw sa partikular na oras
  • { "type": "weekly", "day": "mon", "time": "09:00" } — lingguhan
  • { "type": "weekdays", "time": "08:30" } — Lunes hanggang Biyernes
  • { "type": "daysOfWeek", "days": ["mon", "wed", "fri"], "time": "10:00" } — mga partikular na araw
  • { "type": "monthly", "dayOfMonth": 1, "time": "09:00" } — buwanan
  • { "type": "manual" } — kapag pinagana lang sa pamamagitan ng API

Paganahin ang trigger nang manu-mano:

POST /v1/triggers/{id}/fire

Nagbabalik ng 202 na may threadId para sa nagresultang pagtakbo.

I-update o i-delete:

PATCH /v1/triggers/{id}
DELETE /v1/triggers/{id}

Mga Webhook

Ang mga webhook trigger ay nagpapahintulot sa mga panlabas na serbisyo (CI/CD, monitoring, form builders) na mag-trigger ng pagtakbo ng agent sa pamamagitan ng HTTP.

Gumawa ng webhook trigger:

POST /v1/triggers
Content-Type: application/json

{
  "name": "Deploy hook",
  "prompt": "May nangyaring deploy: {{webhook.body}}",
  "modeId": "general",
  "kind": "webhook"
}

Nagbabalik ng 201 na may webhookSecret at webhookPath. Itago ang secret — kakailanganin mo ito para pirmahan ang mga payload.

Magpadala ng webhook:

# I-compute ang HMAC-SHA256 ng raw request body
SIGNATURE=$(echo -n '{"repo":"my-app","branch":"main"}' | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | awk '{print $2}')

POST /v1/webhooks/{triggerId}
Content-Type: application/json
X-Webhook-Signature: $SIGNATURE

{"repo": "my-app", "branch": "main"}

Ang webhook endpoint ay HINDI nangangailangan ng bearer auth — gumagamit ito ng HMAC verification sa halip. Nagbabalik ng 202 na may threadId ng ipinadalang pagtakbo. Ang {{webhook.body}} placeholder sa trigger prompt ay mapapalitan ng raw request body.

Mga Messaging trigger

Gumagana ang mga messaging trigger kapag ang isang konektadong messaging adapter (hal. isang Slack o Discord integration na naka-install sa pamamagitan ng Community Hub) ay nakatanggap ng papasok na mensahe na tumutugma sa filter ng trigger. Gumawa gamit ang kind: "messaging":

POST /v1/triggers
Content-Type: application/json

{
  "name": "Mention responder",
  "prompt": "Sumagot nang may katulong sa: {{message.text}}",
  "modeId": "general",
  "kind": "messaging",
  "messagingAdapterId": "slack-team-acme",
  "messagingChannelFilter": "#support"
}

Ang adapter ang responsable sa pagpapadala ng mga tumutugmang event sa trigger; ang messagingChannelFilter ay partikular sa adapter.

Mga Custom Function

Gumawa ng sarili mong mga tool na maaaring tawagan ng mga agent. Ang mga function ay isinusulat sa JavaScript o Python at tumatakbo sa isang sandbox.

I-list ang mga function:

GET /v1/functions

Gumawa ng function:

POST /v1/functions
Content-Type: application/json

{
  "name": "calculate_bmi",
  "description": "I-calculate ang Body Mass Index mula sa taas at timbang",
  "language": "javascript",
  "source": "return { bmi: (input.weightKg / (input.heightM * input.heightM)).toFixed(1) };",
  "inputSchema": {
    "type": "object",
    "properties": {
      "weightKg": { "type": "number" },
      "heightM": { "type": "number" }
    },
    "required": ["weightKg", "heightM"]
  }
}

Ang mga JavaScript function ay tumatanggap ng input at dapat magbalik ng resulta. Ang mga Python function naman ay nagse-set ng result variable:

# Halimbawa sa Python
result = {"bmi": round(input["weightKg"] / (input["heightM"] ** 2), 1)}

I-execute nang direkta ang isang function:

POST /v1/functions/{id}/execute
Content-Type: application/json

{ "input": { "weightKg": 75, "heightM": 1.80 } }

Seguridad: Ang JavaScript ay tumatakbo sa vm sandbox ng Node (walang access sa filesystem o network, 10s timeout). Ang Python ay tumatakbo bilang isang subprocess na may 30s timeout. Parehong nagva-validate ng input bago ang execution.

I-update o i-delete:

PATCH /v1/functions/{id}
DELETE /v1/functions/{id}

Mga Skill

Ang mga Skill ay mga naka-save na prompt na maaaring i-reference ng mga agent at mabilis na i-launch mula sa blank-conversation view. Ang mga skill na naka-install mula sa Hub (pinamamahalaan sa pamamagitan ng package install) ay HINDI kasama rito — tanging mga skill na ginawa ng user ang nakalista at maaaring i-edit.

Ilista ang mga skill:

GET /v1/skills

Nagbabalik ng { skills: [...] } ng mga skill na ginawa ng user para sa aktibong profile. Ang mga tombstoned, hub-overlay, at sync-shadow na skill ay sinala palabas.

Kumuha ng isang skill:

GET /v1/skills/{id}

Gumawa ng skill:

POST /v1/skills
Content-Type: application/json

{
  "prompt": "I-summarize ang pahina sa 3 bullet point.",
  "tags": ["utility", "summarize"],
  "isFavorite": true,
  "modes": ["general"],
  "displayName": "Mabilis na Buod",
  "description": "Tatlong-bullet na TL;DR ng aktibong pahina"
}

Tanging prompt ang kinakailangan. Ang modes (opsyonal) ay naglilimita sa skill sa mga partikular na agent ID; laktawan para sa lahat ng mode. Nagbabalik ng 201 kasama ang bagong skill (kabilang ang server-assigned id, createdAt, updatedAt).

I-update ang isang skill:

PATCH /v1/skills/{id}
Content-Type: application/json

{ "prompt": "Na-update na prompt", "isFavorite": false }

Mga field na maaaring i-patch: prompt, tags, modes, displayName, description, isFavorite. Ang mga pagtatangkang i-patch ang isang hub-overlay skill ay magbabalik ng 404.

Burahin ang isang skill:

DELETE /v1/skills/{id}

Soft-delete sa pamamagitan ng tombstone. Nagbabalik ng 204. Ang mga hub-overlay skill ay magbabalik ng 404 — i-uninstall ang source package sa halip.

Mga Workflow

Mag-orchestrate ng maraming agent sa isang DAG (directed acyclic graph) — magpatakbo ng mga step nang sabay-sabay kung posible, at gamitin ang mga output mula sa mga naunang step sa mga susunod.

I-validate ang isang workflow graph:

POST /v1/workflows/validate
Content-Type: application/json

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Magsaliksik tungkol sa mga trend sa renewable energy" },
      { "id": "analyze", "agentId": "general", "prompt": "Magsaliksik tungkol sa presyo ng mga kakumpitensya" },
      { "id": "report", "agentId": "general", "prompt": "Sumulat ng report na pinagsasama ang: {{outputs.research}} at {{outputs.analyze}}", "dependsOn": ["research", "analyze"] }
    ]
  }
}

Ibinabalik ang { valid: true/false, errors: [...] }. Sinusuri nito kung may mga cycle, duplicate na ID, at nawawalang dependency reference.

I-execute ang isang workflow:

POST /v1/workflows/execute
Content-Type: application/json

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Magsaliksik tungkol sa mga trend sa renewable energy" },
      { "id": "summarize", "agentId": "general", "prompt": "I-summarize: {{outputs.research}}", "dependsOn": ["research"] }
    ]
  }
}

Ibinabalik ang { status: "completed", outputs: { research: "...", summarize: "..." }, nodeResults: {...} }.

Ang mga independent node (walang shared dependency) ay tumatakbo nang sabay-sabay. Ang {{outputs.nodeId}} placeholder sa prompt ng isang node ay pinapalitan ng content output ng pinangalanang upstream node. Ang bawat node ay isang ganap na pagtakbo ng agent, kaya maaari itong gumamit ng mga tool, mag-browse sa web, at ma-access ang lahat ng kakayahan ng target agent.

Mga Knowledge Base

Ayusin ang mga dokumento sa mga searchable collection na maaaring sangguniin ng mga agent.

I-list ang mga knowledge base:

GET /v1/knowledge/bases

Gumawa ng knowledge base:

POST /v1/knowledge/bases
Content-Type: application/json

{ "name": "Mga Research Paper" }

Ibinabalik ang 201 kasama ang bagong base ID.

Mag-upload ng dokumento sa isang knowledge base:

POST /v1/knowledge/bases/{id}/documents
Content-Type: application/json

{
  "fileName": "research-paper.pdf",
  "contentType": "application/pdf",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ...",
  "description": "Mga trend sa renewable energy 2026"
}

Ang dataUrl field ay isang base64-encoded data URL. Ibinabalik ang 201 kasama ang metadata ng dokumento.

I-list ang mga dokumento sa isang knowledge base:

GET /v1/knowledge/bases/{id}/documents

Mag-search sa loob ng isang knowledge base:

POST /v1/knowledge/bases/{id}/search
Content-Type: application/json

{ "query": "renewable energy" }

Ibinabalik ang mga tumutugmang dokumento batay sa pangalan ng file at paglalarawan. Ang semantic (vector) search ay darating sa susunod na release.

I-delete ang isang dokumento o knowledge base:

DELETE /v1/knowledge/bases/{id}/documents/{docId}
DELETE /v1/knowledge/bases/{id}

Mag-export at Mag-import ng mga Agent

Ibahagi ang mga agent bilang mga portable package — sa mga device, team, o sa Community Hub.

I-export ang isang agent:

POST /v1/agents/{id}/export

Nagbabalik ng isang JSON package na naglalaman ng agent definition, tool requirements (mula sa mga enabled tool), connector requirements (kung aling mga OAuth provider ang kailangan), at mga trigger template. Ang sync metadata ay tinatanggal — ang package ay isang malinis at self-contained na blueprint.

Mag-import ng isang agent:

POST /v1/agents/import
Content-Type: application/json

{
  \"package\": {
    \"$schema\": \"caiioo.agent.package/v1\",
    \"agent\": {
      \"id\": \"shared-research-agent\",
      \"branding\": { \"name\": \"Research Agent\", \"description\": \"Mula sa team\" },
      \"defaultSettings\": { \"systemPrompt\": \"Nagsasaliksik ka ng mga bagay.\" },
      \"settingLevels\": {}
    },
    \"toolRequirements\": [
      { \"toolId\": \"web_browsing\", \"enabled\": true },
      { \"toolId\": \"search_tools\", \"enabled\": true }
    ]
  }
}

Nagbabalik ng 201 kasama ang na-install na agent. Ang mga ID collision sa mga builtin o umiiral na agent ay nagbabalik ng 409.

Paghawak ng Error

Gumagamit ang API ng mga standard na HTTP status code:

Code Kahulugan
200 Tagumpay
201 Nalikha
202 Tinanggap (nagsimula na ang async operation)
204 Nabura (walang nilalaman)
400 Maling request — tingnan ang error field para sa mga detalye
401 Walang pahintulot — kulang o hindi balidong session secret
403 Ipinagbabawal — hal., sinusubukang baguhin ang isang builtin agent
404 Hindi nahanap
409 Salungatan — hal., umiiral na ang agent ID
422 Error sa validation — hindi tumutugma ang input sa tool schema
429 Limitado ang rate — tingnan ang mga rate-limit budget sa seksyon ng Pagpapatotoo
500 Error sa server — tingnan ang error field
501 Hindi ipinatupad — umiiral ang feature pero hindi available sa ganitong paraan
503 Hindi available ang serbisyo — hindi handa ang storage o provider

Lahat ng tugon sa error ay may kasamang { "error": "mensaheng nababasa ng tao" }.

Halimbawa ng Quick Start

Narito ang isang kumpletong workflow: gumawa ng agent, patakbuhin ito, at i-stream ang mga resulta.

# 1. Gumawa ng custom agent
curl -X POST http://localhost:3847/v1/agents \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "quick-summarizer",
    "branding": { "name": "Quick Summarizer" },
    "defaultSettings": {
      "systemPrompt": "I-summarize ang anumang input nang maikli sa 3 bullet point.",
      "enabledTools": { "web_browsing": true }
    },
    "settingLevels": {}
  }'

# 2. Patakbuhin ito nang asynchronously
RUN=$(curl -s -X POST http://localhost:3847/v1/runs \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "agentId": "quick-summarizer", "input": { "message": "I-summarize ang https://en.wikipedia.org/wiki/Artificial_intelligence" }, "mode": "async" }')

RUN_ID=$(echo $RUN | jq -r '.runId')

# 3. I-stream ang mga event
curl -N http://localhost:3847/v1/runs/$RUN_ID/events \
  -H "Authorization: Bearer $API_TOKEN"

# 4. I-export ang agent para maibahagi
curl -X POST http://localhost:3847/v1/agents/quick-summarizer/export \
  -H "Authorization: Bearer $API_TOKEN"

This guide is maintained by the Caiioo team using Slate, our built-in editor.