API облачных агентов
Создавайте агентов, ставьте им задачи и забирайте результат прямо из своего кода — из CI, внутреннего сервиса или бота.
Облачный агент Kodagent — это кодинг-агент на отдельной изолированной машине. Он берёт задачу, работает с вашим репозиторием или файлами и возвращает merge request, патч или архив. Через API ваш код делает с агентами всё то же, что консоль: создаёт и запускает их, пишет им, ставит на паузу и будит, завершает, читает транскрипт, скачивает результат и удаляет.
Агенты, созданные через API, ничем не отличаются от созданных в консоли. Они видны в разделе Консоль → Агенты, их работа оплачивается с баланса организации, и вести их можно из любой двери: API, консоли или Telegram.
- Базовый URL:
https://kodagent.ru/api/v1 - Формат: JSON в запросах и ответах. Ошибка — HTTP-статус и тело
{"error": "описание"}. - Авторизация: заголовок
Authorization: Bearer <API-ключ>с ключом, которому открыт доступ к агентам.
Авторизация
API принимает обычные API-ключи Kodagent, но только те, у которых включён доступ к API агентов. По умолчанию ключ умеет только обращаться к моделям. Открыть ему агентов можно в Консоль → API-ключи: переключатель «Доступ к API агентов» есть при создании ключа и в его настройках.
Ключ действует от имени своего владельца — с его ролью и в его организации. Ключи создают
администраторы организации, поэтому обычно ключу доступно всё. Если владельца позже перевели в
участники (member или viewer), ключ сможет только читать: создание агентов и управление ими
будут отвечать 403. Если владельца заблокировали, ключ сразу перестаёт работать. Отозванный
ключ получает 401 со следующего же запроса.
Такой ключ запускает машины и тратит кредиты, поэтому храните его только на сервере — не в браузере и не в мобильном приложении. Лимиты расходов ключа считают его собственные запросы к моделям. Расходы агентов ограничены их собственными бюджетами, которые вы задаёте при создании, а также балансом организации.
Быстрый старт
Создайте агента с задачей. Ответ придёт сразу, а машина стартует в фоне: на нашем железе — за секунду, на арендованной облачной ВМ — за пару минут.
export KODAGENT_API_KEY="sk-..."
curl -s https://kodagent.ru/api/v1/agents \
-H "Authorization: Bearer $KODAGENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"source_kind": "git",
"source_url": "https://github.com/acme/api",
"source_token": "ghp_...",
"prompt": "Обнови зависимости и почини тесты, которые после этого упадут",
"budget_credits": 300
}'
В ответе — агент и его первый запуск:
{
"id": "8f1c2e4a-…",
"handle": "irina-volkova",
"display_name": "Ирина Волкова",
"status": "active",
"latest_run": { "id": "41d27b90-…", "status": "provisioning", "budget_micro": 300000000, "…": "…" },
"runs": [ { "id": "41d27b90-…", "…": "…" } ],
"total_spent_micro": 0
}
Следите за работой в реальном времени — это поток Server-Sent Events с транскриптом запуска:
curl -N "https://kodagent.ru/api/v1/agents/$AGENT_ID/runs/$RUN_ID/stream?after=0" \
-H "Authorization: Bearer $KODAGENT_API_KEY"
data: {"seq":1,"kind":"user","payload":{"text":"Обнови зависимости…"},"created_at":"…"}
data: {"seq":2,"kind":"status","payload":{"state":"running","detail":"init"},"created_at":"…"}
data: {"seq":3,"kind":"assistant","payload":{"text":"Посмотрю, какие зависимости устарели."},"created_at":"…"}
Когда агент закончит ход (событие result), ответьте ему или дайте следующую задачу:
curl -s "https://kodagent.ru/api/v1/agents/$AGENT_ID/messages" \
-H "Authorization: Bearer $KODAGENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Отлично. Теперь обнови раздел об установке в README"}'
Когда работа принята, завершите агента. Он закоммитит изменения, запушит ветку
kodagent/agent-<id> и откроет merge request. Ссылка на него появится в latest_run.result_url.
curl -s -X POST "https://kodagent.ru/api/v1/agents/$AGENT_ID/stop" \
-H "Authorization: Bearer $KODAGENT_API_KEY"
Основные понятия
Агент
Агент — постоянная сущность с именем (display_name), адресом (handle, например
irina-volkova) и ролью (role). Он переживает свои машины: каждая работа агента — это
запуск на отдельной машине, а между запусками сохраняются рабочая копия и весь разговор.
Поле status агента:
| Статус | Что значит |
|---|---|
active | идёт запуск: машина работает |
paused | агент на паузе: работа сохранена, машина освобождена. Сообщение или resume разбудят его |
finished | агент завершён. Если can_resume равно true, его можно вернуть к работе сообщением или resume |
Агент, который ждёт сообщения дольше таймаута простоя, сам встаёт на паузу с сохранением. Ваше следующее сообщение продолжит работу с того же места.
Агента на паузе будят и письма — от коллег, расписаний и вебхуков. Если разбудить не выходит
(бюджет меньше часа работы машины, кончился баланс, заняты все места для агентов), в
wake_error написано почему, а в wake_error_at — с какого времени; пока агенту ничего не
мешает, оба поля равны null. Платформа пробует снова каждую минуту.
Запуск
Запуск (run) — одна машина и всё, что агент на ней сделал. У каждого запуска свои транскрипт,
бюджет, расходы и результат. Пауза и возобновление создают новый запуск, поэтому текущий берите
из latest_run в ответе.
Поле status запуска:
| Статус | Что значит |
|---|---|
provisioning | машина создаётся |
running | агент работает |
idle | агент закончил ход и ждёт сообщения |
stopping | идёт остановка: доставка результата и сохранение |
stopped | запуск закончен |
failed | запуск закончился ошибкой — подробности в error |
Результат запуска:
result_kind:mr(ссылка вresult_url),branch(ветка вresult_branch),s3илиyadisk.has_patch: есть ли патч с изменениями относительно исходного состояния. Патч сохраняется всегда, что бы ни случилось.has_archive: есть ли zip с рабочей копией. Его получает каждый запуск на пустой рабочей копии (blank).
События транскрипта
Каждое событие — это {"seq", "kind", "payload", "created_at"}. Номер seq растёт внутри
запуска, и по нему читают продолжение (?after=<seq>).
kind | payload | Что это |
|---|---|---|
user | text | сообщение агенту — из API, консоли или Telegram |
assistant | text | реплика агента |
thinking | text | рассуждение модели, если она его показывает |
tool_use | id, name, input | вызов инструмента: команда, правка файла, MCP |
tool_result | tool_use_id, is_error, content | результат вызова |
status | state, detail | служебная отметка жизненного цикла |
error | detail | ошибка на машине |
result | subtype, is_error, text | агент закончил ход и ждёт сообщения |
События субагентов несут parent_tool_use_id — идентификатор вызова, который их породил.
Деньги и лимиты
- 1 кредит = $0,01. Цены в рублях — по текущему курсу, см. страницу тарифов. Суммы
в полях
*_microуказаны в микрокредитах: 1 кредит = 1 000 000. - Машина оплачивается поминутно. При старте блок машинного времени (час) удерживается авансом, а неиспользованные минуты возвращаются на баланс при остановке. Токены списываются по ценам каталога моделей.
- У каждого запуска есть два потолка: бюджет и срок. Вы выбираете, чем управлять
(
limit_kind), но второй потолок действует всегда. - Если баланса не хватает на первый блок, API ответит
402. Если заняты все слоты одновременных агентов организации —409.
Безопасность интеграции
- Задача и сообщения — это указания от имени владельца ключа. Агент выполняет их со всеми
его полномочиями: с токенами рабочей копии, MCP-серверами организации и почтой коллегам. Не
передавайте в
promptиmessagesнепроверенный текст своих пользователей как есть: такой текст может попросить агента сделать всё, что умеет сам агент. Для задач, которые формулируют ваши пользователи, берите пустую рабочую копию (blank) без токенов, не сохраняйте учётные данные и задавайте небольшой бюджет. - Состояние запуска берите из
latest_run.status. Его ведёт платформа, а события транскрипта пишет машина агента. Решения вроде «работа закончена» стройте на статусе, а не на тексте событий. - Не кладите токены в
source_url. Адрес виден всем, кто может читать агента, поэтому URL с учётными данными (https://user:token@host/…) API не примет: передайте токен вsource_token. - Ключи запусков агентов для API не подходят. Платформа выдаёт каждому запуску свой ключ к моделям. Такие ключи видны в списке ключей, но доступа к API агентов у них не бывает, и изменить их нельзя.
Справочник
Модели — GET /v1/models
Каталог моделей. Агенту подходят модели с "agent_capable": true. Ещё можно выбрать свой гибрид
hybrid/<название>, если обе его модели подходят агентам.
[{ "slug": "glm-5.3", "display_name": "GLM-5.3", "agent_capable": true,
"input_price_micro": 140, "output_price_micro": 440, "…": "…" }]
Список агентов — GET /v1/agents
| Параметр | |
|---|---|
q | поиск по адресу, имени, роли, названию последнего запуска или началу id |
status | active, paused или finished |
limit | от 1 до 200, по умолчанию 50 |
offset | смещение для постраничного чтения |
Ответ — массив агентов с последним запуском в latest_run.
Создать агента — POST /v1/agents
Создаёт агента и сразу запускает его с задачей. Ответ — 201 и агент со списком запусков.
| Поле | Тип | |
|---|---|---|
prompt | string, обязательно | задача, до 32 000 символов. Длинные логи передавайте файлом |
source_kind | string, обязательно | рабочая копия: git, blank, s3 или yadisk |
source_url | string | git: https-адрес репозитория или ссылка на открытый PR/MR (агент обновит его, а не создаст новый). s3: s3://bucket/prefix. yadisk: путь к папке, например disk:/Projects/app |
source_ref | string | ветка или коммит для git |
source_token | string | токен для приватного репозитория |
s3_endpoint, s3_access_key, s3_secret_key | string | доступ к S3-совместимому хранилищу |
yadisk_token | string | OAuth-токен Яндекс Диска, обязателен для yadisk |
input_archive_base64 | string | zip со стартовыми файлами для blank, до 32 МБ |
model_slug, small_model_slug | string | модель агента и модель для его фоновых вызовов |
effort | string | low, medium, high, xhigh или max |
speed | string | fast — микро-ВМ на нашем железе, slow — арендованная облачная ВМ. По умолчанию — быстрая, если доступна. Недоступный вариант не подменяется другим: API ответит 400 |
limit_kind | string | credits (по умолчанию) или hours |
budget_credits | integer | бюджет запуска в кредитах (для credits) |
limit_hours | integer | длительность запуска в часах (для hours) |
deliver_on_limit | boolean | доставлять результат, даже если запуск остановил лимит. По умолчанию — только патч |
display_name, handle, role | string | имя, адрес и роль. Если не указаны, имя и адрес придумываются |
locale | string | ru или en: из каких имён выбирать придуманное |
remember_credentials | boolean | сохранить токены рабочей копии (зашифрованными) для следующих запусков, чтобы будить и завершать агента без них |
title | string | название запуска |
Учётные данные рабочей копии не записываются в базу: машина забирает их один раз при старте.
Исключение — remember_credentials: тогда они хранятся зашифрованными.
Агент — GET /v1/agents/{id}
Агент со всеми запусками (runs, от старых к новым) и общей стоимостью total_spent_micro.
Изменить агента — PATCH /v1/agents/{id}
Меняет display_name, handle и role. Переданные поля меняются, остальные остаются как были.
Удалить агента — DELETE /v1/agents/{id}
Удаляет агента, его запуски и сохранённое состояние. Ответ — 204. Работающего агента сначала
остановите или поставьте на паузу, иначе ответ будет 409.
Написать агенту — POST /v1/agents/{id}/messages
{ "text": "Теперь добавь тесты на этот модуль" }
Работающий агент получит сообщение сразу. Агент на паузе или завершённый, но с сохранённой
работой, проснётся с этим сообщением в новом запуске. Ответ — 202 и агент: новый запуск
будет в latest_run. Длина сообщения — до 32 000 символов.
Передать файл — POST /v1/agents/{id}/files
{ "filename": "spec/requirements.docx", "content_base64": "UEsDB…", "message": "Сделай форму по этой спеке" }
Кладёт файл в рабочую копию работающего агента (до 32 МБ). Сообщение message придёт агенту
после того, как файл окажется на диске. Ответ — 202 и {"path": "…"}. Если агент не
работает, ответ будет 409: сначала разбудите его сообщением. Пока агент не забрал предыдущие
файлы, в очереди может ждать не больше 20 файлов общим объёмом до 64 МБ — сверх этого тоже
409.
Прервать текущий шаг — POST /v1/agents/{id}/interrupt
Агент бросает текущий шаг, но запуск продолжается, и можно сразу написать, что делать вместо
этого. Ответ — 202.
Пауза — POST /v1/agents/{id}/pause
Сохраняет рабочую копию и разговор и освобождает машину. Результат при этом не доставляется. Неиспользованные минуты возвращаются на баланс.
Разбудить — POST /v1/agents/{id}/resume
Запускает агента на паузе или завершённого агента из сохранённого состояния. Тело необязательно:
| Поле | |
|---|---|
message | что сказать агенту при пробуждении. Без сообщения он продолжит с того места, где остановился |
model_slug, small_model_slug, effort, speed | другие настройки для нового запуска |
limit_kind, budget_credits, limit_hours, deliver_on_limit | новые лимиты |
source_token, s3_endpoint, s3_access_key, s3_secret_key, yadisk_token, remember_credentials | учётные данные рабочей копии, если они не были сохранены |
Всё, что не передано, берётся из предыдущего запуска.
Завершить — POST /v1/agents/{id}/stop
Завершает работу: агент доставляет результат (MR или ветку в репозиторий, синхронизацию в S3
или на Диск, архив для blank), сохраняется и останавливается. Агента на паузе разбудит
короткий запуск, который только доставит результат. Если токены не были сохранены, передайте их
в теле, как в resume. Повторный вызов для уже завершающегося агента ничего не ломает.
Транскрипт — GET /v1/agents/{id}/runs/{run}/events
| Параметр | |
|---|---|
after | вернуть события с seq больше этого номера, по умолчанию 0 |
limit | до 500 событий за раз |
Ответ — массив событий по возрастанию seq. Одна страница вмещает до 4 МБ событий, поэтому
крупных событий в ней может оказаться меньше limit — продолжайте с последнего seq.
Поток событий — GET /v1/agents/{id}/runs/{run}/stream
Тот же транскрипт как Server-Sent Events. Каждое событие приходит строкой data: {…}. Когда
запуск закончится, придёт event: end с {"status": "…"}, и соединение закроется. Между
событиями сервер шлёт комментарии : keepalive. Одно соединение живёт до 30 минут: переподключайтесь
с ?after=<последний seq> — пропусков и повторов не будет. У организации может быть открыто
не больше 20 потоков одновременно, на следующий API ответит 429. Если ключ отозвали или
закрыли ему доступ к агентам, поток закроется на ближайшей проверке — не позже чем через 15
секунд.
Патч — GET /v1/agents/{id}/runs/{run}/patch
Изменения запуска относительно исходного состояния в формате git diff (text/x-patch). Его
можно сразу применить через git apply. Если изменений нет, ответ будет 404.
Архив — GET /v1/agents/{id}/runs/{run}/archive
Рабочая копия запуска в zip (application/zip). Архив есть у каждого запуска на blank.
Пример: агент в вашем сервисе
Скрипт на Python ставит задачу, печатает ответы агента до конца хода, просит доработку и завершает работу.
import time
import requests
API = "https://kodagent.ru/api/v1"
s = requests.Session()
s.headers["Authorization"] = "Bearer sk-..."
def wait_turn(agent_id, run_id, after=0):
"""Печатает ответы агента, пока он не закончит ход. Возвращает курсор."""
while True:
events = s.get(f"{API}/agents/{agent_id}/runs/{run_id}/events",
params={"after": after}).json()
for ev in events:
after = ev["seq"]
if ev["kind"] == "assistant":
print(ev["payload"]["text"])
elif ev["kind"] == "result":
return after
if not events:
run = s.get(f"{API}/agents/{agent_id}").json()["latest_run"]
if run["status"] in ("stopped", "failed"):
raise RuntimeError(run.get("error") or "запуск закончился")
time.sleep(2)
agent = s.post(f"{API}/agents", json={
"source_kind": "git",
"source_url": "https://github.com/acme/api",
"source_token": "ghp_...",
"prompt": "Добавь тесты на модуль billing и почини то, что они найдут",
"budget_credits": 300,
}).json()
agent_id, run_id = agent["id"], agent["latest_run"]["id"]
cursor = wait_turn(agent_id, run_id)
s.post(f"{API}/agents/{agent_id}/messages", json={"text": "Теперь опиши изменения в CHANGELOG"})
wait_turn(agent_id, run_id, cursor)
s.post(f"{API}/agents/{agent_id}/stop")
Если агент успел уснуть между сообщениями, ответ на messages вернёт новый запуск в
latest_run, и читать нужно его.
Ошибки
| Статус | Когда |
|---|---|
400 | неверные параметры: неизвестный source_kind, бюджет вне допустимых пределов, недоступная скорость, токен в source_url, слишком длинная задача, неверный JSON и т. п. Текст ошибки объясняет, что не так |
401 | нет ключа, ключ неизвестен или отозван, владелец ключа заблокирован |
402 | на балансе не хватает кредитов на первый блок машинного времени |
403 | у ключа нет доступа к API агентов, или его владелец больше не администратор организации и ему доступно только чтение |
404 | агент или запуск не найден — в том числе чужой |
409 | действие не подходит к состоянию агента: он уже работает, ещё работает, заняты все слоты организации или в очереди слишком много файлов |
429 | у организации уже открыто 20 потоков событий |
503 | API агентов или сами агенты сейчас недоступны |
Что ещё стоит знать
- Свои MCP-серверы организации, заданные в консоли (Консоль → Агенты), получают и агенты, созданные через API.
- Через API пока нельзя собирать проекты и команды агентов. Одобрения, которые запрашивают агенты, решаются в консоли или в Telegram.
- Чтобы событие из CI или CRM ставило задачу уже существующему агенту без кода на вашей стороне, используйте вебхуки в разделе Консоль → Автоматизация.
- Изоляция, сетевой журнал и проверка поведения агентов работают так же, как в консоли. Подробнее — в статье «Как мы защищаем облачных агентов».