Устойчивое расширение

Устойчивое расширение для платформы агента Microsoft обеспечивает устойчивое выполнение агентов, оркестрации нескольких агентов и рабочих процессов Microsoft Agent Framework. Его можно использовать для сохранения сеансов агента, оркестрации контрольных точек и хода выполнения рабочего процесса, восстановления от сбоев и масштабирования работы между распределенными узлами без изменения логики основного агента.

Расширение поддерживает две модели размещения в C# и Python:

  • Функции Azure для управляемого бессерверного размещения с помощью модели программирования Функции Azure.
  • Приведите собственные вычислительные ресурсы или локальное размещение для выполнения устойчивых агентов и рабочих процессов в собственном рабочем процессе, службе, контейнере, среде Kubernetes или существующей инфраструктуре приложений.

Замечание

В этом руководстве рассматриваются C# и Python размещение устойчивых расширений. Сведения о размещении Go см. в разделе "Размещение A2A " и репозиторий Agent Framework Go.

Overview

Устойчивые агенты объединяют модель программирования Agent Framework с инфраструктурой устойчивых задач, например планировщик устойчивых задач, чтобы создать агенты, которые:

  • Автоматическое сохранение состояния между запросами и рабочими выполнениями
  • Возобновление после сбоев без потери контекста беседы или повторения завершенной работы
  • Масштабирование между распределенными, без отслеживания состояния рабочими ролей на основе спроса
  • Оркестрация рабочих процессов с несколькими агентами с надежными гарантиями выполнения
  • Рабочие процессы агента контрольных точек, созданные с помощью модели рабочих процессов на основе графа
  • Приостановка ввода или внешних событий без использования маркеров вычислений или моделей во время ожидания
  • Возобновление потоковой доставки при настройке с помощью брокера потоковой передачи, например Redis; подтверждение устойчивого завершения отдельно
  • Управление жизненным циклом сеанса с помощью очистки времени ожидания сеанса (TTL) и мониторинга на основе панели мониторинга

Когда следует использовать устойчивые агенты

Выберите устойчивые агенты при необходимости:

  • Состояние сохраняемой беседы: сеансы агента выживают сбои процесса, перезапуски и горизонтальное масштабирование событий
  • Сложные оркестрации: координация нескольких агентов с детерминированными, надежными рабочими процессами, которые могут выполняться в течение нескольких дней или недель.
  • Оркестрация на основе событий: интеграция с триггерами, очередями, веб-перехватчиками, таймерами или существующими событиями приложения
  • Автоматическое состояние беседы: журнал бесед агента автоматически управляется и сохраняется без явной обработки состояния в коде
  • Durable Agent Framework рабочих процессов. Создание рабочих процессов на основе графов Microsoft Agent Framework, чтобы каждый шаг можно было провести контрольные точки и возобновить работу.
  • Длительные сеансы. Сохранение полезных бесед при использовании очистки времени ожидания сеанса (TTL) для автоматического удаления сеансов бездействия
  • Ответы в режиме реального времени: доставка добавочных выходных данных маркера с помощью повторного подключения на основе брокера при проверке устойчивого результата отдельно

Этот подход размещения отличается от размещения управляемого агента на основе служб (например, Службы агента Foundry), который предоставляет полностью управляемую инфраструктуру, не требуя развертывания или управления рабочими узлами. Устойчивые агенты идеально подходят, если требуется гибкость развертывания в коде в сочетании с устойчивым управлением состоянием.

Выбор модели размещения

Модель размещения Выберите его при необходимости
Функции Azure Управляемая, бессерверная модель размещения; встроенное горизонтальное масштабирование и масштабирование до нуля; триггеры и привязки Функции Azure; Конечные точки HTTP, созданные моделью программирования функций; триггер сервера MCP; и минимальное управление инфраструктурой узлов.
Перенос собственных вычислений или локально размещенных Дополнительные возможности контроля над процессом размещения, средой развертывания, жизненным циклом среды выполнения, инфраструктурой, сетью, проверкой подлинности или интеграцией с существующим приложением или службой. Используйте эту модель для контейнеров, Kubernetes, длительных рабочих ролей, консольных приложений, пользовательских служб или сред размещения, отличных от функций.

При размещении в плане размещения Функции Azure Flex Consumption агенты могут масштабироваться до тысяч экземпляров или уменьшаться до нуля, если они не используются, что позволяет платить только за необходимые вычислительные ресурсы. В локальных сценариях собственные элементы управления узлом управляют временем существования, масштабированием, сетью и развертыванием.

Начало работы

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

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

Important

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

В проекте .NET выберите набор пакетов для модели размещения.

Для размещения Функции Azure добавьте пакет интеграции Функции Azure и рабочие пакеты Функций.

dotnet add package Microsoft.Agents.AI.Foundry --prerelease
dotnet add package Microsoft.Agents.AI.Hosting.AzureFunctions --prerelease

Замечание

Используйте расширение рабочих функций, расширение устойчивых рабочих ролей и версии рабочих расширений AzureManaged, объявленные зависимостями расширения агента. Удалите прямые ссылки на пакеты, которые понизят уровень этих зависимостей. См. ссылки на .NET зависимости. Для параллельного обновления схемы-версии 2 также требуется фильтрация рабочих элементов; см. миграцию развертывания и схемы.

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

dotnet add package Microsoft.Agents.AI.Foundry --prerelease
dotnet add package Microsoft.Agents.AI.DurableTask --prerelease
dotnet add package Microsoft.DurableTask.Client.AzureManaged
dotnet add package Microsoft.DurableTask.Worker.AzureManaged
dotnet add package Microsoft.Extensions.Hosting

В проекте Python выберите пакет для модели размещения. Python узлам требуется явная стратегия развертывания.

Для размещения Функции Azure используйте Python 3.13 или более поздней версии и установите пакет интеграции Функции Azure. Следующие команды также устанавливаются Azure клиент OpenAI, используемый в этом руководстве.

pip install agent-framework-azurefunctions agent-framework-openai azure-identity --pre

Для размещения собственных вычислений используйте Python 3.10 или более поздней версии и установите пакет интеграции устойчивых задач.

pip install agent-framework-durabletask agent-framework-openai azure-identity --pre

Для нового изолированного концентратора задач с обновленными рабочими и клиентами установите DURABLE_AGENTS_DEPLOYMENT_MODE=isolated_v2 перед запуском любого узла. Для существующего концентратора выберите стратегию миграции вместо применения этого параметра вслепую. Параметр подтверждает изоляцию; он не обнаруживает других работников или делает старые журналы совместимыми.

размещение Функции Azure

С помощью устойчивого расширения можно развертывать и размещать агенты агента агента Microsoft в Функции Azure со встроенными конечными точками HTTP и вызовом на основе оркестрации. Функции Azure предоставляют цену на основе событий, оплату за каждый вызов с автоматическим масштабированием и минимальным управлением инфраструктурой.

При настройке устойчивого агента в Функции Azure расширение автоматически создает конечные точки HTTP для агента и управляет базовой инфраструктурой для хранения состояния беседы, обработки одновременных запросов и координации рабочих процессов с несколькими агентами. Интеграция размещения Функции Azure также обеспечивает удобные функции, такие как созданные REST API для отправки сообщений, проверки состояния и управления сеансами, а также триггеры, такие как триггер сервера MCP для размещения агентов в качестве серверов MCP без записи клея триггера.

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.AzureFunctions;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Hosting;

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT") ?? "gpt-4o-mini";

// Create an AI agent following the standard Microsoft Agent Framework pattern
AIAgent agent = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(
        model: deploymentName,
        instructions: "You are good at telling jokes.",
        name: "Joker");

// Configure the function app to host the agent with durable thread management
// This automatically creates HTTP endpoints and manages state persistence
using IHost app = FunctionsApplication
    .CreateBuilder(args)
    .ConfigureFunctionsWebApplication()
    .ConfigureDurableAgents(options =>
        options.AddAIAgent(agent)
    )
    .Build();
app.Run();

Warning

DefaultAzureCredential удобно для разработки, но требует тщательного рассмотрения в рабочей среде. В рабочей среде рекомендуется использовать определенные учетные данные (например, ManagedIdentityCredential), чтобы избежать проблем с задержкой, непреднамеренной проверки данных аутентификации и потенциальных рисков безопасности из-за резервных механизмов.

import os
from agent_framework_azurefunctions import AgentFunctionApp
from agent_framework.openai import OpenAIChatCompletionClient
from azure.identity import DefaultAzureCredential

endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
deployment_name = os.getenv("AZURE_OPENAI_DEPLOYMENT", "gpt-4o-mini")
api_version = os.getenv("AZURE_OPENAI_API_VERSION")

# Create an AI agent following the standard Microsoft Agent Framework pattern
agent = OpenAIChatCompletionClient(
    azure_endpoint=endpoint,
    model=deployment_name,
    api_version=api_version,
    credential=DefaultAzureCredential()
).as_agent(
    instructions="You are good at telling jokes.",
    name="Joker"
)

# Configure the function app to host the agent with durable thread management
# This automatically creates HTTP endpoints and manages state persistence
app = AgentFunctionApp(agents=[agent])

Перенос собственного вычислительного или локального размещения

Используйте размещение собственных вычислений, если требуется возможность устойчивых расширений без использования модели программирования Функции Azure. В этой модели процесс запускает рабочую роль устойчивых задач, регистрирует устойчивые агенты или рабочие процессы и подключается к серверной части планировщика устойчивых задач. Клиентский код может выполняться в одном процессе или в отдельной службе.

Локальные работники используют те же основные возможности устойчивых расширений, что и Функции Azure размещения: контрольные точки и возобновление, детерминированное оркестрация агента, рабочие процессы устойчивых агентов, ожидания в цикле, надежная потоковая передача, очистка сеанса простоя, видимость панели мониторинга и распределенное выполнение между экземплярами рабочих ролей без отслеживания состояния. Узел отвечает за предоставление собственных API, управления жизненным циклом, сети, проверки подлинности и развертывания.

Настройте узел с базовым пакетом интеграции устойчивых задач. Используйте ConfigureDurableAgents для устойчивых агентов и ConfigureDurableWorkflows для рабочих процессов на основе графов Microsoft Agent Framework.

string connectionString = Environment.GetEnvironmentVariable("DURABLE_TASK_SCHEDULER_CONNECTION_STRING")
    ?? "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None";

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.ConfigureDurableAgents(
            options => options.AddAIAgent(agent),
            workerBuilder: builder => builder.UseDurableTaskScheduler(connectionString),
            clientBuilder: builder => builder.UseDurableTaskScheduler(connectionString));
    })
    .Build();

await host.StartAsync();

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

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

from agent_framework_durabletask import DurableAIAgentWorker
from durabletask.azuremanaged.worker import DurableTaskSchedulerWorker

worker = DurableTaskSchedulerWorker(
    host_address="http://localhost:8080",
    secure_channel=False,
    taskhub="default",
)

agent_worker = DurableAIAgentWorker(worker)
agent_worker.add_agent(agent)

worker.start()

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

Рабочие процессы платформы устойчивых агентов

Устойчивость не ограничивается устойчивыми оркестрациями. Microsoft рабочих процессов Agent Framework, созданных с помощью модели рабочих процессов на основе графов, также можно сделать устойчивыми. Контрольные точки устойчивых расширений выполняют рабочий процесс, поэтому завершенные действия исполнителя и агента не повторяются после перезапуска или сбоя процесса.

Используйте устойчивые оркестрации, если требуется императивная координация с ветвлением на основе кода, таймерами, действиями и внешними событиями. Используйте устойчивые рабочие процессы Agent Framework, если требуется декларативный граф исполнителей и агентов с типизированной маршрутизацией, вентилятором и вентилятором, условными краями, событиями рабочего процесса, общим состоянием, вложенными рабочими процессами или портами запросов в цикле.

Замечание

Рабочие процессы устойчивых агентов отличаются от хранилища контрольных точек в стандартных рабочих процессах. Хранилище контрольных точек помогает возобновить выполнение рабочего процесса в среде выполнения Agent Framework. Устойчивый модуль запускает рабочий процесс в инфраструктуре устойчивых задач, чтобы ход выполнения рабочего процесса был контрольным и восстановлен между распределенными устойчивыми рабочими возможностями. Сведения о стандартной контрольной точке рабочего процесса см. в разделе "Контрольные точки" и "Возобновление".

Зарегистрируйте рабочие процессы на основе графов с помощью ConfigureDurableWorkflows для локальных приложений или ConfigureDurableWorkflows в построителе приложений "Функции" для размещения Функции Azure.

См. примеры Функции Azure< Функции Azure .NET> и .NET устойчивых рабочих процессов.

Примеры устойчивых рабочих процессов доступны для размещения Функции Azure, включая общее состояние, общее состояние, параллельное выполнение рабочих процессов и рабочие процессы в цикле. Python также поддерживает рабочие процессы на основе графов в автономной рабочей роли устойчивых задач.

Примеры Python Функции Azure для устойчивых агентов, оркестрации, сервера MCP и рабочих процессов.

Сведения о локальном выполнении графа см. в примере автономного Python рабочего процесса.

Samples

Language Модель размещения Устойчивые агенты и оркестрации Рабочие процессы на основе графов
C# Функции Azure примеры агента .NET примеры рабочих процессов .NET
C# Самостоятельный хостинг примеры агента консоли .NET примеры рабочих процессов консоли .NET
Python Функции Azure Примеры функций Python Примеры рабочих процессов Python Функций
Python Самостоятельный хостинг примеры рабочих и клиентских Python автономный рабочий процесс Python

В этих примерах демонстрируется поддержка, не идентичные контракты API на разных языках. Функции создают конечные точки HTTP; автономные приложения реализуют и защищают собственные API.

Потоки агента с отслеживанием состояния с журналом бесед

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

Этот шаблон позволяет обеспечить непрерывность бесед, в которой состояние агента сохраняется с помощью сбоев процесса и перезапусков, что позволяет поддерживать полный журнал бесед в потоках пользователей. Устойчивое хранилище гарантирует, что даже если процесс узла перезагружается или возобновляет работу в другом рабочем экземпляре, беседа легко продолжается с того места, где он остался.

Намеренно настройте очистку сеанса, хранение журнала и хранение результатов. Эти политики имеют различные эффекты; см. жизненный цикл состояния и емкость.

В следующем Функции Azure примере показано несколько HTTP-запросов к одному сеансу. Обе интеграции языка возвращают x-ms-session-id и принимают канонический sessionId параметр запроса. Обработайте возвращаемый идентификатор как непрозрачный: в примере показан адрес сущности .NET схемы версии 2, а форматирование сеанса Python зависит от стратегии развертывания. В локальных приложениях используйте API клиента устойчивых задач из собственного процесса или службы.

# First interaction - start a new session
curl -i -X POST https://your-function-app.azurewebsites.net/api/agents/Joker/run \
  -H "Content-Type: text/plain" \
  -d "Tell me a joke about pirates"

# Response includes session ID in x-ms-session-id header and joke as plain text
# HTTP/1.1 200 OK
# Content-Type: text/plain
# x-ms-session-id: @dafx-v2-joker@263fa373-fa01-4705-abf2-5a114c2bb87d
#
# Why don't pirates shower before they walk the plank? Because they'll just wash up on shore later!

# Second interaction - reuse the exact session ID returned by the first request
curl -X POST "https://your-function-app.azurewebsites.net/api/agents/Joker/run?sessionId=@dafx-v2-joker@263fa373-fa01-4705-abf2-5a114c2bb87d" \
  -H "Content-Type: text/plain" \
  -d "Tell me another one about the same topic"

# Agent remembers the pirate context from the first message and responds with plain text
# What's a pirate's favorite letter? You'd think it's R, but it's actually the C!

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

Используйте sessionId и waitForResponse в новых клиентах HTTP агента. thread_id является устаревшим псевдонимом запроса, а не заголовком ответа для записи. Для Python ответов JSON, считывания sessionId и correlationId. Ознакомьтесь с руководством по миграции API HTTP для псевдонимов и обработки конфликтов.

Подтверждение устойчивого завершения

Для созданных конечных точек агента функций .NET интерпретировать завершение следующим образом:

Состояние HTTP Meaning
202 Accepted Диспетчер принимается. Выполнение не подтверждено успешно.
200 OK Доступен зафиксированный успешный результат.
500 Internal Server Error Возвращается поддерживаемый зафиксированный сбой терминала. Различает это от обычных ошибок узла или транспорта.
410 Gone Завершение известно, но его результат недоступен. Сохраненный результат может быть succeeded или failed; это не обязательно неудачное выполнение или только срок действия результата.

Чтение x-ms-durable-outcome , когда завершение не имеет доступного результата. Не рассматривайте 410 как ожидающие, выводите результат из журнала бесед или автоматически перезаписывайте с новым удостоверением. Вызывающие объекты JSON используют строковый status и числовый statusCodeпсевдоним. Более раннее status_code поле является временным псевдонимом совместимости.

функции Python также различают доступный успех, сохраненные результаты сбоя и недоступные завершенные результаты. Его конверты ошибок и параметры пакета SDK не идентичны .NET. Ознакомьтесь с контрактом .NET завершения и Python HTTP-контрактом.

Эти состояния описывают конечные точки агента. API управления оркестрацией Устойчивые функции имеет собственный ответ состояния и контракт опроса.

Надежная потоковая передача

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

Используйте надежную потоковую передачу, если взаимодействие с пользователем зависит от добавочных ответов, но рабочая нагрузка по-прежнему нуждается в устойчивой семантике выполнения. Завершение потока само по себе не подтверждает, что результат и состояние агента были постоянно сохранены; Проверьте надежный устойчивый результат отдельно. Примеры запуска см. в примерах Python устойчивых задач, включая надежные шаблоны потоковой передачи.

Детерминированные оркестрации с несколькими агентами

Устойчивое расширение поддерживает создание детерминированных рабочих процессов, которые координирует несколько агентов с помощью оркестрации устойчивых задач. В Функции Azure используются Устойчивые функции оркестрации; в узлах собственных вычислений они выполняются через настраиваемую рабочую роль устойчивых задач и клиент.

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

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

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

Последовательные оркестрации

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

При работе с агентами в оркестрации необходимо использовать context.GetAgent() API для получения экземпляра DurableAIAgent, который является специальным подклассом стандартного типа AIAgent, инкапсулирующего одного из зарегистрированных агентов. Оболочка DurableAIAgent гарантирует правильность отслеживания вызовов агента и контрольных точек платформой устойчивой оркестрации.

using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
using Microsoft.Agents.AI.DurableTask;

[Function(nameof(SpamDetectionOrchestration))]
public static async Task<string> SpamDetectionOrchestration(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    Email email = context.GetInput<Email>();

    // Check if the email is spam
    DurableAIAgent spamDetectionAgent = context.GetAgent("SpamDetectionAgent");
    AgentSession spamSession = await spamDetectionAgent.CreateSessionAsync();

    AgentResponse<DetectionResult> spamDetectionResponse = await spamDetectionAgent.RunAsync<DetectionResult>(
        message: $"Analyze this email for spam: {email.EmailContent}",
        session: spamSession);
    DetectionResult result = spamDetectionResponse.Result;

    if (result.IsSpam)
    {
        return await context.CallActivityAsync<string>(nameof(HandleSpamEmail), result.Reason);
    }

    // Generate response for legitimate email
    DurableAIAgent emailAssistantAgent = context.GetAgent("EmailAssistantAgent");
    AgentSession emailSession = await emailAssistantAgent.CreateSessionAsync();

    AgentResponse<EmailResponse> emailAssistantResponse = await emailAssistantAgent.RunAsync<EmailResponse>(
        message: $"Draft a professional response to: {email.EmailContent}",
        session: emailSession);

    return await context.CallActivityAsync<string>(nameof(SendEmail), emailAssistantResponse.Result.Response);
}

При использовании агентов в оркестрации необходимо использовать app.get_agent() метод для получения устойчивого экземпляра агента, который является специальной оболочкой для одного из зарегистрированных агентов. Оболочка устойчивого агента гарантирует правильность отслеживания вызовов агента и контрольных точек в рамках устойчивой платформы оркестрации.

from durabletask.task import OrchestrationContext
from agent_framework_azurefunctions import AgentFunctionApp
from pydantic import BaseModel

class SpamDetectionResult(BaseModel):
    is_spam: bool
    reason: str

class EmailResponse(BaseModel):
    response: str

app = AgentFunctionApp(agents=[spam_detection_agent, email_assistant_agent])

@app.orchestration_trigger(context_name="context")
def spam_detection_orchestration(context: OrchestrationContext, email: dict):
    # Check if the email is spam
    spam_agent = app.get_agent(context, "SpamDetectionAgent")
    spam_thread = spam_agent.create_session()

    spam_result_raw = yield spam_agent.run(
        messages=f"Analyze this email for spam: {email['content']}",
        session=spam_thread,
        options={"response_format": SpamDetectionResult},
    )
    spam_result = SpamDetectionResult.model_validate(spam_result_raw.value)

    if spam_result.is_spam:
        result = yield context.call_activity("handle_spam_email", input=spam_result.reason)
        return result

    # Generate response for legitimate email
    email_agent = app.get_agent(context, "EmailAssistantAgent")
    email_thread = email_agent.create_session()

    email_response_raw = yield email_agent.run(
        messages=f"Draft a professional response to: {email['content']}",
        session=email_thread,
        options={"response_format": EmailResponse},
    )
    email_response = EmailResponse.model_validate(email_response_raw.value)

    result = yield context.call_activity("send_email", input=email_response.response)
    return result

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

Параллельные оркестрации

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

using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
using Microsoft.Agents.AI.DurableTask;

[Function(nameof(ResearchOrchestration))]
public static async Task<string> ResearchOrchestration(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    string topic = context.GetInput<string>();

    // Execute multiple research agents in parallel
    DurableAIAgent technicalAgent = context.GetAgent("TechnicalResearchAgent");
    DurableAIAgent marketAgent = context.GetAgent("MarketResearchAgent");
    DurableAIAgent competitorAgent = context.GetAgent("CompetitorResearchAgent");

    // Start all agent runs concurrently
    Task<AgentResponse<TextResponse>> technicalTask = 
        technicalAgent.RunAsync<TextResponse>($"Research technical aspects of {topic}");
    Task<AgentResponse<TextResponse>> marketTask = 
        marketAgent.RunAsync<TextResponse>($"Research market trends for {topic}");
    Task<AgentResponse<TextResponse>> competitorTask = 
        competitorAgent.RunAsync<TextResponse>($"Research competitors in {topic}");

    // Wait for all tasks to complete
    await Task.WhenAll(technicalTask, marketTask, competitorTask);

    // Aggregate results
    string allResearch = string.Join("\n\n", 
        technicalTask.Result.Result.Text,
        marketTask.Result.Result.Text,
        competitorTask.Result.Result.Text);

    DurableAIAgent summaryAgent = context.GetAgent("SummaryAgent");
    AgentResponse<TextResponse> summaryResponse = 
        await summaryAgent.RunAsync<TextResponse>($"Summarize this research:\n{allResearch}");

    return summaryResponse.Result.Text;
}
from durabletask.task import OrchestrationContext, when_all
from agent_framework_azurefunctions import AgentFunctionApp

app = AgentFunctionApp(agents=[technical_agent, market_agent, competitor_agent, summary_agent])

@app.orchestration_trigger(context_name="context")
def research_orchestration(context: OrchestrationContext, topic: str):
    # Execute multiple research agents in parallel
    technical_agent = app.get_agent(context, "TechnicalResearchAgent")
    market_agent = app.get_agent(context, "MarketResearchAgent")
    competitor_agent = app.get_agent(context, "CompetitorResearchAgent")

    technical_task = technical_agent.run(messages=f"Research technical aspects of {topic}")
    market_task = market_agent.run(messages=f"Research market trends for {topic}")
    competitor_task = competitor_agent.run(messages=f"Research competitors in {topic}")

    # Wait for all tasks to complete
    results = yield when_all([technical_task, market_task, competitor_task])

    # Aggregate results
    all_research = "\n\n".join(r.text for r in results)

    summary_agent = app.get_agent(context, "SummaryAgent")
    summary = yield summary_agent.run(messages=f"Summarize this research:\n{all_research}")

    return summary.text

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

Оркестрации "человек в цикле"

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

using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
using Microsoft.Agents.AI.DurableTask;

[Function(nameof(ContentApprovalWorkflow))]
public static async Task<string> ContentApprovalWorkflow(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    string topic = context.GetInput<string>();

    // Generate content using an agent
    DurableAIAgent contentAgent = context.GetAgent("ContentGenerationAgent");
    AgentResponse<GeneratedContent> contentResponse = 
        await contentAgent.RunAsync<GeneratedContent>($"Write an article about {topic}");
    GeneratedContent draftContent = contentResponse.Result;

    // Send for human review
    await context.CallActivityAsync(nameof(NotifyReviewer), draftContent);

    // Wait for approval with timeout
    HumanApprovalResponse approvalResponse;
    try
    {
        approvalResponse = await context.WaitForExternalEvent<HumanApprovalResponse>(
            eventName: "ApprovalDecision",
            timeout: TimeSpan.FromHours(24));
    }
    catch (OperationCanceledException)
    {
        // Timeout occurred - escalate for review
        return await context.CallActivityAsync<string>(nameof(EscalateForReview), draftContent);
    }

    if (approvalResponse.Approved)
    {
        return await context.CallActivityAsync<string>(nameof(PublishContent), draftContent);
    }

    return "Content rejected";
}
from durabletask.task import OrchestrationContext, when_any
from datetime import timedelta
from agent_framework_azurefunctions import AgentFunctionApp

app = AgentFunctionApp(agents=[content_agent])

@app.orchestration_trigger(context_name="context")
def content_approval_workflow(context: OrchestrationContext, topic: str):
    # Generate content using an agent
    content_agent = app.get_agent(context, "ContentGenerationAgent")
    draft_content = yield content_agent.run(
        messages=f"Write an article about {topic}"
    )

    # Send for human review
    yield context.call_activity("notify_reviewer", input=draft_content.text)

    # Wait for approval with timeout
    approval_task = context.wait_for_external_event("ApprovalDecision")
    timeout_task = context.create_timer(
        context.current_utc_datetime + timedelta(hours=24)
    )

    winner = yield when_any([approval_task, timeout_task])

    if winner == approval_task:
        timeout_task.cancel()
        approval_data = approval_task.result
        if approval_data.get("approved"):
            result = yield context.call_activity("publish_content", input=draft_content.text)
            return result
        return "Content rejected"

    # Timeout occurred - escalate for review
    result = yield context.call_activity("escalate_for_review", input=draft_content.text)
    return result

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

Предоставление человеческих данных

Чтобы отправить утверждение или входные данные в оркестрацию ожидания, создайте внешнее событие в экземпляр оркестрации с помощью пакета SDK для клиента устойчивых задач или конечных точек Функции Azure устойчивых расширений. Например, рецензент может утвердить содержимое через веб-форму, которая вызывает:

await client.RaiseEventAsync(instanceId, "ApprovalDecision", new HumanApprovalResponse 
{ 
    Approved = true,
    Feedback = "Looks great!"
});
approval_data = {
    "approved": True,
    "feedback": "Looks great!"
}
await client.raise_event(instance_id, "ApprovalDecision", approval_data)

Рентабельность

Рабочие процессы с участием человека и долговечными агентами являются чрезвычайно экономичными при размещении на плане потребления функций Azure Flex. Для рабочего процесса, ожидающего 24 часа утверждения, вы оплачиваете только несколько секунд выполнения (время для создания содержимого, отправки уведомления и обработки ответа) — не за 24 часа ожидания. В период ожидания вычислительные ресурсы не используются.

Наблюдаемость с помощью планировщика устойчивых задач

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

Аналитика сеанса агента

  • Журнал бесед: просмотр полного журнала чата для каждого сеанса агента, включая все сообщения, вызовы инструментов и контекст беседы в любой момент времени
  • Время выполнения задачи: мониторинг времени выполнения конкретных задач и взаимодействий с агентом

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

Аналитика оркестрации

  • Визуализация с несколькими агентами: см. поток выполнения при вызове нескольких специализированных агентов с визуальным представлением параллельных выполнений и условной ветвью
  • Журнал выполнения. Доступ к подробным журналам выполнения
  • Мониторинг в режиме реального времени: отслеживание активных оркестраций, поставленных в очередь рабочих элементов и состояний агентов в развертывании
  • Метрики производительности: отслеживайте время отклика агентов, использование токенов и продолжительность оркестрации.

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

Возможности отладки

  • Просмотр структурированных выходных данных агента и результатов вызова средства
  • Вызовы средств трассировки и их результаты
  • Мониторинг обработки внешних событий для сценариев взаимодействия с человеком

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

Миграция развертывания и схемы

Состояние агента Schema-v2 изменяет как сохраняемое состояние, так и удостоверения диспетчера. Планирование сосуществования рабочих ролей отдельно от преобразования состояния.

Новые сеансы используют dafx-v2- пространство имен сущностей. Во время двухфазного развертывания оставьте ProcessLegacyEntities отключенным, пока рабочие роли версии 1 остаются активными. Остановите всех рабочих ролей версии 1, прежде чем включить ProcessLegacyEntities обработку и обновление допустимых устаревших сущностей.

Автономные работники регистрируют фильтры рабочих элементов. Для развертываний параллельных функций также требуются совместимые расширения "Рабочие функции", "Устойчивые рабочие функции" и пакеты расширения рабочих расширений AzureManaged, поддерживающие фильтрацию на стороне узла на каждом принимающем узле, а workItemFilteringEnabled также в конфигурации поставщика хранилища планировщика. Без совместимой фильтрации используйте автономный переход вместо одновременных узлов версии 1 и 2 в одном концентраторе. Следуйте руководству по обновлению .NET для полной конфигурации.

Выберите явную стратегию перед созданием узла:

  • two_phase: используйте планировщик устойчивых задач с совместимой фильтрацией рабочих элементов серверной части. Новые имена версий изолируют отправку, пока допустимые устаревшие сущности остаются на старых рабочих объектах. Остановите старых рабочих ролей перед включением обработки исторических имен и обновлений сущностей на месте. Поддерживать совместимые отфильтрованные рабочие роли во время сосуществования; Фильтры имен не являются постоянными резервированиями, если этот парк отключен.
  • isolated_v2: используйте изолированный концентратор задач с сопоставлением обновленных рабочих и клиентов. Параметр признает изоляцию, но не проверяет наличие других рабочих ролей. Используйте новые экземпляры рабочих процессов.

Новый концентратор не является безусловным требованием для пути миграции двухфазной сущности. См. Python миграцию сущностей для настройки и предварительных требований для конкретного узла.

Warning

Миграция сущностей не восстанавливает совместимость воспроизведения рабочего процесса. Затронутые старые журналы рабочих процессов, включая старые журналы версий 2, не поддерживаются обновленной средой выполнения. Если они должны закончить, сохраните их на своих исходных рабочих и центрах. Запуск новых экземпляров после обновления; Не полагаться только на маркер версии рабочего процесса, чтобы доказать совместимость. См. Python совместимость среды выполнения.

Жизненный цикл состояния и емкость

Выберите политики для каждого слоя независимо:

Слой Что он контролирует
TTL сеанса Удаляет всю сущность, включая состояние беседы и квитанции о завершении.
Хранение устойчивых журналов Удаляет допустимое сохраненное содержимое расшифровки; Защищенное состояние по-прежнему может превышать емкость.
Сжатие входных данных модели Изменение контекста, отправленного в модель; он не обязательно обрезает устойчивую историю.
Хранение результатов Управляет доступностью полезных данных ответа независимо от сохраненного результата завершения.
Жизненный цикл полезных данных BLOB-объектов Управляет большими двоичными объектами полезных данных, загруженными с помощью пакета SDK; Удаление сеанса или очистка оркестрации не очищает их.

В .NET состоянии 14-дневного TTL схемы-версии 2 не будет автоматически удалять сущность. Настройте глобальный или TTL для каждого агента явным образом, если требуется очистка сеанса бездействия. Передача timeToLive: null в AddAIAgent наследование настроенного глобального по умолчанию; она не переопределяет семь дней глобального по умолчанию с "никогда не истекает". Установите для DefaultTimeToLive = null отключения глобального TTL для агентов без положительных переопределений для каждого агента.

.NET по умолчанию DurableAgentHistoryRetentionMode.KeepAll; Auto обеспечивает хранение транскрибирования на основе давления. ResultRetentionPeriod значение по умолчанию составляет 60 секунд и отличается от срока жизни сеанса. Python имеет различные варианты хранения и бюджета, включая retention="keep_all" по умолчанию. Не предполагайте одинаковые параметры или значения по умолчанию между узлами.

Python поддерживает разгрузку полезных данных, управляемых пакетом SDK, управляемым пакетом SDK, в обеих моделях размещения. Настройте как производитель, так и потребительские хранилища, учетные данные и жизненный цикл BLOB-объектов. Разгрузка не удаляет ограничения емкости целой сущности или не заменяет хранение; сохраняйте большие двоичные объекты во время ссылки на состояние или журнал воспроизведения. См. сведения о состоянии и хранении .NET, Python хранении и бюджетах, а также разгрузке BLOB-объектов функций Python.

Сведения о инфраструктуре планировщика, емкости и операционном руководстве см. в разделе "Интеграция устойчивых задач" для Agent Framework.

Руководство. Создание и запуск устойчивого агента с помощью Функции Azure

В этом руководстве показано, как создать и запустить устойчивый агент ИИ с помощью модели размещения Функции Azure для расширения Устойчивый. Вы создадите приложение Функций Azure, в котором размещен агент с отслеживанием состояния со встроенными конечными точками HTTP, и узнайте, как отслеживать его с помощью панели мониторинга планировщика устойчивых задач. Примеры см. в примерах для локальных агентов.

Prerequisites

Перед началом работы убедитесь, что у вас есть следующие предварительные требования:

Замечание

Microsoft Agent Framework поддерживается всеми активно поддерживаемыми версиями .NET. В целях этого примера рекомендуется использовать пакет SDK для .NET 9 или более позднюю версию.

Установите DURABLE_AGENTS_DEPLOYMENT_MODE=isolated_v2 только после подтверждения изоляции центра учебников, а все рабочие и клиенты используют обновленную среду выполнения.

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

Скачивание проекта быстрого запуска

Инициализация нового проекта из шаблона быстрого запуска устойчивых агентов с помощью Интерфейса командной строки разработчика Azure.

  1. Создайте новый каталог для проекта и перейдите к нему:

    mkdir MyDurableAgent
    cd MyDurableAgent
    

  1. Инициализировать проект из шаблона:

    azd init --template durable-agents-quickstart-dotnet
    

    При появлении запроса на имя среды введите имя, например my-durable-agent.

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

  1. Создайте новый каталог для проекта и перейдите к нему:

    mkdir MyDurableAgent
    cd MyDurableAgent
    

  1. Инициализировать проект из шаблона:

    azd init --template durable-agents-quickstart-python
    

    При появлении запроса на имя среды введите имя, например my-durable-agent.

  2. Создайте и активируйте виртуальную среду:

    uv venv --python 3.13 .venv
    source .venv/bin/activate
    

Замечание

Можно также использовать python -m venv .venv с установленным интерпретатором Python 3.13. Если эта команда висит на Windows, используйте указанную uv venv выше команду. Проверьте активный интерпретатор перед python --version установкой пакетов.

  1. Установите необходимые пакеты:

    Обновите шаблон requirements.txt до пакетов функций в начале работы, включая клиентский пакет, перед установкой agent-framework-openai . Устранение конфликтующих закреплений зависимостей в манифесте, а не принудительное их установку.

    uv pip install -r requirements.txt
    

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

Развертывание ресурсов Azure

Используйте CLI разработчика Azure для создания необходимых ресурсов Azure для Durable Agent.

  1. Подготовка инфраструктуры:

    azd provision
    

    Эта команда создает следующее:

    • Служба Azure OpenAI с развертыванием gpt-4o-mini
    • Приложение Функции Azure с тарифным планом Flex Consumption
    • Учетная запись хранения Azure для среды выполнения Функций Azure и устойчивого хранилища
    • Экземпляр планировщика устойчивых задач (план потребления) для управления состоянием агента
    • Необходимые сетевые и идентификационные конфигурации
  2. При появлении запроса выберите подписку Azure и укажите расположение для ресурсов.

Процесс подготовки занимает несколько минут. После завершения azd сохраняет сведения о созданном ресурсе в вашей среде.

Просмотреть код агента

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

Откройте Program.cs , чтобы просмотреть конфигурацию агента:

using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.AzureFunctions;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Hosting;

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") 
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT environment variable is not set");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT") ?? "gpt-4o-mini";

// Create an AI agent following the standard Microsoft Agent Framework pattern
AIAgent agent = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(
        model: deploymentName,
        instructions: "You are a helpful assistant that can answer questions and provide information.",
        name: "MyDurableAgent");

using IHost app = FunctionsApplication
    .CreateBuilder(args)
    .ConfigureFunctionsWebApplication()
    .ConfigureDurableAgents(options => options.AddAIAgent(agent))
    .Build();
app.Run();

Этот код:

  1. Извлекает конфигурацию Azure OpenAI из переменных среды.
  2. Создает клиент Azure OpenAI с помощью учетных данных Azure.
  3. Создает агент ИИ с инструкциями и именем.
  4. Настраивает приложение Функции Azure для размещения агента с использованием надежного управления потоками.

Откройте function_app.py , чтобы просмотреть конфигурацию агента:

import os
from agent_framework_azurefunctions import AgentFunctionApp
from agent_framework.openai import OpenAIChatCompletionClient
from azure.identity import DefaultAzureCredential

endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
if not endpoint:
    raise ValueError("AZURE_OPENAI_ENDPOINT is not set.")
deployment_name = os.getenv("AZURE_OPENAI_DEPLOYMENT", "gpt-4o-mini")
api_version = os.getenv("AZURE_OPENAI_API_VERSION")

# Create an AI agent following the standard Microsoft Agent Framework pattern
agent = OpenAIChatCompletionClient(
    azure_endpoint=endpoint,
    model=deployment_name,
    api_version=api_version,
    credential=DefaultAzureCredential()
).as_agent(
    instructions="You are a helpful assistant that can answer questions and provide information.",
    name="MyDurableAgent"
)

# Configure the function app to host the agent with durable thread management
app = AgentFunctionApp(agents=[agent])

Этот код:

  • Извлекает конфигурацию Azure OpenAI из переменных среды.
  • Создает клиент Azure OpenAI с помощью учетных данных Azure.
  • Создает агент ИИ с инструкциями и именем.
  • Настраивает приложение Функции Azure для размещения агента с использованием надежного управления потоками.

Теперь агент готов к размещению в Функции Azure. Расширение долговечных задач автоматически создает конечные точки HTTP для взаимодействия с вашим агентом и управляет состоянием взаимодействия в рамках нескольких запросов.

Настройка локальных параметров

local.settings.json Создайте файл для локальной разработки на основе примера файла, включенного в проект.

  1. Скопируйте файл параметров примера:

    cp local.settings.sample.json local.settings.json
    

  1. Получите конечную точку Azure OpenAI из подготовленных ресурсов:

    azd env get-value AZURE_OPENAI_ENDPOINT
    
  2. Откройте local.settings.json и замените <your-resource-name> значение конечной AZURE_OPENAI_ENDPOINT точкой из предыдущей команды.

Ваш local.settings.json должен выглядеть следующим образом:

{
  "IsEncrypted": false,
  "Values": {
    // ... other settings ...
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "AZURE_OPENAI_ENDPOINT": "https://your-openai-resource.openai.azure.com",
    "AZURE_OPENAI_DEPLOYMENT": "gpt-4o-mini",
    "DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None",
    "TASKHUB_NAME": "default"
  }
}

Замечание

Файл local.settings.json используется только для локальной разработки и не развертывается в Azure. Для рабочих развертываний эти параметры автоматически настраиваются в приложении "Функции Azure" шаблонами инфраструктуры.

Для Python добавьте "DURABLE_AGENTS_DEPLOYMENT_MODE": "isolated_v2"Values только после подтверждения изоляции центра учебников. Настройте эквивалентный параметр приложения при развертывании; Локальные параметры не передаются автоматически.

Для размещения, поддерживаемого планировщиком, используйте тот же концентратор задач ( host.json через %TASKHUB_NAME%), TASKHUB_NAME, DURABLE_TASK_SCHEDULER_CONNECTION_STRINGэмулятор и панель мониторинга. В этом руководстве используется default, который эмулятор создает автоматически. Если этот концентратор уже содержит старые журналы или используется другими работниками, выберите уникальное, неиспользуемое имя концентратора, задайте для эмулятора DTS_TASK_HUB_NAMES это имя и последовательно обновите параметры приложения и выбор панели мониторинга. Простое определение планировщика строка подключения не выбирает поставщика хранилища планировщика.

В host.jsonполе "Настройка поставщика extensions.durableTaskпланировщика" сохраняется другие параметры узла шаблона:

{
  "extensions": {
    "durableTask": {
      "hubName": "%TASKHUB_NAME%",
      "storageProvider": {
        "type": "AzureManaged",
        "connectionStringName": "DURABLE_TASK_SCHEDULER_CONNECTION_STRING"
      }
    }
  }
}

Используйте зависимости поставщика планировщика для языка размещения. Эта конфигурация выбирает серверную часть для нового изолированного развертывания учебника; Он не включает фильтрацию, необходимую для параллельного обновления.

Запуск локальных зависимостей разработки

Для локального запуска безотказных агентов необходимо запустить две службы:

  • Azurite: эмулирует службы хранилища Azure (используется функциями Azure для управления триггерами и внутренним состоянием).
  • Эмулятор планировщика устойчивых задач (DTS): управление устойчивым состоянием (журнал беседы, состояние оркестрации) и планированием для агентов

В этих шагах предполагается, что узел функций использует поставщик хранилища планировщика устойчивых задач. Примеры функций Python выпуска по умолчанию служба хранилища Azure. Если начать с этих примеров, выберите и настройте поставщика планировщика перед использованием панели мониторинга DTS; В противном случае Azurite содержит устойчивое состояние, а панель мониторинга планировщика остается пустой. См. раздел "Настройка планировщика устойчивых задач".

Запуск Azurite

Azurite эмулирует службы хранилища Azure локально. Функции Azure используют его для управления внутренним состоянием. Вам нужно запустить это в новом окне терминала и поддерживать его работу в процессе разработки и тестирования устойчивого программного агента.

  1. Откройте новое окно терминала и извлеките образ Azurite Docker:

    docker pull mcr.microsoft.com/azure-storage/azurite
    
  2. Запустите Azurite в окне терминала:

    docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.microsoft.com/azure-storage/azurite
    

    Azurite начнет прослушивание на портах по умолчанию для служб Blob (10000), очереди (10001) и таблицы (10002).

Оставьте это окно терминала открытым во время разработки и тестирования долговечного агента.

Tip

Дополнительные сведения об Azurite, включая альтернативные методы установки, см. в статье Об использовании эмулятора Azurite для разработки локальной службы хранилища Azure.

Запустите эмулятор Планировщика устойчивых задач

Эмулятор DTS предоставляет надёжную серверную часть для управления состоянием агента и оркестрациями. Он сохраняет журнал бесед и гарантирует, что состояние агента сохраняется во время перезапуска. Он также активирует долговечные оркестрации и агентов. Вам потребуется запустить это в отдельном новом окне терминала и оставить его работающим, пока вы будете разрабатывать и тестировать устойчивого агента.

  1. Откройте другое новое окно терминала и извлеките образ Docker эмулятора DTS:

    docker pull mcr.microsoft.com/dts/dts-emulator:latest
    
  2. Запустите эмулятор DTS:

    docker run -p 8080:8080 -p 8082:8082 mcr.microsoft.com/dts/dts-emulator:latest
    

    Эта команда создает default концентратор задач и запускает эмулятор, соответствующий параметрам этого учебника. Команда предоставляет:

    • Порт 8080: конечная точка gRPC для планировщика устойчивых задач (используется приложением "Функции")
    • Порт 8082: информационная панель администрирования
  3. Панель мониторинга будет доступна по адресу http://localhost:8082.

Оставьте это окно терминала открытым во время разработки и тестирования долговечного агента.

Tip

Дополнительные сведения о эмуляторе DTS, включая настройку нескольких центров задач и доступ к панели мониторинга, см. в статье "Разработка с помощью планировщика устойчивых задач".

Запустите функциональное приложение

Теперь вы готовы запустить приложение Функций Azure с устойчивым агентом.

  1. В новом окне терминала (оставляя Azurite и эмулятор DTS работающими в отдельных окнах), перейдите в каталог проекта.

  2. Запустите среду выполнения Функций Azure:

    func start
    
  3. Вы увидите выходные данные, указывающие, что приложение-функция запущено, включая конечные точки HTTP для агента:

    Functions:
         http-MyDurableAgent: [POST] http://localhost:7071/api/agents/MyDurableAgent/run
         dafx-v2-MyDurableAgent: entityTrigger
    

Это иллюстрирует регистрацию схемы версии 2 .NET; Python имена триггеров зависят от стратегии развертывания. Эти конечные точки автоматически управляют состоянием беседы, поэтому вам не нужно самостоятельно создавать объекты сеансов.

Тестируйте агента локально

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

Запуск новой беседы

Создайте новый сеанс и отправьте первое сообщение:

curl -i -X POST http://localhost:7071/api/agents/MyDurableAgent/run \
  -H "Content-Type: text/plain" \
  -d "What are three popular programming languages?"

Пример ответа (x-ms-session-idзаголовок содержит идентификатор сеанса; в этом примере показан идентификатор .NET schema-v2):

HTTP/1.1 200 OK
Content-Type: text/plain
x-ms-session-id: @dafx-v2-mydurableagent@263fa373-fa01-4705-abf2-5a114c2bb87d
Content-Length: 189

Three popular programming languages are Python, JavaScript, and Java. Python is known for its simplicity and readability, JavaScript powers web interactivity, and Java is widely used in enterprise applications.

Сохраните точный идентификатор сеанса из заголовка x-ms-session-id для следующего запроса. Не создавайте или перезаписывайте его. Python также возвращает этот заголовок, но его формат идентификатора может отличаться.

Продолжить беседу

Отправьте следующее сообщение в тот же сеанс, включив возвращенный идентификатор в канонический sessionId параметр запроса:

Замените идентификатор примера фактическим значением из заголовка предыдущего x-ms-session-id ответа. При необходимости закодируйте значение в URL-коде.

curl -X POST "http://localhost:7071/api/agents/MyDurableAgent/run?sessionId=@dafx-v2-mydurableagent@263fa373-fa01-4705-abf2-5a114c2bb87d" \
  -H "Content-Type: text/plain" \
  -d "Which one is best for beginners?"

Пример ответа:

Python is often considered the best choice for beginners among those three. Its clean syntax reads almost like English, making it easier to learn programming concepts without getting overwhelmed by complex syntax. It's also versatile and widely used in education.

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

Мониторинг с помощью панели планировщика долговременных задач

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

Доступ к панели мониторинга

  1. Откройте панель мониторинга для локального эмулятора http://localhost:8082 DTS в веб-браузере.

  2. Выберите значение по умолчанию или одно и то же уникальное имя концентратора, которое вы настроили в приложении и эмуляторе, чтобы просмотреть его сведения.

  3. Щелкните значок шестеренки в правом верхнем углу, чтобы открыть параметры, и убедитесь, что выбран параметр "Включить страницы агента " в разделе "Предварительные версии компонентов ".

Изучение бесед агентов

  1. На панели мониторинга перейдите на вкладку "Агенты ".

  2. Выберите в списке поток устойчивых агентов (например, mydurableagent - 263fa373-fa01-4705-abf2-5a114c2bb87d).

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

    Снимок экрана панели управления Durable Task Scheduler, показывающий историю переписки потоков агента.

Панель мониторинга предоставляет представление временной шкалы для понимания потока беседы. К ключевым сведениям относятся:

  • Метки времени и длительность каждого взаимодействия
  • Содержимое запроса и ответа
  • Количество используемых токенов

Tip

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

Развертывание в Azure

Теперь, когда вы протестировали устойчивый агент локально, разверните его в Azure.

  1. Разверните приложение:

    azd deploy
    

    Эта команда упаковывает приложение и развертывает его в приложении Функции Azure, созданном во время подготовки.

  2. Дождитесь завершения развертывания. Когда ваш агент будет запущен в Azure, выходные данные подтвердят это.

Тестирование развернутого агента

После развертывания проверьте агент, работающий в Azure.

Получение ключа функции

Для авторизации на уровне функций по умолчанию созданных конечных точек добавьте ключ Функций в запросы на Azure. Ключ функций не является авторизацией пользователя приложения; см. сведения о рабочей безопасности и устранении неполадок.

API_KEY=`az functionapp function keys list --name $(azd env get-value AZURE_FUNCTION_NAME) --resource-group $(azd env get-value AZURE_RESOURCE_GROUP) --function-name http-MyDurableAgent --query default -o tsv`

Запуск новой беседы в Azure

Создайте новый сеанс и отправьте первое сообщение в развернутый агент:

curl -i -X POST "https://$(azd env get-value AZURE_FUNCTION_NAME).azurewebsites.net/api/agents/MyDurableAgent/run?code=$API_KEY" \
  -H "Content-Type: text/plain" \
  -d "What are three popular programming languages?"

Сохраните идентификатор сеанса, возвращенный в заголовке x-ms-session-id ответа.

Продолжить беседу в Azure

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

SESSION_ID="<session-id>"
curl -X POST "https://$(azd env get-value AZURE_FUNCTION_NAME).azurewebsites.net/api/agents/MyDurableAgent/run?code=$API_KEY" \
  --url-query "sessionId=$SESSION_ID" \
  -H "Content-Type: text/plain" \
  -d "Which is easiest to learn?"

Агент поддерживает контекст беседы в Azure так же, как и локально, демонстрируя устойчивость состояния агента.

Мониторьте развернутого агента

Вы можете следить за развернутым агентом с помощью панели мониторинга планировщика долговременных задач в Azure.

  1. Получите имя экземпляра планировщика устойчивых задач:

    azd env get-value DTS_NAME
    
  2. Откройте портал Azure и найдите имя планировщика устойчивых задач на предыдущем шаге.

  3. В колонке обзора ресурса планировщика устойчивых задач выберите концентратор задач, настроенный для развернутого приложения.

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

  5. Просматривайте беседы агента так же, как и в локальном эмуляторе.

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

Руководство. Оркестрация устойчивых агентов с помощью Функции Azure

В этом руководстве показано, как оркестрировать несколько устойчивых агентов ИИ с помощью модели размещения Функции Azure и шаблона вентилятора или вентилятора. Вы расширите устойчивый агент из предыдущего руководства , чтобы создать систему с несколькими агентами, которая обрабатывает вопрос пользователя, а затем преобразует ответ на несколько языков одновременно. Примеры локальной оркестрации см. в примерах.

Общие сведения о шаблоне оркестрации

Оркестрация, которую вы создадите, следует этому потоку:

  1. Входные данные пользователя — вопрос или сообщение от пользователя
  2. Главный агент — MyDurableAgent из первого туториала обрабатывает вопрос
  3. Фан-аут — ответ основного агента отправляется одновременно обоим агентам перевода
  4. Агенты перевода — два специализированных агента переводят ответ (французский и испанский)
  5. Fan-in — результаты собираются в единый ответ JSON, содержащий исходный ответ и переводы

Этот шаблон позволяет одновременно обрабатывать, уменьшая общее время отклика по сравнению с последовательным переводом.

Регистрация агентов при запуске

Чтобы корректно использовать агентов в стабильных оркестрациях, зарегистрируйте их при запуске приложения. Их можно использовать в различных случаях выполнения оркестрации.

Обновите ваш Program.cs, чтобы зарегистрировать агентов перевода вместе с существующим MyDurableAgent.

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.AzureFunctions;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Hosting;

// Get the Azure OpenAI configuration
string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT")
    ?? "gpt-4o-mini";

// Create the Microsoft Foundry client
AIProjectClient client = new(new Uri(endpoint), new DefaultAzureCredential());

// Create the main agent from the first tutorial
AIAgent mainAgent = client.AsAIAgent(
    model: deploymentName,
    instructions: "You are a helpful assistant that can answer questions and provide information.",
    name: "MyDurableAgent");

// Create translation agents
AIAgent frenchAgent = client.AsAIAgent(
    model: deploymentName,
    instructions: "You are a translator. Translate the following text to French. Return only the translation, no explanations.",
    name: "FrenchTranslator");

AIAgent spanishAgent = client.AsAIAgent(
    model: deploymentName,
    instructions: "You are a translator. Translate the following text to Spanish. Return only the translation, no explanations.",
    name: "SpanishTranslator");

// Build and configure the Functions host
using IHost app = FunctionsApplication
    .CreateBuilder(args)
    .ConfigureFunctionsWebApplication()
    .ConfigureDurableAgents(options =>
    {
        // Register all agents for use in orchestrations and HTTP endpoints
        options.AddAIAgent(mainAgent);
        options.AddAIAgent(frenchAgent);
        options.AddAIAgent(spanishAgent);
    })
    .Build();

app.Run();

Обновите ваш function_app.py, чтобы зарегистрировать агентов перевода вместе с существующим MyDurableAgent.

import os
from azure.identity import DefaultAzureCredential
from agent_framework_azurefunctions import AgentFunctionApp
from agent_framework.openai import OpenAIChatCompletionClient

# Get the Azure OpenAI configuration
endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
if not endpoint:
    raise ValueError("AZURE_OPENAI_ENDPOINT is not set.")
deployment_name = os.getenv("AZURE_OPENAI_DEPLOYMENT", "gpt-4o-mini")
api_version = os.getenv("AZURE_OPENAI_API_VERSION")

# Create the Azure OpenAI client
chat_client = OpenAIChatCompletionClient(
    azure_endpoint=endpoint,
    model=deployment_name,
    api_version=api_version,
    credential=DefaultAzureCredential()
)

# Create the main agent from the first tutorial
main_agent = chat_client.as_agent(
    instructions="You are a helpful assistant that can answer questions and provide information.",
    name="MyDurableAgent"
)

# Create translation agents
french_agent = chat_client.as_agent(
    instructions="You are a translator. Translate the following text to French. Return only the translation, no explanations.",
    name="FrenchTranslator"
)

spanish_agent = chat_client.as_agent(
    instructions="You are a translator. Translate the following text to Spanish. Return only the translation, no explanations.",
    name="SpanishTranslator"
)

# Create the function app and register all agents
app = AgentFunctionApp(agents=[main_agent, french_agent, spanish_agent])

Создание функции оркестрации

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

Создайте файл с именем AgentOrchestration.cs в каталоге проекта:

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.DurableTask;
using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;

namespace MyDurableAgent;

public static class AgentOrchestration
{
    // Define a strongly-typed response structure for agent outputs
    public sealed record TextResponse(string Text);

    [Function("agent_orchestration_workflow")]
    public static async Task<Dictionary<string, string>> AgentOrchestrationWorkflow(
        [OrchestrationTrigger] TaskOrchestrationContext context)
    {
        var input = context.GetInput<string>() ?? throw new ArgumentNullException(nameof(context), "Input cannot be null");

        // Step 1: Get the main agent's response
        DurableAIAgent mainAgent = context.GetAgent("MyDurableAgent");
        AgentResponse<TextResponse> mainResponse = await mainAgent.RunAsync<TextResponse>(input);
        string agentResponse = mainResponse.Result.Text;

        // Step 2: Fan out - get the translation agents and run them concurrently
        DurableAIAgent frenchAgent = context.GetAgent("FrenchTranslator");
        DurableAIAgent spanishAgent = context.GetAgent("SpanishTranslator");

        Task<AgentResponse<TextResponse>> frenchTask = frenchAgent.RunAsync<TextResponse>(agentResponse);
        Task<AgentResponse<TextResponse>> spanishTask = spanishAgent.RunAsync<TextResponse>(agentResponse);

        // Step 3: Wait for both translation tasks to complete (fan-in)
        await Task.WhenAll(frenchTask, spanishTask);

        // Get the translation results
        TextResponse frenchResponse = (await frenchTask).Result;
        TextResponse spanishResponse = (await spanishTask).Result;

        // Step 4: Combine results into a dictionary
        var result = new Dictionary<string, string>
        {
            ["original"] = agentResponse,
            ["french"] = frenchResponse.Text,
            ["spanish"] = spanishResponse.Text
        };

        return result;
    }
}

Добавьте функцию оркестрации в function_app.py файл:

from durabletask.task import OrchestrationContext, when_all

@app.orchestration_trigger(context_name="context")
def agent_orchestration_workflow(context: OrchestrationContext, input_text: str):
    """
    Orchestration function that coordinates multiple agents.
    Returns a dictionary with the original response and translations.
    """
    # Step 1: Get the main agent's response
    main_agent = app.get_agent(context, "MyDurableAgent")
    main_response = yield main_agent.run(input_text)
    agent_response = main_response.text

    # Step 2: Fan out - get the translation agents and run them concurrently
    french_agent = app.get_agent(context, "FrenchTranslator")
    spanish_agent = app.get_agent(context, "SpanishTranslator")

    parallel_tasks = [
        french_agent.run(agent_response),
        spanish_agent.run(agent_response)
    ]

    # Step 3: Wait for both translation tasks to complete (fan-in)
    translations = yield when_all(parallel_tasks)

    # Step 4: Combine results into a dictionary
    result = {
        "original": agent_response,
        "french": translations[0].text,
        "spanish": translations[1].text
    }

    return result

Замечание

В этом руководстве рассматриваются C# и Python размещение устойчивых расширений. Сведения о размещении Go см. в разделе "Размещение A2A " и репозиторий Agent Framework Go.

Тестирование оркестрации

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

  • Azurite в одном окне терминала
  • Эмулятор планировщика устойчивых задач в другом окне терминала

При запуске локальных зависимостей разработки:

  1. Запустите приложение Функций Azure в новом окне терминала:

    func start
    
  2. Расширение Устойчивые функции автоматически создает встроенные HTTP точки входа для управления оркестрациями. Запустите оркестрацию с помощью встроенного API:

    curl -X POST http://localhost:7071/runtime/webhooks/durabletask/orchestrators/agent_orchestration_workflow \
      -H "Content-Type: application/json" \
      -d '"\"What are three popular programming languages?\""'
    

  1. Ответ содержит URL-адреса для управления оркестрационным экземпляром.

    {
      "id": "abc123def456",
      "statusQueryGetUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456",
      "sendEventPostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456/raiseEvent/{eventName}",
      "terminatePostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456/terminate",
      "purgeHistoryDeleteUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456"
    }
    
  2. Запросите состояние оркестрации с помощью команды statusQueryGetUri (замените abc123def456 на фактический идентификатор вашего экземпляра).

    curl http://localhost:7071/runtime/webhooks/durabletask/instances/abc123def456
    

  1. Выполняйте опрос состояния конечной точки до тех пор, пока runtimeStatus не станет Completed. По завершении вы увидите результаты оркестрации с ответом главного агента и его переводами.

    {
      "name": "agent_orchestration_workflow",
      "instanceId": "abc123def456",
      "runtimeStatus": "Completed",
      "output": {
        "original": "Three popular programming languages are Python, JavaScript, and Java. Python is known for its simplicity...",
        "french": "Trois langages de programmation populaires sont Python, JavaScript et Java. Python est connu pour sa simplicité...",
        "spanish": "Tres lenguajes de programación populares son Python, JavaScript y Java. Python es conocido por su simplicidad..."
      }
    }
    

Отслеживайте оркестрацию на информационной панели

Панель мониторинга планировщика задач Durable Task Scheduler обеспечивает видимость вашей оркестрации:

  1. Откройте http://localhost:8082 в браузере.

  2. Выберите центр задач, настроенный для приложения.

  3. Перейдите на вкладку "Оркестрации".

  4. Найдите экземпляр оркестрации в списке.

  5. Выберите экземпляр, чтобы увидеть:

    • Временная шкала оркестрации
    • Выполнение основного агента, за которым следует параллельные агенты перевода
    • Каждое выполнение агента (MyDurableAgent, затем запуск французского и испанского переводчиков)
    • Визуализация моделей расширения и объединения
    • Время и длительность каждого шага

Развертывание оркестрации в Azure

Разверните обновленное приложение с помощью Интерфейса командной строки разработчика Azure:

azd deploy

Это позволяет развернуть обновленный код с новой функцией оркестрации и дополнительными агентами в приложении Функции Azure, созданном в первом руководстве.

Протестируйте развернутую оркестрацию

После развертывания проверьте оркестрацию, запущенную в Azure.

  1. Получите системный ключ для устойчивого расширения:

    SYSTEM_KEY=$(az functionapp keys list --name $(azd env get-value AZURE_FUNCTION_NAME) --resource-group $(azd env get-value AZURE_RESOURCE_GROUP) --query "systemKeys.durabletask_extension" -o tsv)
    

  1. Запустите оркестрацию с помощью встроенного API:

    curl -X POST "https://$(azd env get-value AZURE_FUNCTION_NAME).azurewebsites.net/runtime/webhooks/durabletask/orchestrators/agent_orchestration_workflow?code=$SYSTEM_KEY" \
      -H "Content-Type: application/json" \
      -d '"\"What are three popular programming languages?\""'
    

  1. Используйте statusQueryGetUri из ответа, чтобы опросить статус завершения и просмотреть результаты с переводами.

Безопасность и устранение неполадок в рабочей среде

Обработайте эти границы доступа отдельно:

  • Пользователи приложения: Проверка подлинности вызывающих лиц и авторизация доступа к каждому сеансу, рабочему процессу и ответу на утверждение человека. Идентификаторы сеансов, корреляции и запросов — это идентификаторы, а не учетные данные.
  • Конечные точки функций: Ключи уровня функций защищают созданные конечные точки HTTP, но не устанавливают удостоверение пользователя приложения или владение сеансом. Защита и поворот ключей; Не предоставляйте их в коде приложения, доставленном в браузере.
  • Доступ к модели: Предоставьте удостоверению рабочей роли необходимые разрешения модели. Учетные данные модели не предоставляют доступ к планировщику или к сеансу другого пользователя.
  • Доступ планировщика: Настройте разрешения рабочей роли, клиента и панели мониторинга для их предполагаемых ролей. Рекомендации по инфраструктуре см. в разделе "Интеграция устойчивых задач".
Симптом Проверка
сбой установки пакета Python или запуска функций Используйте Python 3.13 или более поздней версии для функций, установите пакеты функций в начале работы и явно выберите стратегию развертывания. Автономный Python минимум отличается.
Запросы успешно выполнены, но панель мониторинга DTS пуста Убедитесь, что поставщик хранилища функций не AzureStorageявляется AzureManagedи что конечная точка планировщика и концентратор задач соответствуют панели мониторинга.
Сеанс, как представляется, теряет контекст Повторно используйте точное возвращаемое x-ms-session-id значение с sessionId; проверьте наличие другого концентратора, пространства имен развертывания или настройки очистки сеанса.
Сбой старых рабочих процессов после обновления Проверьте совместимость воспроизведения перед возобновлением исторических запусков. Миграция сущностей не восстанавливает несовместимые журналы рабочих процессов.
Поток завершается, но устойчивое завершение отсутствует Рассматривайте выходные данные потока как временные и проверяйте достоверный результат или сохраняемый результат. Маркер завершения потока не является устойчивым подтверждением фиксации.
Завершенная операция возвращается 410 Проверьте сохраненный результат и доступность результатов. Не предполагайте, что сбой, продолжайте опрос, как в ожидании или автоматически отправьте новую операцию.
Записи в состоянии сущности превышают емкость Проверьте состояние целой сущности, защищенные записи, политику хранения и ссылки на полезные данные. Только сжатие входных данных модели не гарантирует соответствие хранимого состояния.

Дальнейшие действия

Дополнительные ресурсы: