Данный документ является машинным переводом оригинальной английской версии. В случае любых расхождений между переводом и оригиналом на английском языке, приоритет имеет английская версия. Читать оригинал на английском языке


Публичный API

Caiioo включает REST API, который позволяет управлять всем программно: запускать агентов, управлять инструментами, планировать задачи и многое другое. API находится на том же локальном сервере, который обеспечивает работу десктопного приложения и браузерного моста.

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

Аутентификация: Два способа аутентификации, оба ограничиваются переключателем API в настройках:

Для внешних потребителей (скрипты, интеграции, curl): Установите токен доступа к API в Настройки > API Access, затем используйте его как Bearer-токен:

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

Для локального приложения (автоматически): Десктопное приложение Caiioo, расширения для браузера и мобильные приложения аутентифицируются автоматически через существующий заголовок relay auth (x-relay-auth; заголовки HTTP нечувствительны к регистру). Ручная настройка не требуется — приложение обрабатывает это за кулисами. Запросы с relay-auth обходят переключатель «Enable Public API», так как они уже являются доверенными; только запросы с bearer-токеном ограничиваются этим переключателем.

Настройка:

  1. Откройте Caiioo Настройки > API Access
  2. Включите Enable Public API
  3. Установите API access token (любая строка на ваш выбор — относитесь к ней как к паролю)
  4. Используйте этот токен во всех API-запросах

API доступен на localhost и через приватный ретранслятор. Проверьте GET /v1/auth/info (авторизация не требуется) для получения текущего статуса и инструкций по настройке.

Лимиты запросов: каждый запрос к /v1/* ограничен по IP клиента — 100 GET-запросов в минуту для чтения и 30 запросов на запись в минуту (POST / PATCH / DELETE) суммарно. Запросы сверх лимита получают код 429. Доставка вебхуков (POST /v1/webhooks/:id) не требует bearer-авторизации и не подпадает под эти лимиты.

Профили

Одно устройство может содержать несколько профилей пользователей (например, личный + рабочий). API позволяет внешним скриптам проверять доступные профили и переключать активный перед выполнением работы. Создание, обновление и удаление профилей намеренно не выведены в публичный API — эти процессы относятся к интерфейсу онбординга приложения.

Список профилей:

GET /v1/profiles

Возвращает { profiles: [...] } с одной записью для каждого неудаленного профиля. Каждая запись включает id, name, email, avatarUrl, tier, accessibleModes, license, organization, preferences, onboardingComplete, createdAt, lastAccessedAt. Поля, содержащие токены (serviceCredentials, oauthConnections), и внутренние данные синхронизации (vectorClock, lastModifiedBy) удалены. Используйте /v1/connectors для просмотра подключений OAuth.

Получить активный профиль:

GET /v1/profiles/active

Возвращает { profile } для профиля, используемого сервером в данный момент. Все ресурсы /v1/*, привязанные к профилю (треды, вложения, настройки, навыки), работают с этим профилем.

Переключить активный профиль:

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

{ "profileId": "user-uuid-from-list" }

Возвращает { profile } для нового активного профиля. Возвращает 404, если ID профиля не найден.

Providers & Models

Узнайте, какие провайдеры LLM настроены и какие модели доступны.

Список провайдеров:

GET /v1/providers

Возвращает все поддерживаемые типы провайдеров. В настоящее время: anthropic, openai, google, openrouter, ollama, poe, mlx, perplexity, baseten, cloudflare. Каждая запись включает type, displayName, icon, requiresApiKey, hasApiKey, а также объект capabilities с флагами, указанными ниже.

Флаг возможности Значение
supportsVision Провайдер может принимать изображения на вход
supportsPdfFile Провайдер нативно поддерживает блоки содержимого в формате PDF
supportsToolCalling Провайдер поддерживает вызов функций/инструментов
supportsStreaming Провайдер поддерживает потоковую передачу токенов
supportsExtendedThinking Провайдер предоставляет бюджет на рассуждения (thinking budget)
supportsPromptCaching Провайдер поддерживает директивы кэширования промптов
nativeReasoningBlocks Провайдер выдает рассуждения в виде нативных блоков сообщений (а не текста)
requiresThoughtSignature Провайдер требует возврата подписанных токенов рассуждений

Флаги возможностей дублируют поле readonly capabilities каждого класса провайдера (см. src/shared/providers/*-provider.ts) и проверяются тестом на соответствие — вызывайте этот эндпоинт во время выполнения, а не прописывайте матрицу жестко в коде.

Примечания для BYOK провайдеров:

  • perplexity предоставляет курируемый список моделей Sonar (у Perplexity нет публичного эндпоинта /models).
  • cloudflare (AI Gateway) — это BYOK + мульти-вендор; список моделей определяется конфигурацией вашего шлюза и возвращается в виде пустого массива через /v1/providers/cloudflare/models. Используйте каталог вашего собственного шлюза.

Список моделей для провайдера:

GET /v1/providers/openrouter/models

Возвращает каталог моделей для указанного провайдера. Каждая модель включает id, displayName и contextLength (если доступно). Возвращает ошибку 503, если у провайдера отсутствует API ключ или его вышестоящий каталог недоступен.

Общий каталог по всем провайдерам:

GET /v1/models

Объединяет модели от всех настроенных провайдеров в один список. Провайдеры без API ключей пропускаются и указываются в поле warnings.

Агенты

Агенты — это сердце caiioo. Каждый агент — это Режим, настроенная личность со своим системным промптом, инструментами и навыками.

Список всех агентов:

GET /v1/agents

Возвращает встроенных агентов (Shopping, Workplace, General) и созданных вами. Каждый помечен как source: \"builtin\" или source: \"custom\".

Создать агента:

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

{
  \"id\": \"my-research-agent\",
  \"branding\": {
    \"name\": \"Research Agent\",
    \"description\": \"Ищет в сети и резюмирует находки\"
  },
  \"defaultSettings\": {
    \"systemPrompt\": \"Вы — ассистент-исследователь. Всегда цитируйте источники.\",
    \"enabledTools\": { \"web_browsing\": true, \"search_tools\": true }
  },
  \"settingLevels\": {}
}

Возвращает 201. Векторные часы добавляются автоматически для синхронизации.

Обновить агента:

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

{ \"branding\": { \"name\": \"Research Agent\", \"description\": \"Обновленное описание\" } }

Объединяет изменения с существующим агентом. Встроенные агенты возвращают 403 — они только для чтения.

Удалить агента:

DELETE /v1/agents/my-research-agent

Мягкое удаление через tombstone (синхронизируется между устройствами). Возвращает 204.

Запуск агентов

Это основное событие — вызов агента для обработки сообщения.

Тело запроса — поддерживаемые поля

Поле Обязательно Описание
agentId да ID встроенного режима (например, general) или ID пользовательского агента
input.message да Текст сообщения пользователя
input.attachments нет Массив ID вложений (уже загруженных через /v1/attachments) для прикрепления к этому ходу
input.variables нет Переопределения переменных для конкретного запуска, объединяемые с резолвером переменных агента
input.tabContext нет Строка в свободной форме, вставляемая как контекст страницы (используется браузерным мостом)
input.messageId нет ID сообщения, предоставляемый клиентом — полезно для дедупликации при повторных попытках
threadId нет Существующий тред для продолжения. Если не указан, создается и возвращается новый тред
mode нет "sync" или "async". По умолчанию "async"

Синхронный режим

Ожидание полного ответа:

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

{
  "agentId": "general",
  "input": { "message": "What's the weather in Paris today?" },
  "mode": "sync"
}

Возвращает 200 с { content, usage, status: "completed" } после завершения работы агента. Если агент выдает ошибку, возвращает 500 с { error, status: "error" }. Синхронные запуски завершаются по таймауту через 5 минут со статусом status: "error", если не получено терминальное событие — используйте async + SSE для задач, которые могут занять больше времени.

Асинхронный режим

«Выстрелил и забыл» — полезно для длительных задач:

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

{
  "agentId": "my-research-agent",
  "input": { "message": "Write a 2000-word analysis of renewable energy trends" },
  "mode": "async"
}

Немедленно возвращает 202 с { runId, threadId, status: "running" }.

Опрос статуса:

GET /v1/runs/{runId}

Возвращает { run: { runId, threadId, agentId, status, createdAt, content?, usage?, error? } }. Статус принимает одно из значений: running, completed, error или cancelled.

Стриминг событий в реальном времени (SSE):

GET /v1/runs/{runId}/events

Возвращает text/event-stream с каждым событием агента по мере их возникновения: GENERATION_STARTED, STREAMING_CONTENT, вызовы инструментов, активность субагентов и терминальное событие (GENERATION_COMPLETE, GENERATION_ERROR или GENERATION_CANCELLED).

После терминального события сервер отправляет один финальный SSE-фрейм с event: terminal и пустыми данными в качестве явного маркера конца потока, затем закрывает соединение. Клиенты должны рассматривать получение этого фрейма (или закрытие соединения) как сигнал к прекращению чтения.

Если вы подписываетесь после того, как запуск уже завершен, сервер воспроизводит один фрейм типа RUN_SNAPSHOT, содержащий полную финальную запись record, за которым следует маркер event: terminal, после чего закрывает соединение.

Отмена запуска:

POST /v1/runs/{runId}/cancel

Возвращает { run: { ..., status: "cancelled" } }.

Threads

Threads — это беседы. Каждый запуск агента происходит внутри thread, и они сохраняются между сессиями. API позволяет перечислять, читать, создавать и управлять threads программно.

Список всех threads (только метаданные):

GET /v1/threads

Возвращает { threads: [...] } для текущего профиля с удаленным полем messages (используйте эндпоинт детализации, когда они вам понадобятся). Все остальные поля сохраняются — id, title, createdAt, updatedAt, modeId, archived, статистика использования, а также subAgentHistories, anonymizerSnapshot, threadToolApprovals, threadVariables, threadToolOverrides, messagingBinding, scheduledTaskId, если они установлены. (Более полная полезная нагрузка эксклюзивна для API — широковещательная рассылка боковой панели через WebSocket использует более сильное сокращение данных, чтобы оставаться в рамках лимитов передачи.)

Получить thread с полным списком сообщений:

GET /v1/threads/{id}

Возвращает полный объект thread, включая массив messages — каждое сообщение пользователя, ответ ассистента, вызов инструмента и результат работы инструмента.

Получить только сообщения:

GET /v1/threads/{id}/messages

Возвращает только массив messages — это легче, чем полный объект thread, когда вам нужна только беседа.

Создать thread:

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

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

Возвращает 201 с объектом { thread }. Новый thread немедленно появляется в боковой панели (через WebSocket). API никогда не переключает активный thread в приложении при создании — вызовите PUT /v1/threads/active отдельно, если вам это необходимо.

Обновить thread:

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

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

Поля, доступные для обновления: title, modeId, archived, lastUsedModel. Изменения транслируются в боковую панель в режиме реального времени.

Удалить thread:

DELETE /v1/threads/{id}

Выполняет мягкое удаление thread (пометка для синхронизации). Возвращает 204. Удаленные threads перемещаются в корзину и могут быть восстановлены до тех пор, пока корзина не будет очищена.

Активный thread:

GET /v1/threads/active            # Возвращает { threadId }
PUT /v1/threads/active            # Тело: { "threadId": "..." }

Управление корзиной:

GET /v1/threads/trash/count       # Возвращает { count }
POST /v1/threads/trash/empty      # Возвращает { deletedCount, protectedCount }

Защищенные threads (сохраненные с помощью переключателя хранения данных) исключаются при очистке корзины.

Продолжение беседы через API: Чтобы отправить последующее сообщение в существующий thread, используйте POST /v1/runs с ID этого thread:

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

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

Агент видит всю историю беседы из данного thread.

Вложения

Вложения — это файлы, связанные с тредами: скриншоты, PDF, документы, загруженные изображения, сгенерированные артефакты. API позволяет просматривать, загружать, скачивать и управлять ими.

Список всех вложений (только метаданные):

GET /v1/attachments

Возвращает метаданные вложений для текущего профиля. Тяжелые поля (dataUrl, extractedContent, extractedImages) удалены — используйте эндпоинты деталей или контента для их получения.

Список вложений для конкретного треда:

GET /v1/threads/{threadId}/attachments

Получение метаданных вложения:

GET /v1/attachments/{id}

Возвращает полные метаданные, включая extractedContent (текст OCR, распарсенный markdown), contentType, fileName, size и флаг hasContent. Необработанный бинарный файл НЕ включен — используйте эндпоинт /content для этого.

Скачивание бинарного файла вложения:

GET /v1/attachments/{id}/content

Возвращает необработанный файл с правильными заголовками Content-Type и Content-Disposition. Перенаправьте это в файл:

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

Загрузка вложения:

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

{
  "threadId": "thread-id",
  "type": "user_upload",
  "contentType": "application/pdf",
  "fileName": "report.pdf",
  "description": "Квартальный отчет",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ..."
}

dataUrl — это URL-адрес данных в кодировке base64. Возвращает 201 с ID нового вложения. Вложение привязывается к указанному треду.

Обновление метаданных вложения:

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

{ "description": "Обновленное описание", "fileName": "new-name.pdf" }

Удаление вложения:

DELETE /v1/attachments/{id}

Мягкое удаление через tombstone. Возвращает 204.

MCP Серверы

Управляйте подключениями к вашим серверам MCP (Model Context Protocol) — серверам, которые предоставляют агентам доступ к внешним инструментам и источникам данных.

Список настроенных серверов:

GET /v1/mcp-servers

Возвращает все конфигурации MCP серверов для текущего профиля. Конфиденциальные поля (authToken, env, credentialId) удаляются из ответа.

Получить конфигурацию сервера:

GET /v1/mcp-servers/{id}

Добавить новый MCP сервер:

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"
}

Для удаленных HTTP-серверов используйте "url" вместо "command":

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

Допустимые необязательные поля в POST: command, args, env, url, description, transportType, authType, authToken, authHeader, headers, specType, specPath, timeoutMs, credentialId, oauthConnectionId, approval. Поля, управляемые сервером (customOAuth, hubPackageId, profileId, connectorId, teamPublished, teamOrgId, vectorClock, ...), не могут быть установлены через API.

Обновить сервер:

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

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

Поля, доступные для изменения через PATCH, соответствуют белому списку POST (включая credentialId и oauthConnectionId — удобно для ротации OAuth соединения без удаления и повторного создания). Поля, управляемые сервером, остаются доступными только для чтения.

Включить/выключить сервер:

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

{ "enabled": false }

Удалить сервер:

DELETE /v1/mcp-servers/{id}

Управление процессами

Для локальных (stdio) MCP серверов вы можете управлять процессом сервера напрямую.

Список запущенных процессов:

GET /v1/mcp-servers/processes

Возвращает запущенные процессы серверов со статусами pid, startedAt и running.

Запустить сервер:

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

Считывает command/args/env из конфигурации сервера и порождает процесс. Возвращает статус процесса.

Остановить сервер:

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

Корректно завершает процесс сервера (SIGTERM с переходом к SIGKILL при необходимости).

Вызвать метод JSON-RPC напрямую:

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

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

Отправляет необработанный запрос JSON-RPC 2.0 на сервер и возвращает результат. Полезно для отладки или вызова методов, не представленных через API инструментов.

Tools & Toolkits

Просматривайте и вызывайте инструменты, которые используют агенты — веб-браузинг, поиск, календарь, Gmail, Slate и другие.

Список наборов инструментов (сгруппированный):

GET /v1/toolkits

Возвращает встроенные инструменты, сгруппированные по категориям (Productivity, Search, Utilities и т. д.), а также любые подключенные MCP серверы как отдельные наборы инструментов, каждый со списком доступных действий.

Список всех инструментов (плоский):

GET /v1/tools
GET /v1/tools?source=embedded   # Только встроенные инструменты
GET /v1/tools?source=mcp        # Только инструменты MCP серверов

Получение сведений об инструменте со схемой ввода:

GET /v1/tools/calculator

Возвращает { tool: { name, displayName, description, source, category, inputSchema, actions?, requiredTier?, requiredRuntimes?, riskTier?, riskExplanation?, requiresApproval? } }.

Поле Значение
inputSchema JSON Schema для входных данных инструмента — выполните валидацию перед вызовом
actions Необязательные под-действия (например, read/write в Slate); каждое имеет id, displayName, description, необязательный requiredTier
requiredTier Минимальный уровень подписки пользователя (free, если не указано). Вызов через публичный API отклоняет всё, что выше free
requiredRuntimes Платформы, на которых доступен этот инструмент (macos, ios и т. д.); если опущено ⇒ доступен везде
riskTier Риск согласия: low (по умолчанию), medium, high
riskExplanation Понятное человеку объяснение причины повышения riskTier
requiresApproval true, если инструменту требуется одобрение пользователя для каждого вызова — вызовы через публичный API отклоняют такие инструменты

Прямой вызов инструмента:

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

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

Возвращает { result }. Входные данные проверяются на соответствие схеме инструмента — некорректные данные возвращают 422 с подробностями. Передайте необязательный threadId, если инструменту требуется контекст в рамках потока (например, поиск вложений).

Ограничения — что отклоняет публичный API:

  • Инструменты с ограничением по уровню подписки (metadata.requiredTier !== 'free') → 403. Цикл агента проверяет уровень подписки в сессии пользователя; у публичного API нет контекста подписки, поэтому консервативная политика — отказ. Вместо этого используйте POST /v1/runs с агентом, имеющим соответствующий уровень.
  • Инструменты, требующие одобрения (metadata.approval.requiresApproval === true) → 403. В цикле нет человека, у которого можно спросить разрешение. Вызывайте через POST /v1/runs (который выводит запрос пользователю) или установите режим одобрения инструментов на approve_all в приложении для обхода.
  • Удаленные инструменты MCP501 с рекомендацией использовать /v1/runs (им требуется транспорт подпроцесса агента).

Инструменты для работы со зрением и изображениями: сначала загрузите файл через POST /v1/attachments, затем передайте полученный ID вложения внутри input (например, { "input": { "attachment_id": "att_abc", "prompt": "What is in this image?" } }). Инструмент считывает бинарные данные из хранилища, используя threadId; байты не передаются напрямую в теле запроса.

Коннекторы

Управляйте OAuth-интеграциями — Google, Microsoft, GitHub, Notion, Slack и другими.

Просмотр доступных интеграций:

GET /v1/connectors/catalog

Возвращает всех зарегистрированных OAuth-провайдеров с их именами, категориями и областями доступа по умолчанию.

Список ваших подключенных аккаунтов:

GET /v1/connectors

Возвращает активные подключения для текущего профиля. Токены никогда не раскрываются — только метаданные (провайдер, email, статус, области доступа, метки времени).

Получить одно подключение:

GET /v1/connectors/{id}

Возвращает метаданные одного подключения. Токены никогда не раскрываются.

Проверить состояние подключения:

POST /v1/connectors/{id}/test

Возвращает { health: { status, isTokenExpired, canRefresh } }.

Удалить подключение:

DELETE /v1/connectors/{id}

Создание новых подключений требует интерактивного потока OAuth через интерфейс приложения или маршруты /auth/*.

Триггеры

Планируйте автоматический запуск агентов — ежедневные сводки, еженедельные отчеты, мониторинг с заданным интервалом.

У каждого триггера есть дискриминатор kind: schedule (по умолчанию — срабатывает по часам), webhook (срабатывает, когда внешний сервис отправляет POST на путь вебхука) или messaging (срабатывает от подключенного мессенджер-адаптера — например, входящие сообщения Slack/Discord, соответствующие фильтру канала).

Список триггеров:

GET /v1/triggers

Возвращает { triggers: [...] }. Каждая запись включает kind, расписание и специфичные для типа поля (например, webhookSecret/webhookPath для вебхуков, messagingAdapterId/messagingChannelFilter для мессенджеров).

Получить один триггер:

GET /v1/triggers/{id}

Создать триггер по расписанию:

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

{
  \"name\": \"Утренняя сводка\",
  \"prompt\": \"Кратко изложи мои непрочитанные письма и календарь на сегодня\",
  \"modeId\": \"general\",
  \"schedule\": { \"type\": \"daily\", \"time\": \"08:00\" }
}

Поддерживаемые типы расписания:

  • { \"type\": \"interval\", \"minutes\": 60 } — каждые N минут (мин 15, макс 1440)
  • { \"type\": \"daily\", \"time\": \"09:00\" } — ежедневно в указанное время
  • { \"type\": \"weekly\", \"day\": \"mon\", \"time\": \"09:00\" } — еженедельно
  • { \"type\": \"weekdays\", \"time\": \"08:30\" } — с понедельника по пятницу
  • { \"type\": \"daysOfWeek\", \"days\": [\"mon\", \"wed\", \"fri\"], \"time\": \"10:00\" } — в конкретные дни
  • { \"type\": \"monthly\", \"dayOfMonth\": 1, \"time\": \"09:00\" } — ежемесячно
  • { \"type\": \"manual\" } — только при запуске через API

Запустить триггер вручную:

POST /v1/triggers/{id}/fire

Возвращает 202 с threadId для созданного запуска.

Обновить или удалить:

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

Вебхуки

Триггеры вебхуков позволяют внешним сервисам (CI/CD, мониторинг, конструкторы форм) запускать агента через HTTP.

Создание триггера вебхука:

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

{
  "name": "Deploy hook",
  "prompt": "Произошел деплой: {{webhook.body}}",
  "modeId": "general",
  "kind": "webhook"
}

Возвращает 201 с webhookSecret и webhookPath. Сохраните секрет — он понадобится для подписи полезной нагрузки.

Отправка вебхука:

# Вычисление HMAC-SHA256 необработанного тела запроса
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"}

Конечная точка вебхука НЕ требует bearer-авторизации — вместо этого используется проверка HMAC. Возвращает 202 с threadId запущенного процесса. Плейсхолдер {{webhook.body}} в промпте триггера заменяется необработанным телом запроса.

Триггеры сообщений

Триггеры сообщений срабатывают, когда подключенный адаптер мессенджера (например, интеграция со Slack или Discord, установленная через Community Hub) получает входящее сообщение, соответствующее фильтру триггера. Создается с параметром kind: "messaging":

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

{
  "name": "Mention responder",
  "prompt": "Ответь вежливо на: {{message.text}}",
  "modeId": "general",
  "kind": "messaging",
  "messagingAdapterId": "slack-team-acme",
  "messagingChannelFilter": "#support"
}

Адаптер отвечает за отправку соответствующих событий в триггер; messagingChannelFilter зависит от конкретного адаптера.

Пользовательские функции

Создавайте собственные инструменты, которые могут вызывать агенты. Функции пишутся на JavaScript или Python и выполняются в песочнице.

Список функций:

GET /v1/functions

Создание функции:

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

{
  "name": "calculate_bmi",
  "description": "Рассчитать индекс массы тела по росту и весу",
  "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"]
  }
}

Функции JavaScript получают input и должны возвращать результат. Функции Python устанавливают переменную result:

# Пример на Python
result = {"bmi": round(input["weightKg"] / (input["heightM"] ** 2), 1)}

Прямое выполнение функции:

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

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

Безопасность: JavaScript выполняется в песочнице Node vm (без доступа к файловой системе или сети, таймаут 10с). Python выполняется как подпроцесс с таймаутом 30с. Оба варианта проверяют ввод перед выполнением.

Обновление или удаление:

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

Навыки

Навыки — это сохраненные промпты, на которые агенты могут ссылаться и которые можно быстро запускать из окна нового чата. Навыки, установленные из Hub (через установку пакетов), здесь НЕ отображаются — перечисляются и редактируются только созданные пользователем навыки.

Список навыков:

GET /v1/skills

Возвращает { skills: [...] } созданных пользователем навыков для активного профиля. Удаленные, наложенные из Hub и теневые навыки синхронизации отфильтрованы.

Получить один навык:

GET /v1/skills/{id}

Создать навык:

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

{
  "prompt": "Сделай краткое резюме страницы в 3 пунктах.",
  "tags": ["utility", "summarize"],
  "isFavorite": true,
  "modes": ["general"],
  "displayName": "Быстрое резюме",
  "description": "TL;DR активной страницы в трех пунктах"
}

Обязательным является только поле prompt. Поле modes (необязательно) ограничивает навык конкретными ID агентов; пропустите для всех режимов. Возвращает 201 с новым навыком (включая назначенные сервером id, createdAt, updatedAt).

Обновить навык:

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

{ "prompt": "Обновленный промпт", "isFavorite": false }

Поля для обновления: prompt, tags, modes, displayName, description, isFavorite. Попытки обновить навыки, наложенные из Hub, возвращают 404.

Удалить навык:

DELETE /v1/skills/{id}

Мягкое удаление через пометку. Возвращает 204. Для навыков из Hub возвращает 404 — вместо этого удалите исходный пакет.

Ворклоу (Рабочие процессы)

Организуйте работу нескольких агентов в виде DAG (направленного ациклического графа) — запускайте шаги параллельно, где это возможно, и передавайте выходные данные предыдущих шагов в последующие.

Валидация графа ворклоу:

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

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Исследовать тенденции в возобновляемой энергетике" },
      { "id": "analyze", "agentId": "general", "prompt": "Изучить цены конкурентов" },
      { "id": "report", "agentId": "general", "prompt": "Написать отчет, объединяющий: {{outputs.research}} и {{outputs.analyze}}", "dependsOn": ["research", "analyze"] }
    ]
  }
}

Возвращает { valid: true/false, errors: [...] }. Проверяет на наличие циклов, дублирующихся ID и отсутствующих ссылок на зависимости.

Выполнение ворклоу:

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

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Исследовать тенденции в возобновляемой энергетике" },
      { "id": "summarize", "agentId": "general", "prompt": "Обобщить: {{outputs.research}}", "dependsOn": ["research"] }
    ]
  }
}

Возвращает { status: "completed", outputs: { research: "...", summarize: "..." }, nodeResults: {...} }.

Независимые узлы (без общих зависимостей) запускаются параллельно. Плейсхолдер {{outputs.nodeId}} в промпте узла заменяется текстовым выводом указанного вышестоящего узла. Каждый узел — это полноценный запуск агента, поэтому он может использовать инструменты, просматривать веб-страницы и иметь доступ ко всем возможностям целевого агента.

Базы знаний

Организуйте документы в коллекции с возможностью поиска, на которые могут ссылаться агенты.

Список баз знаний:

GET /v1/knowledge/bases

Создание базы знаний:

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

{ "name": "Научные статьи" }

Возвращает 201 с ID новой базы.

Загрузка документа в базу знаний:

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

{
  "fileName": "research-paper.pdf",
  "contentType": "application/pdf",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ...",
  "description": "Тенденции возобновляемой энергетики 2026"
}

Поле dataUrl представляет собой URL-адрес данных в кодировке base64. Возвращает 201 с метаданными документа.

Список документов в базе знаний:

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

Поиск внутри базы знаний:

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

{ "query": "возобновляемая энергия" }

Возвращает подходящие документы на основе имени файла и описания. Семантический (векторный) поиск появится в будущем выпуске.

Удаление документа или базы знаний:

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

Экспорт и импорт агентов

Делитесь агентами как переносимыми пакетами — между устройствами, командами или через Community Hub.

Экспорт агента:

POST /v1/agents/{id}/export

Возвращает JSON-пакет с определением агента, требованиями к инструментам, коннекторам и шаблонами триггеров. Метаданные синхронизации удаляются — пакет представляет собой чистый чертеж.

Импорт агента:

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

{
  \"package\": {
    \"$schema\": \"caiioo.agent.package/v1\",
    \"agent\": {
      \"id\": \"shared-research-agent\",
      \"branding\": { \"name\": \"Research Agent\", \"description\": \"От команды\" },
      \"defaultSettings\": { \"systemPrompt\": \"Вы исследуете вещи.\" },
      \"settingLevels\": {}
    },
    \"toolRequirements\": [
      { \"toolId\": \"web_browsing\", \"enabled\": true },
      { \"toolId\": \"search_tools\", \"enabled\": true }
    ]
  }
}

Возвращает 201. Конфликты ID со встроенными или существующими агентами возвращают 409.

Обработка ошибок

API использует стандартные коды состояния HTTP:

Код Значение
200 Успешно
201 Создано
202 Принято (асинхронная операция запущена)
204 Удалено (нет содержимого)
400 Неверный запрос — проверьте поле error для подробностей
401 Не авторизован — отсутствует или невалиден секрет сессии
403 Запрещено — например, попытка изменить встроенного агента
404 Не найдено
409 Конфликт — например, ID агента уже существует
422 Ошибка валидации — входные данные не соответствуют схеме инструмента
429 Превышен лимит запросов — см. бюджеты лимитов в разделе Аутентификация
500 Ошибка сервера — проверьте поле error
501 Не реализовано — функция существует, но недоступна этим способом
503 Сервис недоступен — хранилище или провайдер не готовы

Все ответы с ошибками включают { "error": "человекочитаемое сообщение" }.

Пример быстрого старта

Вот полный рабочий процесс: создание агента, его запуск и стриминг результатов.

# 1. Создание пользовательского агента
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": "Кратко обобщи любой ввод в виде 3 пунктов.",
      "enabledTools": { "web_browsing": true }
    },
    "settingLevels": {}
  }'

# 2. Асинхронный запуск
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": "Обобщи https://en.wikipedia.org/wiki/Artificial_intelligence" }, "mode": "async" }')

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

# 3. Стриминг событий
curl -N http://localhost:3847/v1/runs/$RUN_ID/events \
  -H "Authorization: Bearer $API_TOKEN"

# 4. Экспорт агента для совместного использования
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.