← Создание агентов на Cloudflare / agents / harnesses / think
Программные отправки
Устойчиво примите ход Think и вернитесь ещё до запуска инференса. Используйте submitMessages() для обработчиков вебхуков, инициаторов RPC-вызовов и родительских Workers, которым нужны быстрое подтверждение, безопасный повтор и последующая проверка статуса.
Декларативный запланированные задачи с промптами используют один и тот же устойчивый путь отправки под капотом. Используйте getScheduledTasks() когда триггер является повторяющимся и объявлен в коде; используйте submitMessages() напрямую, когда внешний вызывающий объект или webhook создаёт разовую задачу. Чтобы дождаться ответа синхронно, используйте saveMessages() взамен.
submitMessages
async submitMessages(
messages: UIMessage[],
options?: {
submissionId?: string;
idempotencyKey?: string;
metadata?: Record<string, unknown>;
},
): Promise<SubmitMessagesResult>submitMessages() принимает сериализуемые UIMessage[] значения. Он не принимает функциональную форму, поддерживаемую saveMessages((messages) => ...), потому что устойчивые отправки сохраняют работу ещё до выполнения и не могут хранить closures. Массив должен содержать хотя бы одно сообщение.
const submission = await this.submitMessages(
[
{
id: crypto.randomUUID(),
role: "user",
parts: [{ type: "text", text: "Process webhook event 123" }],
},
],
{ idempotencyKey: "webhook-event-123" },
);
return Response.json({
submissionId: submission.submissionId,
status: submission.status,
accepted: submission.accepted,
});const submission = await this.submitMessages(
[
{
id: crypto.randomUUID(),
role: "user",
parts: [{ type: "text", text: "Process webhook event 123" }],
},
],
{ idempotencyKey: "webhook-event-123" },
);
return Response.json({
submissionId: submission.submissionId,
status: submission.status,
accepted: submission.accepted,
});Статусы отправки
| Статус | Значение |
|---|---|
pending |
Принято и ожидает своей очереди |
running |
Принято агентом и выполняется |
completed |
Ход Think успешно завершён |
aborted |
Отправка была отменена |
skipped |
Состояние хода было сброшено до выполнения отправки |
error |
Выполнение завершилось ошибкой или восстановление было небезопасным |
Идемпотентные повторные попытки
Передайте idempotencyKey из вашей внешней системы. Повторный запрос с тем же ключом возвращает уже существующую отправку с accepted: false вместо вставки дублирующихся сообщений:
const first = await this.submitMessages(messages, {
idempotencyKey: payload.id,
});
const retry = await this.submitMessages(messages, {
idempotencyKey: payload.id,
});
console.log(first.submissionId === retry.submissionId); // true
console.log(retry.accepted); // falseconst first = await this.submitMessages(messages, {
idempotencyKey: payload.id,
});
const retry = await this.submitMessages(messages, {
idempotencyKey: payload.id,
});
console.log(first.submissionId === retry.submissionId); // true
console.log(retry.accepted); // falseЕсли вы передадите оба submissionId и idempotencyKey, они должны указывать на одну и ту же отправку. Если они указывают на разные существующие отправки, submitMessages() выбрасывает исключение.
Просмотр, вывод списка, отмена и удаление
Используйте API отправки заданий, чтобы просматривать активную работу, отменять устойчивое задание и очищать терминальные записи:
const current = await this.inspectSubmission(submission.submissionId);
const active = await this.listSubmissions({
status: ["pending", "running"],
});
await this.cancelSubmission(submission.submissionId, "No longer needed");
await this.deleteSubmissions({
status: ["completed", "error", "aborted"],
completedBefore: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
});const current = await this.inspectSubmission(submission.submissionId);
const active = await this.listSubmissions({
status: ["pending", "running"],
});
await this.cancelSubmission(submission.submissionId, "No longer needed");
await this.deleteSubmissions({
status: ["completed", "error", "aborted"],
completedBefore: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
});Используйте cancelSubmission(submissionId) для устойчивой отмены через границы RPC между Worker и Durable Object. Используйте AbortSignal с saveMessages() или continueLastTurn() только если вызывающий код создаёт сигнал внутри Durable Object, который выполняет ход.
Поведение Session
Think сначала сохраняет принятые отправки в реестре отправок. Отправленные сообщения добавляются в Session беседы только тогда, когда отправка начинает выполняться. Более поздние принятые отправки остаются скрытыми от модели, пока не начнётся их собственный ход, что сохраняет семантику ходов по принципу FIFO.
Если вы отменяете отправку до того, как её сообщения будут применены, включая уже принятую к обработке, но всё ещё ожидающую своего хода, эти сообщения не сохраняются в разговоре.
Если чат очищается или состояние хода сбрасывается до выполнения отложенной отправки, эта отправка помечается как skipped.
Сравнение с Workflows
Используйте Workflows для многошаговой оркестрации, повторов на уровне шага, долгих ожиданий, внешних событий, подтверждений от человека или конвейеров, которые могут запускать Think как часть более крупного процесса. См. Think Workflows.