Справочник инструментов#

Агент разговаривает с платформой инструментами MCP. Наборов два, и живут они на разных адресах: ученический — <адрес сервиса>/mcp, кураторский — <адрес сервиса>/authoring. Токен у них один и тот же; что человеку доступно, решают роли во Frappe, а не выбор адреса.

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

Раздел устроен одинаково: назначение, параметры, что приходит в ответ и отказы, которые возвращает именно этот метод. Общие правила отказов — в конце страницы.

Обзор#

Инструменты ученика — их получает агент, который ведёт занятие.

Инструмент Назначение
artifact прочитать документы курса ученика — перечень или один целиком
choose предложить ученику выбор кнопками
complete_lesson закрыть урок, у которого нет обязательной проверки знаний
course_outline программа курса: главы, уроки, цели уроков со статусами
enroll записать ученика на курс из каталога
forget удалить заметку об ученике по ключу
get_my_progress сводка по ученику: курсы, просрочки, последние занятия
lesson_item подробности пункта урока по ключу
list_catalog курсы, на которые ученик может записаться сам, и анонсы
list_my_courses курсы ученика с прогрессом и дедлайнами
mark_goal отметить разобранный пункт урока со свидетельством
my_homework домашние задания ученика: статус, срок, комментарий куратора
my_notes показать ученику, что о нём запомнено
my_reports репорты ученика: статус и ответ автора
notify_when_released подписать ученика на письмо о выходе анонсированного курса
org_report отчёт по обучению своей организации (для руководителя)
remember запомнить об ученике то, что пригодится дальше
report_issue сообщить авторам курса, что мешает учиться
request_quiz начать проверку знаний и получить первый вопрос
start_lesson начать занятие: карта урока, указания агенту, с чего начать
store_homework_file сдать файлы из окна домашнего задания (зовёт окно, не модель)
student_detail подробности по одному сотруднику (для руководителя)
submit_answer отправить ответ ученика и получить вердикт
submit_homework сдать или поправить текст домашнего задания
update_artifact записать раздел документа курса: строки или поля
upload_homework_file показать ученику окно сдачи файлов домашнего задания
whoami под какой учётной записью вошёл ученик

Инструменты куратора — ими агент работает с курсом вместе с куратором: смотрит релиз, публикует курс, ведёт заметки и репорты. Сам курс меняется только новым релизом — командой конвейера, не этими инструментами.

Инструмент Назначение
add_note задать куратору вопрос на месте релиза
announce_course показать курс в каталоге как анонс, до выхода
course_notes заметки куратора по ключам релиза
course_release действующий релиз курса — с ответами квиза и пакетом агента урока
course_releases история релизов курса: версии, даты, какой действует
course_reports репорты агентов учеников о курсе
create_course завести курс до первого релиза — для анонса
goal_runs прохождения учеников: уроки, цели, отмеченные пункты со свидетельствами
list_courses курсы платформы, их ключи и действующие релизы
publish_course открыть курс из релиза ученикам
reply_note ответить в нить заметки
resolve_note отметить заметку сделанной и сказать, что поменялось
resolve_report сменить статус репорта и ответить ученику, что сделано
unpublish_course убрать курс из каталога
update_course поправить название и описания анонса

Инструменты ученика#

Этот набор получает агент, подключённый к ученическому адресу /mcp. Он же работает в веб-чате платформы: маршрут занятия там тот же, и различает каналы сама платформа, а не набор инструментов.

Здесь же лежат два инструмента отчётности — org_report и student_detail. Их видит всякий подключившийся, и это осознанно: данные закрыты правами, у не-руководителя отчёт пуст.

Пространства. У ученика одна учётная запись, а курсы и документы разложены по пространствам: личному и каждой организации, где он состоит. Прогресс общий: урок, пройденный лично, пройден и для компании. Документ у каждого пространства свой — один курс может дать два документа. Ученик выбирает пространство в интерфейсе платформы или просит агента (set_space); инструменты списков работают в выбранном, а инструменты курса — в пространстве начатого занятия по этому курсу, иначе в выбранном. Параметр space называет пространство явно; пространство, которого у ученика нет, — отказ space_not_available, курса в названном пространстве нет — course_not_in_space.

Занятие по цепочке. Агент открывает урок start_lesson: в ответе — карта урока (цели и их пункты со статусами), указания автора агенту и опора для объяснения, рамка курса, что известно об ученике и с чего начать. Подробности пункта агент берёт lesson_item, когда дошёл до него, а разобранный пункт сразу отмечает mark_goal со свидетельством — что ученик сделал или сказал. Когда обязательные пункты закрыты, урок проверяет квиз (request_quiz, submit_answer), а урок без обязательного квиза закрывает complete_lesson. Правила ведения приходят тремя пакетами: «старт и разбор» — в ответе start_lesson, «квиз» — в request_quiz, «закрытие» — в последнем ответе квиза и в complete_lesson. Поле next в ответах start_lesson, lesson_item, mark_goal и квиза называет следующий шаг. В веб-чате все три пакета стоят в системных инструкциях, и в ответах их нет.

Пункты урока и свидетельства видят агент и авторы курса — чтобы улучшать курс (goal_runs). Ученику и руководителю платформа показывает цели урока и их статусы: на странице курса, в course_outline, в шапке веб-чата и в student_detail. Занятие с агентом идёт по курсу, выпущенному релизом; у другого курса методы занятия отказывают course_not_released.

Домашнее задание. У урока может быть задание от автора — одно на всех учеников. Ученик получает его, когда урок закрыт, и сдаёт текстом, файлами или тем и другим — как задал автор: агенту (submit_homework, upload_homework_file) или на странице урока. Каждое сохранение — новая версия ответа, и куратор видит все. На зачёт урока домашка не влияет. Сдача живёт в пространстве, как документ: занятие в организации даёт сдачу, которую видит её руководитель, личное — личную.

Идентификаторы курсов, уроков и занятий агент между сессиями не помнит. Он берёт их из ответов: курс — из списка курсов, урок — из программы курса, занятие и попытку — из ответа на начало занятия и на запрос проверки знаний.

artifact#

Показывает агенту документы, которые ученик собирает по ходу курса, — список или один документ целиком.

Параметры

  • course — идентификатор курса. Обязательный.
  • artifact — ключ документа (например agreements_log). Необязательный; без него приходит перечень.
  • space — чей документ: организация или personal. Необязательный; без него — пространство начатого занятия по курсу, иначе выбранное. В ответе space — чей прочитан.

В ответе. Без ключа — перечень документов курса: ключ, название, зачем документ ученику, сколько разделов всего и сколько заполнено. С ключом — документ по разделам, в порядке, который задал автор курса.

Раздел бывает двух видов — rows:

  • many — раздел ведётся строками, как журнал: строка — одна договорённость, один риск. Строки приходят в items, у каждой — id (A1, A2…) и заполненные клетки.
  • one — раздел заполняется один раз, как анкета: его колонки — поля. Значения приходят в values.

Пустые клетки не приходят. У раздела есть columns — колонки (у one — поля) с названием и обязательностью required: true — обязательна, false — нет, {"if_column": "driver"} — обязательна, когда заполнена названная колонка той же строки (у раздела one — поле того же раздела). description — что записывают в раздел, словами для ученика: он видит его на странице «Мои документы». lesson — урок, на котором раздел обычно собирают.

filled — раздел готов: у many есть строки и у каждой заполнены обязательные колонки, у one непусто хоть одно поле и все обязательные. empty_cells — каких обязательных клеток не хватает: row и column у many, field у one.

{ "key": "agreements", "title": "Договорённости",
  "description": "Что сюда записывают", "lesson": "<id урока>", "rows": "many",
  "columns": [ { "key": "topic", "title": "Тема", "required": true },
               { "key": "area", "title": "Область",
                 "required": { "if_column": "driver" } } ],
  "items": [ { "id": "A1", "topic": "Ретро раз в две недели" } ],
  "filled": true, "empty_cells": [] }

Отказы

  • not_enrolled — ученик не зачислен на курс; курс ему открывать нечем.
  • organization_suspended — организация ученика приостановлена; зачисление цело, доступ вернётся вместе со статусом.
  • artifact_not_found — в курсе нет документа с таким ключом; посмотрите перечень вызовом без ключа.

Пример просьбы. Ученик: «покажи, что у нас уже записано в журнале договорённостей».

choose#

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

Параметры

  • prompt — вопрос. Обязательный.
  • options — варианты, по кнопке на каждый. Обязательный.
  • title — заголовок карточки. Необязательный.

В ответе. Клиент, который умеет показывать интерфейс в чате (MCP Apps — Claude, ChatGPT и другие), рисует карточку с кнопками. Нажатая кнопка приходит в разговор репликой ученика ««вопрос» — выбираю: вариант». Клиент без MCP Apps кнопок не покажет, поэтому сервер отвечает ему текстом: задай этот вопрос словами. Агент не ждёт клика, которого не будет. В веб-чате платформы кнопки рисует сама страница.

После вызова агент заканчивает реплику и ждёт ответа. Ответ своими словами тоже засчитывается как выбор.

Отказы. Своих нет — только общие.

Пример просьбы. Отдельно просить не нужно: агент зовёт инструмент сам, когда нужен выбор из готовых вариантов.

complete_lesson#

Закрывает урок, у которого нет обязательной проверки знаний: квиза нет или он не обязателен по политике организации. Как и квиз — только когда закрыты все обязательные пункты урока.

Параметры

  • session — идентификатор занятия из ответа start_lesson. Обязательный.

В ответе. Идентификатор урока, статус занятия, следующий урок курса и empty_blocks — разделы документа этого урока, которые остались незаполненными. Урок закрывается и с ними; агент говорит ученику, что осталось дописать. teaching_rules — правила закрытия урока: домашнее задание, вопрос о том, помогло ли занятие, следующий урок.

Отказы

  • not_your_session — занятие принадлежит другому ученику.
  • session_closed (с полем status) — занятие уже закрыто или брошено; возвращаться к уроку нужно через start_lesson, он заведёт новое занятие.
  • goals_open — открыты обязательные пункты урока; в отказе — goals: [{objective, goal, title}]. Агент разбирает их и отмечает mark_goal.
  • quiz_required — у урока обязательная проверка знаний. Закрыть его можно только сдачей: этот инструмент не обход проверки, и зачёт ставит сервер.
  • not_enrolled, organization_suspended — доступ к курсу отозван.
  • course_not_released, lesson_not_in_release, run_archived, busy — см. отказы цепочки урока.

Пример просьбы. Ученик: «всё понятно, давай закроем урок».

course_outline#

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

Это единственный способ узнать идентификатор уже пройденного урока: start_lesson без аргумента ведёт только вперёд.

Параметры

  • course — идентификатор курса. Обязательный.

В ответе. Главы курса с описанием и прогрессом — сколько уроков начато и пройдено; в каждой — уроки с идентификатором (id), ключом, названием, зачином, признаком пройденного и отметкой текущего. У урока — его цели со статусами (not_started, touched, covered), разделы документа и домашнее задание. Пунктов целей здесь нет: они только в карте урока у агента. В programs — цепочки курсов (программы), в которые входит курс: место курса («2 из 3»), предыдущий и следующий курс, участник ли ученик. Если ученик участник цепочки с обязательным порядком, а предыдущий курс ещё не пройден, в locked_by приходит курс, который пройти раньше.

Инструмент только читает: прохождения уроков не заводит и не сверяет.

Отказы

  • not_enrolled — ученик не зачислен на курс.
  • organization_suspended — организация ученика приостановлена.
  • course_not_released — курс не выпущен релизом.

Пример просьбы. Ученик: «а что мы проходили в начале курса? хочу вернуться к главе про циклы».

enroll#

Записывает ученика на курс из каталога.

Параметры

  • course — идентификатор курса из list_catalog. Обязательный.
  • space — пространство: имя организации из whoami или personal. Необязательный; без него — выбранное учеником.

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

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

Отказы

  • course_not_published — курс ещё черновик.
  • course_upcoming — курс анонсирован и ещё готовится. Вместо записи — notify_when_released.
  • already_enrolled — ученик уже записан; курс есть в list_my_courses.
  • course_not_allowed — курс не открыт ни одной организации ученика.
  • program_order (с program, program_title и previous) — ученик участник программы, где курсы идут по порядку, а предыдущий курс ещё не пройден целиком. Сначала — курс из previous.

Пример просьбы. Ученик: «запиши меня на курс про переговоры».

fill_document#

Собирает с учеником документ курса, который он уже прошёл, — без повторного обучения. Нужен, когда курс пройден лично, а компания назначила его позже, или человек перешёл в другую компанию: прогресс у него общий, а документ для компании свой и пока пустой.

Параметры

  • course — идентификатор курса. Обязательный.
  • artifact — ключ документа. Необязательный; без него приходит перечень.
  • space — чей документ: организация из whoami или personal. Необязательный; без него — выбранное учеником.

В ответе. То же, что у artifact, и rules — правила заполнения для агента: не вести уроки заново, идти по незаполненным разделам в порядке документа, спрашивать о проекте этой организации, записывать словами ученика через update_artifact с тем же space. Ученику правила не зачитываются.

Веб-чат платформы этот режим не ведёт: он строится вокруг урока. Документ заполняют со своим агентом или вручную на странице документа.

Отказы. Как у artifact.

Пример просьбы. Ученик: «курс я уже проходил, давай заполним резюме проекта для компании».

forget#

Удаляет заметку об ученике по ключу.

Параметры

  • key — ключ заметки, например role или pace. Обязательный.
  • course — идентификатор курса для проекта или наблюдения, записанного при курсе. Необязательный; без него ищется заметка-факт.

В ответе. Удалённый ключ.

Отказы

  • note_not_found — заметки с таким ключом нет. Проверьте ключ по my_notes: проект и наблюдение ищутся вместе с курсом, факт — без него.

Пример просьбы. Ученик: «забудь, что я работаю в рознице, — я сменил работу».

get_my_progress#

Даёт сводку по ученику: сколько курсов, что просрочено, чем он занимался в последнее время.

Параметры

  • space — пространство: имя организации из whoami или personal. Необязательный; без него — выбранное учеником.

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

Отказы. Своих нет — только общие.

Пример просьбы. Ученик: «как у меня дела с обучением, много ли осталось?»

lesson_item#

Отдаёт подробности одного пункта урока — что разобрать с учеником и как понять, что он это умеет.

Карта урока в ответе start_lesson даёт только названия пунктов; подробности агент берёт, когда дошёл до пункта. Текст адресован агенту, ученику его не зачитывают.

Параметры

  • session — идентификатор занятия. Обязательный.
  • goal — ключ пункта из lesson_map, например term:T1. Обязательный.

В ответе. goal — ключ, вид, обязательный ли, название и статус пункта; details — подробности из пакета урока. Свидетельства отметки в ответе нет. У открытого пункта next — разобрать его и отметить mark_goal.

Инструмент только читает: прохождение урока не заводит и не сверяет.

Отказы

  • not_your_session — занятие принадлежит другому ученику.
  • goal_unknown — в уроке нет такого пункта или он снят новым релизом курса; в отказе — ключи пунктов урока.
  • not_enrolled, organization_suspended — доступ к курсу отозван.
  • course_not_released, lesson_not_in_release — см. отказы цепочки урока.

Пример просьбы. Отдельно просить не нужно: агент берёт подробности, когда доходит до пункта.

list_catalog#

Показывает курсы, на которые ученик может записаться сам.

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

Параметры

  • space — пространство: имя организации из whoami или personal. Необязательный; без него — выбранное учеником.

Здесь же анонсы — курсы, которые готовятся: записаться на них нельзя, можно попросить сообщить о выходе.

В ответе. Список курсов: идентификатор, название, краткое описание для карточки и upcoming — анонс ли это. У анонса ещё objectives — цели курса, о которых агент расскажет, — и notify: подписан ли ученик на письмо о выходе. Срока выхода в ответе нет, и агент его не называет.

programs — цепочки курсов (программы), в которые входит курс: место курса («2 из 3»), предыдущий и следующий курс, участник ли ученик. Если ученик участник цепочки с обязательным порядком, а предыдущий курс ещё не пройден, в locked_by приходит курс, который пройти раньше. Запертый курс агент не предлагает, а называет тот, что пройти раньше: запись на запертый откажет program_order.

Отказы. Своих нет — только общие.

Пример просьбы. Ученик: «что ещё есть на платформе, чему можно поучиться?»

list_my_courses#

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

Параметры

  • space — пространство: имя организации из whoami или personal. Необязательный; без него — выбранное учеником.

В ответе. Пространство (space) и курсы. В личном — все курсы ученика, в пространстве организации — назначенные ею или взятые из её каталога. По каждому курсу: название, организация, признак обязательности, дедлайн и просрочка, число уроков и пройденных, следующий урок. У ученика, записавшегося самостоятельно, поля назначения пустые.

programs — цепочки курсов (программы), в которые входит курс: место курса («2 из 3»), предыдущий и следующий курс, участник ли ученик. Если ученик участник цепочки с обязательным порядком, а предыдущий курс ещё не пройден, в locked_by приходит курс, который пройти раньше. Курс пройден — агент предлагает следующий курс цепочки.

Курсы приостановленной организации в список не попадают, а зачисление на них сохраняется.

Отказы. Своих нет — только общие.

Пример просьбы. Ученик: «что у меня в работе и что горит?» — или «что проходить после этого курса?»

mark_goal#

Отмечает пункт урока, как только его разобрали: термин, выбор, исполнение или заблуждение, которое нужно было опровергнуть. Следующее занятие опирается на отметки — даже если это занятие прервётся.

Параметры

  • session — идентификатор занятия. Обязательный.
  • goal — ключ пункта из lesson_map ответа start_lesson. Обязательный.
  • status — обязательный:
  • done — ученик показал это на своей задаче;
  • planned — запланировал применить;
  • not_needed — необязательный пункт не понадобился (заблуждение не проявилось); обязательному так отметить нельзя;
  • open — вернуть пункт в работу; свидетельство не нужно и стирается.
  • evidence — что именно ученик сделал или сказал, не длиннее 500 знаков. Нужен для всех статусов, кроме open; пустой не передаётся, и требует его сервер (evidence_required). Свидетельство видят авторы курса, чтобы улучшать курс (goal_runs): в нём — что ученик сделал или сказал, без личных данных. Жалоба ученика на урок идёт не сюда, а в report_issue.
  • resume_from — одна фраза, с чего продолжить урок, если занятие прервётся, не длиннее 500 знаков. Необязательный; без него прежняя заметка остаётся. Следующий агент строит от неё мостик (start.opening: return).

В ответе. goal и status; objective — цель пункта: ключ, статус (not_started, touched, covered) и open — её обязательные пункты, которые ещё открыты; lesson — статус урока; next_step — следующий шаг данными и next — тот же шаг фразой для агента:

next_step Что дальше
{"kind": "goal", "objective", "goal", "title"} следующий открытый обязательный пункт
{"kind": "quiz"} обязательные пункты закрыты — проверка знаний
{"kind": "complete"} закрыты, а обязательного квиза нет — complete_lesson
null урок пройден

Отметка «не по порядку» записывается: платформа не отказывает, а говорит, что по цели ещё открыто и что дальше. Повторная отметка пункта заменяет прежнюю — статус, свидетельство, время и занятие. Цель разобрана, когда закрыты (done или planned) все её обязательные пункты; урок разобран, когда разобраны все цели. Пункты и свидетельства видят агент и авторы курса (goal_runs); ученик видит статусы целей — на странице курса и в шапке веб-чата («темы урока: 2 из 5»). Отметка двигает активность занятия: занятие, где агент только отмечает пункты, не считается брошенным.

Отказы

  • not_your_session — занятие принадлежит другому ученику.
  • session_closed (с полем status) — занятие уже закрыто или брошено; урок продолжают в новом занятии — start_lesson.
  • not_enrolled, organization_suspended — доступ к курсу отозван.
  • goal_unknown — в уроке нет такого пункта; в отказе — ключи пунктов урока.
  • goal_removed — пункт снят из урока новым релизом.
  • goal_status_unknown — статус не из четырёх; в отказе — allowed.
  • not_needed_required — обязательный пункт отмечен not_needed; в отказе — allowed.
  • evidence_required — закрывающая отметка без свидетельства.
  • evidence_too_long (с limit и length) — свидетельство длиннее предела.
  • resume_from_too_long (с limit и length) — заметка «с чего продолжить» длиннее 500 знаков.
  • course_not_released, lesson_not_in_release, run_archived, busy — см. отказы цепочки урока.

Пример просьбы. Отдельно просить не нужно: агент отмечает пункты сам, по ходу разбора.

my_homework#

Показывает домашние задания ученика: что выдано, что сдано, что вернули на доработку, какой срок.

Параметры

  • course — идентификатор курса. Необязательный; без него — все курсы пространства.
  • lesson — идентификатор урока. Необязательный; с ним приходит одна домашка целиком — так агент читает текущий ответ, прежде чем его дополнить.
  • space — пространство: имя организации из whoami или personal. Необязательный; без него с course или lesson — пространство начатого занятия по курсу, иначе выбранное учеником.

В ответе. space и список items, недавние сверху. У каждой домашки — курс и урок с названиями, lesson_url — адрес урока, где она сдаётся в вебе, название задания, статус, срок (due_at), признак просрочки (overdue), номер текущей версии ответа и last_comment — комментарий куратора к последнему возврату на доработку или отмене приёма. С lesson — ещё homework (задание: описание, режим ответа, правило срока) и submission (текущий ответ, файлы, журнал событий).

status Что значит
Assigned выдана при закрытии урока, ещё не сдана
Submitted сдана, ждёт куратора
Returned куратор вернул на доработку или отменил приём
Accepted куратор принял, правка закрыта

Просрочка — признак, а не статус: срок прошёл, а от ученика ждут действия (Assigned или Returned).

Отказы

  • not_enrolled — ученик не записан на курс.
  • organization_suspended — организация пространства приостановлена.
  • space_not_available — такого пространства у ученика нет.
  • course_not_in_space — курса в названном пространстве нет.
  • lesson_not_found — такого урока нет.

Пример просьбы. Ученик: «что у меня висит по домашкам?»

my_notes#

Показывает ученику, что о нём запомнено.

На занятии заметки приходят в history ответа start_lesson; этот инструмент нужен, когда ученик спрашивает вне занятия.

Параметры

  • course — идентификатор курса. Необязательный; с ним к фактам добавляются проект и наблюдения этого курса.

В ответе. facts (о человеке), observations (как учится), project (на чём учится в этом курсе) и projects_elsewhere — проекты других курсов, пока у этого курса своего нет: агент спрашивает, берём ли тот же. У каждой записи ключ, текст и даты — когда появилась и когда обновлялась; у проекта другого курса — ещё курс и его название.

Отказы. Своих нет — только общие.

Пример просьбы. Ученик: «что ты обо мне запомнил?»

my_reports#

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

Видны только репорты с занятий самого ученика. Кто ещё жаловался на то же место, не приходит.

Параметры

  • course — идентификатор курса. Необязательный; без него приходят репорты по всем курсам.

В ответе. Список reports, свежие сверху. У каждого репорта номер (id), вид, урок и его название, цель урока, текст, время отправки, статус, ответ автора (resolution) и время, когда репорт закрыли (resolved_at).

status Что значит
new автор ещё не смотрел
in_progress автор разбирается
fixed курс поправили
rejected автор решил не менять курс
duplicate о том же уже сообщали, правят по тому репорту

Ответ автора агент пересказывает близко к тексту. У дубля без своего ответа приходит ответ на тот репорт, дублем которого он признан.

Отказы. Своих нет — только общие.

Пример просьбы. Ученик: «что там с моим замечанием про второй вопрос?»

notify_when_released#

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

Параметры

  • course — идентификатор анонса из list_catalog (у него upcoming). Обязательный.
  • notify — false снимает подписку. Необязательный, по умолчанию true.

В ответе. Курс, его название и notify — подписан ли ученик теперь. Повторный вызов ничего не меняет. Письмо уходит на почту ученика один раз, когда курс откроют.

Отказы

  • course_not_upcoming — подписка на курс, который не анонсирован: он уже открыт, снят или его нет. Отписаться можно от любого курса.

Пример просьбы. Ученик: «напиши мне, когда выйдет курс про стыки между отделами» или «больше не присылай про этот курс».

org_report#

Отчёт руководителя по обучению своей организации.

Параметры

  • course — идентификатор курса, чтобы сузить отчёт до одного курса. Необязательный.
  • status — not_started, in_progress или completed. Необязательный.

В ответе. Строки «человек × курс»: имя и учётная запись, организация, статус, доля пройденного, дедлайн, обязательность, просрочка, дата последней активности и document — сколько разделов в документах курса и сколько из них заполнил сотрудник. По второму числу видно, собран ли документ у того, кто курс уже прошёл.

Отказы. Своих нет. Сотруднику без роли руководителя отчёт приходит пустым, а не отказом: данные закрыты правами, и ошибки здесь нет.

Пример просьбы. «Покажи, кто из моих сотрудников ещё не начал обязательный курс».

remember#

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

Параметры

  • kind — вид заметки. Обязательный.
  • fact — о человеке: роль, отрасль, размер компании. Живёт у ученика во всех курсах.
  • project — на чём он учится в этом курсе: свой проект, учебный сценарий, роль в сценарии. Живёт при курсе: сценарий одного курса не приходит в другой молча.
  • observation — как учится: темп, что даётся трудно. Живёт при курсе.
  • key — короткий повторяемый ключ вроде role, project или pace. Обязательный. Запись по существующему ключу замещает прежний текст, а не добавляет вторую. Что выяснять об ученике по курсу, говорит рамка курса (course_frame в ответе start_lesson): агент пишет под её ключами, и по ним заметки приходят в history следующих занятий.
  • text — сама заметка. Обязательный.
  • session — идентификатор занятия. Обязателен для проекта и наблюдения: из него берётся курс.

В ответе. Ключ и вид записанной заметки; посреди занятия — ещё прогресс урока по целям: статусы целей, без пунктов.

Профиль ученика. Для фактов о человеке есть канонические ключи: role, industry, company, goal, current_task, background, tools, learning_style, time_budget. Из них складывается профиль: ученик видит его на странице профиля, правит сам и может заполнить в коротком разговоре с наставником в боковой панели. Агент пишет под этими ключами, а не под синонимами — role, а не position, — и роль, названная на уроке, сразу появляется в профиле. В предел заметок канонические ключи не входят.

Отказы

  • unknown_note_kind — вид не fact, project или observation.
  • note_key_required — пустой ключ.
  • not_your_session — для проекта или наблюдения не передан session или занятие чужое.
  • note_limit_reached (с полем limit) — ключей в наборе уже предельно много. Заметки по существующим ключам замещаются и предела не двигают.

Пример просьбы. Ученик: «запомни, что я веду две команды, — объясняй с оглядкой на это».

report_issue#

Сообщает авторам курса о том, что мешает учиться на этом уроке.

Параметры

  • session — идентификатор занятия. Обязательный. Курс, урок и релиз курса сервер проставляет сам.
  • kind — вид репорта. Обязательный: stuck, misconception, material_issue, quiz_question_issue, directive_mismatch, out_of_scope.
  • text — что не так. Обязательный; режется по 2000 символов.
  • question — id вопроса квиза этого урока из request_quiz, если репорт о вопросе. Необязательный; автор курса увидит ключ вопроса.
  • objective — цель урока из lesson_map. Необязательный; режется по 140 символов.

В ответе. Номер репорта (report) и его вид. Номер агент называет ученику: по нему тот найдёт репорт в my_reports. Когда автор ответит, агент скажет об этом на ближайшем занятии по курсу — через closed_reports в ответе start_lesson.

Отказы

  • not_your_session — занятие принадлежит другому ученику.
  • unknown_report_kind (с полем kind) — вид не из списка.
  • report_text_required — описание пустое.
  • question_mismatch (с полем question) — вопрос не из квиза этого урока.

Жалоба ученика идёт сюда, а не в свидетельство mark_goal: на репорты автор отвечает, а свидетельство — о том, что сделал ученик.

Пример просьбы. Ученик: «передай методологу, что второй вопрос понять невозможно».

request_quiz#

Начинает проверку знаний урока и возвращает первый вопрос.

Квиз выдаётся, когда закрыты все обязательные пункты урока, и проверяет весь урок — вопросы из релиза курса. Инструмент всегда в списке: закрытый квиз — отказ со списком того, что осталось разобрать.

Параметры

  • session — идентификатор занятия. Обязательный.

В ответе. Идентификатор попытки и первый вопрос: текст, вид (choice), варианты с идентификаторами без признака правильности, номер вопроса и сколько их всего. Начатая попытка не заводится второй раз — возвращается открытая. Поле next просит агента показать вопрос целиком — текст и все варианты — и ждать ответа ученика: отвечать за него нельзя. teaching_rules — правила проверки знаний.

Открытые попытки курса публикация новой версии переносит или аннулирует сама — см. submit_answer. Попытку, которую публикация не застала — её начали в момент публикации, — вызов аннулирует и сразу начинает новую.

Новая попытка несёт previous_attempt_cancelled — attempt и reason аннулированной попытки ученика по этому уроку, о которой агенту ещё не сообщали, — в этом занятии или в прошлом; reason обычно attempt_outdated (попытку аннулировал сам вызов) или quiz_changed (её аннулировала публикация, пока ученика не было). next тогда просит агента сказать ученику, что курс обновился и вопросы начались заново. Сообщается один раз: если агент уже получил отказ quiz_attempt_cancelled в submit_answer, поля нет.

В веб-чате это держит и сам сервис: вопрос, выданный в ходе модели, получает ответ только в следующем ходе, после реплики ученика. submit_answer в том же ходе модель получает обратно отказом, до платформы он не доходит.

Отказы

  • not_your_session — занятие принадлежит другому ученику.
  • goals_open — открыты обязательные пункты урока; в отказе — goals: [{objective, goal, title}]. Агент разбирает их и отмечает mark_goal.
  • quiz_not_configured — у урока нет квиза; урок закрывается через complete_lesson.
  • quiz_attempts_exhausted (с attempts_used) — попытки кончились.
  • retry_too_soon (с retry_after — моментом с часовым поясом) — не прошла пауза между попытками.
  • not_enrolled, organization_suspended — доступ к курсу отозван.
  • course_not_released, lesson_not_in_release (открытую попытку по снятому уроку вызов перед этим аннулирует), run_archived, busy — см. отказы цепочки урока.

Пример просьбы. Ученик: «давай проверим, как я это усвоил».

set_space#

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

Параметры

  • space — имя организации из whoami или personal. Обязательный.

В ответе. Выбранное пространство (current).

Отказы. space_not_available — такой организации у ученика нет или она приостановлена.

Пример просьбы. Ученик: «давай теперь позанимаемся для себя, не по работе».

start_lesson#

Начинает занятие по уроку: карта урока, указания автора агенту и с чего начать.

Без аргументов берётся то, чем ученик занимался: урок последнего занятия, если он не пройден, иначе следующий урок того же курса. Занятий ещё не было — следующий незакрытый урок курса с ближайшим дедлайном: обязательные и просроченные идут вперёд. С course — следующий незакрытый урок этого курса: так агент продолжает курс, о котором идёт речь, и не открывает урок другого, более срочного. Повторный вызов по тому же уроку продолжает начатое занятие, а не заводит второе.

Параметры

  • lesson — идентификатор урока (id из course_outline). Необязательный.
  • course — идентификатор курса: взять следующий урок в нём. Необязательный; при переданном lesson не действует.
  • frame — отдавать ли рамку курса (course_frame). По умолчанию true. false агент передаёт, только если в этом же разговоре уже получил рамку этого курса: протокол сессий не хранит, и платформа не знает, что агент видел, — рамка длинная, и на каждом уроке повторялась бы целиком.
  • space — в чей документ пишет занятие: организация или personal. Необязательный; без него — пространство начатого занятия по курсу, иначе выбранное. Урок одного курса в двух пространствах — два разных занятия, а документ курса дальше пишется туда, где идёт занятие.

В ответе

  • session и space — занятие и где оно идёт.
  • lesson — урок: идентификатор, ключ, название, зачин (hook), глава, курс и признак просрочки overdue; в веб-чате ещё номер урока, сколько их всего, название курса и остаток пробных уроков.
  • course_promise — обещание курса. Зачин и обещание адресованы ученику, и агент их произносит; пустые — если автор их не задал.
  • start.opening — с чего начинать (таблица ниже).
  • lesson_map — цели урока по порядку: ключ, текст, статус и пункты — ключ, вид, обязательный ли, название, статус. Пункты, снятые новым релизом, не приходят. Подробности пункта — lesson_item, отметка — mark_goal.
  • next_step — следующий шаг данными, как у mark_goal; next — с чего начать фразой для агента: сигналы — первыми, затем репорты и домашнее задание прошлого урока, цели урока списком и в какой реплике их назвать, следующий пункт.
  • resume_from — заметка «с чего продолжить» из прошлых занятий по уроку.
  • directive и material — указания автора к уроку и опора для объяснения. Они адресованы агенту; ученику их не показывают и не пересказывают.
  • course_frame — рамка курса и что выяснять об ученике; только при frame: true.
  • history — что известно об ученике по курсу: прошлые уроки (ключ, название, статус) и их незакрытые цели, заметки — по ключам рамки и свободные. Объём ограничен несколькими прошлыми уроками.
  • closed_reports — репорты ученика по этому курсу, которые авторы закрыли и о которых он ещё не знает; форма та же, что в my_reports. Приходят один раз: агент в начале занятия, до зачина, одной-двумя фразами говорит, что с ними стало, — номер, статус, ответ автора, — и переходит к уроку.
  • artifact_blocks — разделы документа курса, которые собирают на этом уроке: документ, ключ, название, description и заполнен ли (filled). Строки и поля раздела — в artifact. Это подсказка «сегодня собираем этот раздел», а не ограничение: записать можно любой раздел.
  • section_hints — по ключу раздела: что и в какие колонки записать на этом уроке. Адресованы агенту, как directive; ученик видит description раздела.
  • quiz — политика проверки знаний: нужна ли она (required), порог зачёта долей (pass_threshold) и сколько попыток осталось.
  • homework, previous_homework — домашние задания (ниже).
  • signals — наблюдения платформы (ниже).
  • teaching_rules — правила старта и разбора в рамке с пометкой адресата: их ученику не показывают. В веб-чате поля нет: там правила уже стоят в системных инструкциях.
opening Когда С чего начинать
first_in_course первое занятие по курсу знакомство, обещание, зачин, цели
new_lesson новый урок зачин и цели
return прошло больше суток, и есть незакрытое мостик от resume_from, затем цели
repeat урок уже проходили: есть отметки пунктов или урок закрыт одна фраза и выбор: продолжить или заново

Домашнее задание приходит двумя полями; null — задания нет:

  • previous_homework — задание предыдущего по порядку курса урока и сдача ученика в пространстве занятия: статус, срок, overdue, номер версии и last_comment — комментарий куратора к последнему возврату или отмене приёма. Ответа ученика здесь нет — его даёт my_homework с lesson. Агент начинает с него занятие, до зачина: не сдано — предлагает сдать.
  • homework — задание этого урока целиком: описание, режим ответа и правило срока (due). Агент озвучивает его, когда урок засчитан.

signals — наблюдения платформы по истории ученика, фразами для агента; поля нет, когда сказать нечего:

  • ученик не раз начинал этот урок и бросал в самом начале, не отметив ни одного пункта, — агент спрашивает, что мешало, и начинает с его задачи;
  • половина целей урока разобрана, а документ урока не начат — агент собирает первый раздел;
  • срок курса прошёл или к нему нужно проходить от трёх уроков в неделю — агент говорит об этом один раз, без нажима.

Сигнал приходит один раз за занятие, в ответе — не больше трёх. Времени внутри занятия в них нет: агенты плохо толкуют его посреди урока, поэтому платформа считает сама и отдаёт вывод.

Отказы

  • not_enrolled — ученик не зачислен на курс.
  • organization_suspended — организация ученика приостановлена.
  • lesson_not_found — такого урока нет.
  • nothing_to_study — незакрытых уроков не осталось (только при вызове без lesson; с course — в этом курсе, и в отказе есть course).
  • web_demo_exhausted (с lessons_used и lessons_limit) — в веб-чате пройдены все пробные уроки; занятие не заводится, продолжать нужно своим агентом.
  • program_order — курс заперт программой, как у enroll: запись могла появиться раньше вступления в программу.
  • unknown_channel — канал занятия не agent и не web.
  • course_not_released, busy — см. отказы цепочки урока.

Прошедший дедлайн отказом не является: урок отдаётся, в ответе overdue, а зачёт фиксируется как поздний.

Пример просьбы. Ученик: «давай заниматься» — или «открой урок про дедлайны ещё раз».

store_homework_file#

Сдаёт файлы, которые ученик бросил в окно домашнего задания (upload_homework_file). Его зовёт само окно, а не модель (visibility: app): байты идут base64 мимо контекста модели, прямо на платформу от имени ученика. Все файлы окна уходят одним вызовом submit_homework — одной версией ответа; текст ответа остаётся прежним.

Параметры

  • lesson — идентификатор урока. Обязательный.
  • files — файлы из зоны загрузки: имя и содержимое base64. Обязательный, непустой.
  • space — пространство сдачи. Необязательный; окно передаёт то, в котором его открыли: названное агентом, а если агент его не назвал — то, что при открытии выбрал сервер. Переключение пространства, пока окно открыто, сдачу не переносит.

В ответе. То же, что у submit_homework: space и сдача с версиями.

Отказы. Как у submit_homework: больше десяти файлов в ответе, файл больше предела, больше 30 МБ новых файлов за раз, тип, который платформа не принимает, принятая домашка.

Пример просьбы. Отдельно просить не нужно: инструмент зовёт окно по кнопке «Сдать».

student_detail#

Подробности по одному сотруднику своей организации: чем занимался и как сдал проверки знаний.

Параметры

  • user — учётная запись сотрудника. Обязательный.

В ответе. Имя и учётная запись; курсы, назначенные вашими организациями, с дедлайнами; занятия со статусами и целями урока (sessions[].objectives) — цель и её статус по прохождению урока; попытки проверок знаний с баллом и признаком зачёта. Попытка со статусом Cancelled — её аннулировала новая версия курса: в счёт она не идёт, балл у неё 0, и следующая попытка урока получает тот же номер.

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

Отказы

  • not_your_student — сотрудник не состоит ни в одной вашей организации.

Пример просьбы. «Покажи подробности по Иванову: где он застрял».

submit_answer#

Отправляет ответ ученика и получает вердикт со следующим вопросом.

Вердикт выносит сервер. Проверять ответы самостоятельно агенту нельзя: зачёт ставится только по итогам этой проверки.

Параметры

  • attempt — идентификатор попытки из request_quiz. Обязательный.
  • question — идентификатор вопроса, на который отвечают. Обязательный.
  • answer — ответ строкой. Обязательный: ключ (id) выбранного варианта ("V2"); текст варианта тоже принимается — сервер сопоставляет его с ключом без учёта регистра и лишних пробелов. Верный вариант у вопроса один.
  • student_words — что ученик написал в ответ на этот вопрос, дословно: не пересказ и не только номер варианта; ответил одной цифрой или буквой — передаётся она. Обязательный. Не проверяется и на вердикт не влияет: хранится в журнале проверки для разбора курса. Длинный текст обрезается.

В ответе. Вердикт (верно или нет; пояснение — только вместе с верным ответом), следующий вопрос или null и признак завершения попытки. На последнем вопросе добавляется результат: балл и порог долями, признак зачёта, objective_results — сколько вопросов по каждой цели отвечено верно — и статус занятия. У сданной попытки в результате ещё explanations (ниже), next_lesson и empty_blocks — как у complete_lesson, — а рядом teaching_rules — правила закрытия урока. Со следующим вопросом приходит next, как у request_quiz: показать вопрос и ждать ответа ученика.

Ответ — только то, что ученик написал на этот вопрос, увидев его целиком. Просьба показать вопрос ответом не считается.

Неверный ответ приходит без пояснения и без верного варианта, и агент не называет его до конца попытки: иначе ученик получил бы ответ до пересдачи. Сданная попытка приносит explanations — пояснения автора к вопросам, на которые ученик ответил неверно.

Если попытка не засчитана, в результате есть retry_after — с какого момента можно пересдать, с часовым поясом, — и attempts_left: сколько попыток осталось, null — без лимита. Попытки кончились — attempts_left: 0 и retry_after: null: пересдачи не будет. Агент называет ученику время пересдачи в его местном времени, если оно известно, иначе с поясом, и не предлагает пересдачу раньше срока — сервер откажет retry_too_soon.

Новая версия курса посреди попытки. Публикация курса переносит открытую попытку на новую версию, если квиз урока не изменился: вопросы и данные ответы остаются, порог — тот, что был у урока на старте попытки. Изменился квиз или урок снят — попытка аннулируется: в лимит она не идёт и паузы перед следующей не даёт. Попытку, которую публикация не застала (её начали в момент публикации), аннулирует без сравнения первый ответ в неё. Ответ в аннулированную попытку — отказ quiz_attempt_cancelled. Агент говорит ученику, что курс обновился и проверка начнётся заново, и сам запрашивает квиз; урок снят — говорит об этом и предлагает следующий урок.

Отказы

  • student_words_required — слова ученика не переданы или пустые.
  • quiz_attempt_cancelled (с attempt, session, reason) — попытку аннулировала новая версия курса. reason: quiz_changed — квиз урока изменился; attempt_outdated — попытку начали на прежней версии в момент публикации; lesson_removed — урок снят из курса. При первых двух квиз запрашивают заново — request_quiz по session; при lesson_removed квиза по уроку больше нет.
  • attempt_finished — попытка уже завершена.
  • question_mismatch — вопрос не из этой попытки или на него уже отвечено.
  • not_your_session — попытка принадлежит другому ученику.
  • not_enrolled, organization_suspended — доступ к курсу отозван, пока шла попытка. Доступ перепроверяется на каждом ответе.
  • course_not_released — попытка не по уроку из релиза; busy — попытку в этот момент меняет другой запрос, ответ не принят. См. отказы цепочки урока.

Пример просьбы. Отдельно просить не нужно: агент передаёт ответ ученика сам и зачитывает вердикт сервера.

submit_homework#

Сдаёт или правит текст домашнего задания урока.

Текст заменяет прежний целиком: дополняя ответ, агент сначала читает его через my_homework с lesson. Файлы ответа остаются как были; сдают их окном upload_homework_file или на странице урока. Сдать можно и до закрытия урока — тогда домашка сразу Submitted.

Параметры

  • lesson — идентификатор урока. Обязательный.
  • answer — текст ответа, markdown. Обязательный.
  • space — в чьём пространстве сдача. Необязательный; без него — пространство начатого занятия по курсу, иначе выбранное.

В ответе. space и submission — статус, срок, текущая версия, ответ, файлы (имя, тип, размер, адрес), журнал событий и versions — все сохранённые версии ответа. Каждое сохранение — новая версия со статусом Submitted, и куратор видит все версии.

Отказы

  • not_enrolled, organization_suspended, space_not_available, course_not_in_space, lesson_not_found — как у my_homework.
  • no_homework — у урока нет домашнего задания.
  • empty_answer — в ответе нет ни текста, ни файлов.
  • answer_mode — задание сдаётся только файлами.
  • accepted_locked — домашку уже приняли: правка закрыта.
  • too_many_files, file_too_large, answer_too_large, file_rejected — пределы файлов; касаются сдачи из окна и страницы урока.
  • file_missing — файл не передан или пуст; invalid_files — список файлов пришёл не в той форме. Оба — от сдачи из окна.
  • busy — эту же сдачу в тот же момент сохраняет другой запрос; повторить сдачу.

Пример просьбы. Ученик: «запиши в домашку: встречу провёл, спонсор согласовал бюджет».

update_artifact#

Записывает в раздел документа курса строки или поля — словами ученика.

Параметры

  • course — идентификатор курса. Обязательный.
  • artifact — ключ документа. Обязательный.
  • key — ключ раздела. Обязательный; регистр не важен.
  • rows — строки раздела many: список {"id": "A1", "колонка": "текст"}. Необязательный. Строка без id — новая: ID выдаёт платформа, номера не переиспользуются. Со id меняются только названные клетки, прочие остаются.
  • delete_rows — ID строк раздела many на удаление. Необязательный.
  • fields — поля раздела one: {"поле": "текст"}. Необязательный; меняются только названные поля.
  • clear — очистить раздел: у many удалить все строки, у one — все поля. По умолчанию false; вместе с rows, delete_rows или fields не передаётся.
  • space — в чей документ. Необязательный; без него — пространство начатого занятия по курсу, иначе выбранное.

Значение клетки — текст: пробелы по краям обрезаются, пустое значение клетку стирает, предел — 4000 знаков. Очистка нужна, когда записанное перестало быть правдой — ученик сменил проект, — а заменить его пока нечем. Вызов без rows, delete_rows, fields и clear сервер отклоняет: записывать нечего.

В ответе. Документ, ключ раздела и заполненность: сколько разделов всего и сколько готово; посреди занятия — ещё прогресс урока по целям: статусы целей, без пунктов. created — ID строк, которые завела эта запись; empty_cells — каких обязательных клеток разделу ещё не хватает (row и column или field). Пустую клетку агент доводит с учеником или ставит «уточнить у …» с именем и датой — такая клетка считается заполненной.

Сервер проверяет только форму — документ, раздел, колонки и строки есть, значение — текст в пределе. Отвечает ли запись описанию раздела, смотрит агент: на зачёт документ не влияет.

Отказы

  • not_enrolled, organization_suspended — курс ученику сейчас недоступен.
  • artifact_not_found — в курсе нет документа с таким ключом.
  • artifact_block_not_found — в документе нет такого раздела.
  • artifact_nothing_to_write — не передано ни rows, ни delete_rows, ни fields, ни clear.
  • artifact_clear_with_content — clear вместе с rows, delete_rows или fields.
  • artifact_wrong_section — rows или delete_rows у раздела one, fields у раздела many; в отказе — вид раздела (rows).
  • artifact_unknown_column, artifact_unknown_field — у раздела нет такой колонки или поля; в отказе — какие есть.
  • artifact_unknown_row — строки с таким id нет.
  • artifact_invalid_value — значение не текст и не число или длиннее 4000 знаков; в отказе — колонка или поле и предел (max). С param — параметр не той формы (например, rows не список строк).
  • artifact_too_many_rows — строк в разделе больше предела.

Пример просьбы. Ученик: «запиши договорённость: ретро раз в две недели, ведёт Аня» или «у нас решения принимаются согласием — так и запиши».

upload_homework_file#

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

Параметры

  • lesson — идентификатор урока. Обязательный.
  • space — в чьём пространстве сдача. Необязательный; без него — пространство начатого занятия по курсу, иначе выбранное.

В ответе. Клиент с MCP Apps рисует окно: зона перетаскивания нескольких файлов (в ответе до 10 файлов, каждый до 10 МБ, за раз — до 30 МБ) и кнопка «Сдать». Пространство окно фиксирует при открытии. Файлы уходят на платформу мимо модели одной версией ответа (через store_homework_file), и окно пишет в разговор реплику ученика «Сдал файлы домашнего задания…». Клиенту без MCP Apps приходит текст со ссылкой на урок — агент просит ученика прикрепить файлы в блоке «Домашнее задание» там.

Отказы.

  • no_homework — у урока нет домашнего задания;
  • answer_mode — задание сдаётся только текстом: ответ передают через submit_homework;
  • accepted_locked — домашку уже приняли, окно не открывается;
  • а также not_enrolled, organization_suspended, space_not_available, course_not_in_space, lesson_not_found.

Пример просьбы. Ученик: «протокол встречи у меня в файле, давай сдам».

whoami#

Говорит, под какой учётной записью вошёл ученик и в каких он организациях.

Нужен, когда список курсов или каталог пуст: «курсов нет» и «вошли не тем аккаунтом» выглядят одинаково, и различает их только это.

Параметры. Нет.

В ответе. Учётная запись, полное имя, организации — название, роль в организации и признак suspended — и выбранное пространство (space). Приостановленная организация закрывает доступ к своим курсам — без этого признака пустой каталог необъясним.

Отказы. Своих нет — только общие.

Пример просьбы. Ученик: «почему у меня пусто? под кем я вообще вошёл?»

Инструменты куратора#

Этот набор живёт на кураторском адресе /authoring. Он требует авторской роли — Course Creator, Moderator, System Manager или Administrator; вызов без неё отклоняется ошибкой доступа (403), а не кодом отказа — у агента ученика нет сценария, в котором он с этим что-то сделает, и нарушение должно попадать в журнал как нарушение.

Отдельный адрес ничего не защищает: он известен, и токен у ученика тот же. Отказывает авторская роль на стороне Frappe.

Курс меняется только новым релизом. Релиз собирают из карты курса в репозитории course-design и публикуют командой конвейера — как, сказано в «Как собрать курс». Инструментов правки курса здесь нет: набор куратора — чтобы видеть действующий релиз, открывать и снимать курс, вести заметки и репорты по ключам релиза и смотреть, как ученики проходят уроки. Тестеров курса выдаёт человек в кабинете автора, а не агент.

Порядок работы агент получает в инструкциях сервера и в prompt author. Курсы на платформе общие: список курсов, релизы, заметки и репорты доступны любой авторской роли. Прохождения учеников (goal_runs) — только кураторам, которые ведут курс, модераторам и администраторам.

add_note#

Задаёт куратору вопрос на месте курса.

Нужен, когда для правки требуется решение куратора, а его нет в чате. Вопрос встаёт на своё место в кабинете автора и в очередь «Агент спрашивает»; куратор отвечает в нити, а ответ агент читает в course_notes.

Параметры

  • course — идентификатор курса. Обязательный.
  • target — ключ места в действующем релизе курса: course, chapter.<ключ>, lesson.<ключ>, goal.<урок>/<пункт> и другие — полный перечень в course_notes. Ключи берутся из course_release. Обязательный.
  • text — вопрос. Обязательный.
  • quote — фрагмент текста, о котором вопрос. Необязательный.

В ответе. Идентификатор заметки, курс, ключ места target, release и version — релиз, к которому она написана (действующий), lesson_key — урок места (null у мест вне урока), label — место словами, missing: false, статус open и waiting_on: author — ход куратора.

Отказы

  • course_not_found — курса с таким идентификатором нет.
  • course_not_released — у курса нет релиза: ставить заметку не на что.
  • invalid_target — адрес не по форме таблицы мест (where: target).
  • note_target_unknown — адрес по форме, но места с таким ключом в действующем релизе нет (target, release).
  • invalid_note — пустой текст.

Пример просьбы. «Если не уверен, какой пример взять для пункта про эскалацию, — спроси меня в кабинете».

announce_course#

Показывает курс в каталоге до выхода. Записаться на него нельзя, ученик может попросить сообщить о выходе. На странице курса видны только его цели: программа, уроки и документы закрыты.

Цели анонса зависят от того, есть ли у курса релиз:

  • курс без релиза — цели задаются здесь, в objectives, и хранятся в самом курсе; новый список заменяет прежний целиком;
  • курс из релиза — цели анонса это названия глав действующего релиза; objectives ему не передаются.

Параметры

  • course — идентификатор курса. Обязательный.
  • objectives — цели курса списком строк, по цели на пункт. Только для курса без релиза; без них анонс возьмёт цели, заданные раньше.

В ответе. Курс, published и upcoming — оба true — и цели курса в objectives, ровно как их увидят в каталоге.

Открывает анонс publish_course — когда у курса есть релиз: первый релиз привязывают к анонсу при публикации, и подписавшимся уходит письмо. Снимает — unpublish_course.

Отказы

  • course_not_found — курса с таким идентификатором нет.
  • course_objectives_missing — у курса без релиза нет целей: не переданы и не заданы раньше.
  • course_from_release — цели переданы курсу из релиза.
  • course_has_content — у курса без релиза есть уроки: программу курсу даёт релиз.
  • course_already_published — курс уже открыт ученикам и анонсом не станет.

Пример просьбы. «Покажи курс про переговоры в каталоге как анонс, с тремя целями: подготовить разговор, удержать рамку, договориться о следующем шаге».

course_notes#

Показывает заметки куратора к курсу — очередь из кабинета автора.

Куратор вычитывает действующий релиз в кабинете и ставит заметку прямо на место. С этой очереди стоит начинать работу над курсом.

Параметры

  • course — идентификатор курса. Обязательный.
  • status — open (в работе, по умолчанию), done (агент отметил сделанным, ждёт проверки куратора), accepted (принято); null — все.
  • lesson — ключ урока: заметки к уроку и местам внутри него. Необязательный.

В ответе. Заметки, старые сверху. У каждой — release и version (релиз, к которому она написана, а не действующий), ключ места target, lesson_key — урок места (его хранит заметка: у снятого урока он тот же, что при записи), label — место словами по действующему релизу, quote — фрагмент, о котором речь, text, кто и когда написал, нить ответов replies и waiting_on — чей ход: agent или author, у принятой null. missing — места нет в действующем релизе: новый релиз снял этот ключ; подпись тогда — вид места и ключ. Заметка без release — архив прежних мест: адрес как есть и missing: true.

Фильтр lesson ищет по ключу урока, который хранит заметка: находятся и заметки урока, уже снятого из программы. Курс без релиза отказом не отвечает — его заметки только архивные.

Ключи мест:

Ключ Место
course курс целиком
chapter.<ключ> глава
lesson.<ключ> урок
objective.<ключ> цель урока
goal.<урок>/<пункт> пункт цели урока
question.<ключ> вопрос квиза
section.<ключ> раздел документа курса
agent.frame рамка курса в пакете агента
agent.lesson.<ключ> срез пакета агента для урока
agent.item.<урок>/<пункт> подробности пункта в пакете агента
map.<узел> узел карты курса

Отказы

  • course_not_found — курса с таким идентификатором нет.
  • invalid_note — неизвестный статус.

Пример просьбы. «Посмотри, что я написал по курсу в кабинете».

course_release#

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

Параметры

  • course — идентификатор курса. Обязательный.
  • lesson — ключ урока. Необязательный: с ним в ответ добавляется срез пакета агента этого урока.

В ответе. course — карточка курса и действующего релиза: ключ курса, название, release, version, когда и кто опубликовал. Без lesson — ещё chapters и lessons по порядку релиза с ключами: у урока — глава, зачин, порог зачёта, разделы документа, домашнее задание, цели с пунктами и questions — вопросы квиза с вариантами, верным вариантом correct и пояснением; и document — документ курса по разделам (null, если его нет).

С lesson — только этот урок (lesson, в том же виде) и agent — пакет агента: рамка курса (frame, learn_about_student) и срез урока (lesson): то, что агент ученика получает на занятии. Без lesson пакета агента в ответе нет: он большой, а нужен для одного урока.

Ответы квиза видит только авторская роль: метод отдаёт их куратору, чтобы он проверил собственный квиз, а ученику отказывает в доступе.

Отказы

  • course_not_found — курса с таким идентификатором нет.
  • course_not_released — у курса нет действующего релиза.
  • lesson_not_in_release — урока с таким ключом в действующем релизе нет (course, lesson_key, release).

Пример просьбы. «Покажи, что сейчас в четвёртом уроке, вместе с указаниями агенту».

course_releases#

Показывает историю релизов курса.

Параметры

  • course — идентификатор курса. Обязательный.

В ответе. Релизы, свежие сверху: release, version, published_at, published_by — кто опубликовал, digest — отпечаток файла релиза (тот же файл — тот же отпечаток), commit — коммит course-design, из которого версия впервые опубликована (null — опубликована без коммита), document_key — ключ документа курса (null — документа нет) и active — действует ли. Тот же релиз, опубликованный ещё раз, новой версии не даёт. У курса без релиза список пуст.

Содержимое платформа хранит только у действующей версии — его показывает course_release. От прежних версий остаётся запись из этого списка; саму прежнюю версию смотрят в git course-design по commit. У версии без коммита кандидата из истории карты проверяют по digest: собранный из него релиз даёт тот же отпечаток. Не дал ни один кандидат — восстановить такую версию нельзя.

Отказы

  • course_not_found — курса с таким идентификатором нет.

Пример просьбы. «Когда мы последний раз выпускали курс, какая версия сейчас у учеников и из какого она коммита?»

course_reports#

Показывает, на что жалуются агенты, ведущие этот курс.

Репорт шлёт агент ученика, когда курс мешает учиться: материал неверен, вопрос квиза двусмыслен, указание не подходит или ученик сказал об уроке что-то, чего автор не знает.

Параметры

  • course — идентификатор курса. Обязательный.
  • kind — вид репорта: stuck, misconception, material_issue, quiz_question_issue, directive_mismatch, out_of_scope. Необязательный.
  • lesson — ключ урока. Необязательный. Урок ищется по ключу на его записи: находятся и репорты урока, снятого из программы.
  • status — open (новые и в работе), new, in_progress, fixed, rejected или duplicate. Необязательный; без него приходят все.

В ответе. Пятьдесят свежих репортов: номер id, вид, текст, когда отправлен, release — действующий релиз на момент жалобы (курс с тех пор могли выпустить заново), lesson_key — ключ урока, objective и question_key — если репорт о цели или о вопросе квиза. У репорта, отправленного до первого релиза курса, release — null, lesson_key — тоже, если у урока нет ключа. У каждого — status, ответ resolution и resolved_at, когда репорт закрыли. Закрывают репорт resolve_report.

Кто пожаловался, не приходит: важно, что не так с курсом, а не кто сказал.

Отказы

  • course_not_found — курса с таким идентификатором нет.
  • unknown_report_kind — вид не из списка.
  • unknown_report_status — статус не из списка.

Пример просьбы. «Посмотри жалобы по курсу за последнее время» или «Покажи, что писали про четвёртый урок».

create_course#

Заводит курс до первого релиза — чтобы показать его в каталоге анонсом (announce_course). Курс создаётся черновиком без уроков и ученикам пока не виден.

Курс из релиза этим инструментом не заводят: его заводит первая публикация релиза. Если анонс уже есть, первый релиз привязывают к нему — подписчики «сообщить о выходе» сохраняются.

Параметры

  • title — название курса. Обязательный.
  • summary — короткий текст для карточки в каталоге. Обязательный.
  • description — полное описание на странице курса. Необязательный; без него берётся summary.

В ответе. Идентификатор курса, название и признак публикации.

Кто завёл курс, становится его инструктором. Первая публикация релиза со списком кураторов этот набор заменит.

Отказы. Своих нет — только общие.

Пример просьбы. «Заведи анонс курса „Переговоры для руководителей групп“, в каталоге пиши, что он про подготовку к сложному разговору».

goal_runs#

Показывает, как ученики проходят уроки курса: что разобрано, где застряли, что засчитано и на каком свидетельстве. По этому автор улучшает курс.

Параметры

  • course — идентификатор курса. Обязательный.
  • lesson — ключ урока. Необязательный. Находятся и прохождения урока, снятого из действующего релиза.
  • start — сколько прохождений пропустить. Необязательный, по умолчанию 0.
  • limit — сколько прохождений на странице: не больше 20, оно же по умолчанию. Необязательный.

В ответе. Курс, lesson, start, limit, has_more — есть ли следующая страница (её start — нынешний плюс число прохождений на этой) — и runs: прохождения уроков, сначала недавно начатые. У каждого — ученик (student: id пользователя и полное имя name), урок (ключ и название; у урока, снятого из релиза, — последнее название, с которым он был; у прохождения без записи урока название — null), status — not_started, in_progress, covered или passed, accepted_at — первый старт урока, started_at — первая отметка пункта, passed_at — урок закрыт, resume_from — с чего агент продолжит. Цели урока — статус и подтверждена ли квизом; пункты — статус, свидетельство evidence, когда и в каком занятии отмечены. removed — цель или пункт сняты новым релизом. Прохождения, сброшенные вместе с прогрессом ученика, не приходят.

Свидетельства — слова учеников. Они открыты автору, а не другим ученикам и не руководителям: в ответы на репорты и в заметки их не переносят.

Доступ. Видят инструкторы курса — их задаёт публикация релиза списком кураторов из карты курса, — модераторы и администраторы платформы. Куратору, который курс не ведёт, и ученику — отказ доступа (403).

Отказы

  • course_not_found — курса с таким идентификатором нет.
  • course_not_released — у курса нет релиза: прохождения ведутся только по урокам релиза.
  • invalid_page — start или limit не целое или меньше допустимого (where, value).

Пример просьбы. «На каком пункте третьего урока ученики застревают чаще всего?»

list_courses#

Показывает курсы платформы — черновики, анонсы и опубликованные, свежие сверху.

С этого начинается работа: идентификатор курса нужен всем остальным инструментам, а между сессиями агент его не помнит.

Параметры

  • published — да или нет: сузить список до опубликованных или до черновиков. Необязательный; без него приходят все.

В ответе. По каждому курсу: идентификатор, название, краткое описание, признаки публикации и анонса, course_key — ключ курса из релиза и release — версия и дата публикации действующего релиза (у курса без релиза оба null), число уроков и когда курс правили в последний раз.

Отказы. Своих нет — только общие.

Пример просьбы. «Найди курс про переговоры и скажи, какая версия сейчас у учеников».

publish_course#

Открывает курс ученикам.

Открыть можно только курс с действующим релизом: проверки курса прошли при публикации релиза. Новый релиз уже открытого курса действует сразу — открывать курс заново не нужно.

Параметры

  • course — идентификатор курса. Обязательный.

В ответе. Курс, признак публикации и warnings — предупреждения проверок действующего релиза, те же, что вернула его публикация: пустой текст для ученика, вопрос без пояснения. Их стоит пересказать куратору.

Публикация анонса (announce_course) открывает его для записи. Тем, кто просил сообщить о выходе, уходит письмо, один раз: сколько писем ушло — в notified.

Отказы

  • course_not_found — курса с таким идентификатором нет.
  • course_not_released — у курса нет релиза; сначала его публикуют конвейером.

Пример просьбы. «Релиз вышел — открывай курс».

reply_note#

Отвечает в нить заметки, не меняя её статуса.

Уточнить, спросить, объяснить, почему правка сделана иначе. Ход переходит к куратору: в кабинете заметка встаёт в очередь «Агент спрашивает».

Параметры

  • note — идентификатор заметки. Обязательный.
  • text — ответ. Обязательный.

В ответе. Идентификатор заметки, статус, waiting_on и число ответов в нити.

Отказы

  • note_not_found — заметки с таким идентификатором нет.
  • invalid_note — пустой текст.

Пример просьбы. «Спроси в заметке про эскалацию, какую отрасль взять для примера».

resolve_note#

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

Отмечают, когда правка вышла новым релизом: куратор проверяет её в действующем релизе. Комментарий уходит в нить: что и где изменено и в какой версии — так, чтобы куратор проверил правку, не перечитывая курс целиком. Принимает или возвращает заметку куратор в кабинете; вернёт — она снова откроется в course_notes с его ответом.

Параметры

  • note — идентификатор заметки. Обязательный.
  • comment — что поменяли. Обязательный.

В ответе. Идентификатор заметки, статус done, waiting_on: author и число ответов в нити.

Отказы

  • note_not_found — заметки с таким идентификатором нет.
  • invalid_transition — заметка не открыта — уже сделана или принята — или комментарий пуст.

Пример просьбы. «Релиз пятый вышел — отметь заметки, которые он закрывает».

resolve_report#

Меняет статус репорта и отвечает, что сделано.

Ответ видит ученик, с чьего занятия пришёл репорт: его агент перескажет ответ на ближайшем занятии по курсу и покажет в my_reports. Поэтому в ответе — что поменялось в курсе: урок и суть правки, а у отказа — почему курс остаётся прежним. Без оценок ученика и без имён: кто пожаловался, автору не приходит, и ответ — о курсе.

Параметры

  • report — номер репорта из course_reports. Обязательный.
  • status — in_progress (взяли в работу), fixed (курс поправлен новым релизом), rejected (менять не будут) или duplicate (о том же уже есть репорт). Обязательный.
  • resolution — ответ ученику. Обязателен для fixed и rejected.
  • duplicate_of — номер репорта, дублем которого признан этот. Обязателен для duplicate; репорт того же курса.

В ответе. Номер репорта, новый статус, ответ, время закрытия resolved_at и duplicate_of.

Отказы.

  • report_not_found — репорта нет.
  • unknown_report_status — статус не из списка.
  • invalid_report_transition — переход не разрешён: закрытый репорт — fixed, rejected, duplicate — можно только вернуть в in_progress, а перевести в тот же статус нельзя; в отказе — текущий статус и allowed.
  • report_resolution_required — у fixed или rejected пустой ответ.
  • duplicate_of_required — у duplicate нет duplicate_of.
  • invalid_duplicate_of — такого репорта нет, он из другого курса или это сам репорт.

Ответ перезаписывается при каждом вызове: не передан — ученик не увидит прежний, например после возврата в in_progress.

Пример просьбы. «Я переписал второй вопрос четвёртого урока, релиз вышел — закрой репорт про него и напиши ученику, что поменялось».

unpublish_course#

Убирает курс из каталога — и анонс тоже. Прогресс учеников сохраняется.

Удаления курсов на платформе нет — снятие с публикации и есть способ убрать курс.

Параметры

  • course — идентификатор курса. Обязательный.

В ответе. Курс и признак публикации.

Отказы

  • course_not_found — курса с таким идентификатором нет.

Пример просьбы. «Сними курс с публикации, пока мы переписываем вторую главу».

update_course#

Правит название, описания или обещание курса до первого релиза — анонса. Карточку курса из релиза пишет релиз.

Параметры

  • course — идентификатор курса. Обязательный.
  • title — новое название. Необязательный.
  • summary — новый текст для карточки в каталоге. Необязательный.
  • description — новое полное описание. Необязательный.
  • promise — обещание курса: что человек получит к концу, так, чтобы в конце это можно было проверить. Агент ученика произносит его на первом занятии по курсу. Необязательный.

Поле, которое не передали, остаётся прежним.

В ответе. Идентификатор курса, название, краткое описание и обещание.

Отказы

  • course_not_found — курса с таким идентификатором нет.
  • course_from_release — курс собран из релиза: карточку меняет новый релиз.
  • course_has_content — у курса есть уроки.

Пример просьбы. «Перепиши описание анонса: курс для руководителей групп, а не для продавцов».

Когда сервер откажет#

Отказы бывают двух видов, и путать их не нужно.

Ожидаемый отказ — это нормальный ход дела: попытки кончились, урок уже в работе, у курса ещё нет релиза. Платформа отвечает на такой вызов успешно, а причину кладёт машинным кодом в тело ответа. Ошибкой транспорта ожидаемый отказ не приходит: HTTP-ошибку формирует фреймворк, и машинного кода в ней не остаётся — в проде она не несёт ничего, кроме имени исключения.

Вот настоящий ответ платформы на просьбу о квизе, пока в уроке не разобран обязательный пункт:

{ "ok": false,
  "error": { "code": "goals_open",
             "message": "Сначала разберите обязательные пункты урока: mark_goal",
             "goals": [ { "objective": "l-2-D1", "goal": "term:T1",
                          "title": "Термин «пример»" } ] } }

Три вещи в этом ответе важны по отдельности. code — по нему агент решает, что делать дальше. message — то, что можно пересказать человеку. Остальные поля — подробности именно этого отказа: какие пункты урока ещё открыты, когда можно повторить попытку.

Ветвиться нужно по коду, а не по тексту. Тексты меняются и переводятся, коды — нет. Именно поэтому в разделах этой страницы перечислены коды: они и есть контракт.

MCP-сервис доносит отказ до агента целиком — тем же кодом и теми же подробностями, — но подаёт его как ошибку инструмента. Агент видит строку вида Сначала разберите обязательные пункты урока: mark_goal [goals_open] goals: [{"objective": "l-2-D1", "goal": "term:T1", "title": "Термин «пример»"}].

Сбой — другое дело. Он приходит HTTP-статусом, кода отказа в нём нет, и тело разбирать не следует: там внутренние структуры. Сервис переводит такой ответ в одну фразу для агента:

Что случилось Что говорит сервис
Токен истёк или отозван «сессия истекла, требуется повторная авторизация»
Нет прав на эти данные (403) «нет доступа к этим данным»
Объекта не существует (404) «запрошенного объекта не существует»
Запрос нарушает инвариант (417) «сервис отклонил запрос как некорректный»
Слишком много запросов (429) «слишком много запросов, попробуйте чуть позже»
Сбой или недоступность (5xx, обрыв связи) «учебный сервис сейчас недоступен, попробуйте позже»

Автоматических повторов нет: решение о повторе принимает агент — у него есть контекст занятия.

Отказы цепочки урока#

Методы занятия — start_lesson, lesson_item, mark_goal, request_quiz, submit_answer, complete_lesson и course_outline — отказывают одинаково:

Код Что случилось Что делать
course_not_released курс не выпущен релизом, и занятия с агентом по нему нет сказать ученику и предложить другой курс
goals_open квиз или закрытие урока, пока открыты обязательные пункты; в отказе — goals: [{objective, goal, title}] разобрать пункты и отметить mark_goal
run_archived прогресс ученика по курсу сброшен, прохождение в архиве начать урок заново через start_lesson
busy то же занятие в этот момент меняет другой запрос повторить вызов один раз
quiz_attempt_cancelled только submit_answer: ответ в попытку квиза, которую аннулировала новая версия курса (attempt, session, reason) quiz_changed, attempt_outdated — запросить квиз заново request_quiz; lesson_removed — перейти к следующему уроку
lesson_not_in_release урок снят из действующего релиза курса (course, lesson_key, release) перейти к следующему уроку; какие уроки есть — course_outline
goal_unknown в уроке нет такого пункта; в отказе — ключи пунктов взять ключ из lesson_map
goal_removed отметка пункта, снятого из урока новым релизом курса (lesson_item по такому пункту отвечает goal_unknown) пропустить его
goal_status_unknown статус пункта не из open, done, planned, not_needed передать статус из allowed
not_needed_required обязательный пункт отмечен not_needed разобрать пункт или вернуть open
evidence_required закрывающая отметка без свидетельства передать, что ученик сделал или сказал
evidence_too_long свидетельство длиннее 500 знаков (limit, length) сократить до одной-двух фраз
resume_from_too_long заметка «с чего продолжить» длиннее 500 знаков (limit, length) одна фраза, не пересказ

busy и run_archived возвращают только пишущие методы. course_outline и lesson_item только читают: прохождение они не блокируют и не сверяют, и этих отказов у них нет.

Отказы пишущих методов приходят до первой записи: отказанный вызов ничего не меняет, кроме сверки прохождения с действующим релизом курса. Исключение — попытка квиза, отставшая от новой версии: submit_answer в неё и request_quiz с отказом lesson_not_in_release сначала аннулируют попытку, потом отказывают.

Отказы курса из релиза#

Курс на платформе меняется только новым релизом, и кураторские инструменты отказывают одинаково, когда просьба с этим расходится:

Код Что случилось Что делать
course_not_released у курса нет релиза: открыть его (publish_course), посмотреть релиз (course_release), прохождения (goal_runs) или поставить заметку (add_note) нельзя опубликовать релиз конвейером
course_from_release правка карточки (update_course) или целей анонса (announce_course) у курса из релиза поправить карту курса и выпустить новый релиз
course_has_content правка карточки или анонс курса без релиза, у которого есть уроки то же: программу и карточку курсу даёт релиз
lesson_not_in_release урока с таким ключом нет в действующем релизе (course_release) взять ключ из релиза целиком
invalid_target адрес заметки (add_note) не по форме таблицы мест поправить адрес по course_notes
note_target_unknown адрес по форме, но такого ключа в действующем релизе нет взять ключ из course_release

Отдельно стоит ошибка доступа у кураторских инструментов. Вызов без авторской роли (Course Creator, Moderator, System Manager, Administrator) отклоняется именно 403, а не кодом отказа: это нарушение доступа, и оно должно попадать в журнал как нарушение.