Human-in-the-loop для агентных рабочих процессов в здравоохранении и бионауках на AWS

В здравоохранении и науках о жизни ИИ-агенты помогают организациям обрабатывать клинические данные, подавать регуляторные документы, автоматизировать медицинское кодирование и ускорять разработку и коммерциализацию лекарств. Однако чувствительный характер медицинских данных и нормативные требования, такие как соблюдение надлежащей практики (GxP), требуют человеческого контроля в ключевых точках принятия решений. Именно здесь конструкции human-in-the-loop (HITL) становятся необходимыми. В этом посте вы узнаете о четырех практических подходах к внедрению конструкций human-in-the-loop с использованием сервисов AWS.

Почему human-in-the-loop важен в здравоохранении

Организации здравоохранения и наук о жизни сталкиваются с уникальными вызовами при развертывании ИИ-агентов:

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

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

Требования к аудиту — медицинским системам нужна полная прослеживаемость того, кто, какие действия и когда одобрил.

Чувствительность данных — защищенная медицинская информация (PHI) требует явного разрешения перед доступом или изменением.

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

Обзор решения

Мы представляем четыре взаимодополняющих подхода к внедрению HITL в агентных рабочих процессах. Каждый рабочий процесс подходит для разных сценариев и профилей риска, как описано в нашем руководстве по созданию ИИ-агентов в средах GxP. Мы строим эти шаблоны с использованием фреймворка Strands Agents, среды выполнения Amazon Bedrock AgentCore и Model Context Protocol (MCP), с примерами кода, которые можно адаптировать под собственные сценарии.

  1. Прерывание агентного цикла (система хуков агентного фреймворка) — мы используем хуки Strands Agent Framework, чтобы реализовать политику human-in-the-loop. С помощью хуков мы можем перехватывать вызовы инструментов до их выполнения.
  2. Прерывание в контексте инструмента — логику согласования human-in-the-loop можно также встроить непосредственно в саму логику инструмента для тонкого, специфичного для конкретного инструмента контроля и гибкости. Контекст сессии можно использовать для пользовательской логики согласования.
  3. Удаленное прерывание инструмента (AWS Step Functions) — в некоторых случаях может понадобиться отправить запрос на согласование внешней системе или человеку асинхронно. Мы демонстрируем этот шаблон, отправляя уведомление внешнему согласующему через Amazon Simple Notification Service (Amazon SNS). Сессия агента продолжается без блокировки, пока согласование выполняется в фоновом режиме.
  4. MCP elicitation — в протоколе MCP недавно появился механизм elicitation, который используется серверами для запроса дополнительной информации у пользователей через клиент во время взаимодействия. Нативный протокол elicitation MCP позволяет выполнять согласование в реальном времени, в интерактивном режиме, используя события, отправляемые сервером (SSE), для состояний и двусторонней связи.

Архитектура

Архитектура решения использует Strands Agents Framework для управления жизненным циклом агента и обработки прерываний, развернутый на Amazon Bedrock AgentCore Runtime для бессерверной масштабируемости и изоляции сессий. AWS Step Functions координирует асинхронные потоки согласования с Amazon SNS, а MCP-серверы предоставляют инструменты агенту через MCP — также развернутые на AgentCore Runtime.

Детали реализации

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

Каждый из следующих методов демонстрирует самостоятельный подход. Агент развертывается в Amazon Bedrock AgentCore Runtime с доступом к инструментам здравоохранения разного уровня чувствительности. Низкорисковые операции, например получение имени пациента, выполняются без согласования, тогда как высокорисковые действия, например получение жизненных показателей или медицинских состояний, требуют человеческого разрешения. Такие операции, как выписка пациента, требуют внешнего одобрения супервайзера по электронной почте.

Метод 1: локальное прерывание инструмента через хук агентного цикла

Strands Agent Framework предоставляет систему хуков, которая перехватывает вызовы инструментов до выполнения на уровне цикла агента. Это обеспечивает единую политику HITL для чувствительных инструментов без изменения самих инструментов.

HookProvider регистрирует callback для BeforeToolCallEvent. Когда вызывается чувствительный инструмент, хук инициирует interrupt, приостанавливая цикл агента до ответа человека. Пользователь может ответить «y» (одобрить один раз), «n» (отклонить) или «t» (доверять — одобрить этот инструмент на оставшуюся часть сессии):

class ApprovalHook(HookProvider):
    SENSITIVE_TOOLS = ["get_patient_condition", "get_patient_vitals"]

    def register_hooks(self, registry: HookRegistry, **kwargs: Any) -> None:
        registry.add_callback(BeforeToolCallEvent, self.approve)

    def approve(self, event: BeforeToolCallEvent) -> None:
        tool_name = event.tool_use["name"]
        if tool_name not in self.SENSITIVE_TOOLS:
            return
# Пропустить, если пользователь ранее выбрал «доверять всегда» для этого инструмента
        approval_key = f"{tool_name}-approval"
if event.agent.state.get(approval_key) == "t":
            return

        approval = event.interrupt(
            approval_key,
            reason={"reason": f"Authorize {tool_name} with args: {event.tool_use.get('input', {})}"},
        )
        if approval.lower() not in ["y", "yes", "t"]:
            event.cancel_tool = f"User denied permission to run {tool_name}"
return
if approval.lower() == "t":
            event.agent.state.set(approval_key, "t")  # доверять инструменту до конца сессии

Хук прикрепляется к агенту при создании — инструменты остаются полностью неосведомленными о логике согласования:

agent = Agent(
    hooks=[ApprovalHook()],
    tools=[get_patient_name, get_patient_condition, get_patient_vitals],
)

Метод 2: прерывание в контексте инструмента

Вместо централизованного хука логика согласования встраивается непосредственно в каждый инструмент с помощью tool_context.interrupt(). Это дает тонкий, помодульный контроль: каждый инструмент может реализовать собственные правила доступа на основе контекста сессии. В этом примере сессия агента содержит user_role. Общая функция check_access обеспечивает доступ на основе роли: в нашем примере кода не-врачи сразу получают отказ, а врачам предлагается подтвердить доступ. Как и в методе 1, опция доверия кэширует одобрение на время сессии:

def check_access(tool_context, patient_id: str, action: str):
    user_role = tool_context.agent.state.get("user_role") or "Non-Physician"
if user_role != "Physician":
        return f"Access denied: {action} requires Physician role (current: {user_role})"

    approval_key = f"{action}-{patient_id}-approval"
if tool_context.agent.state.get(approval_key) == "t":
        return None # ранее доверено

    approval = tool_context.interrupt(
        approval_key,
        reason={"reason": f"[{user_role}] Authorize {action} for patient {patient_id}"},
    )
    if approval.lower() not in ["y", "yes", "t"]:
        return f"Physician denied access to {action} for patient {patient_id}"
if approval.lower() == "t":
        tool_context.agent.state.set(approval_key, "t")
    return None # одобрено

Метод 3: асинхронное одобрение инструмента с использованием AWS Step Functions

Во многих корпоративных сценариях процесс согласования требует одобрения от стороннего уполномоченного лица, которое не является тем, кто вызывает агента. Это предполагает асинхронный рабочий процесс согласования, который может работать независимо от сессии агента. Один из эффективных подходов — использовать AWS Step Functions для оркестрации этих внешних процессов одобрения.

В этом шаблоне инструмент агента запускает рабочий процесс Step Functions, который отправляет запрос на одобрение внешнему согласующему через уведомление по электронной почте с использованием Amazon SNS. Инструмент опрашивает результат одобрения и соответственно обновляет состояние сессии агента. Пользователь также может позже проверить статус одобрения с помощью отдельного инструмента check_discharge_status. Инструмент discharge_patient запускает выполнение Step Functions и опрашивает результат:

@tool(context=True)
def discharge_patient(tool_context, patient_id: str, reason: str) -> str:
    # Пропустить рабочий процесс, если в этой сессии уже есть одобрение
if tool_context.agent.state.get("external-approver-state") == "approved":
        return f"Patient {patient_id} discharged (pre-approved). Reason: {reason}"

    response = sfn_client.start_execution(
        stateMachineArn=state_machine_arn,
        input=json.dumps({"patient_id": patient_id, "action": "discharge", "reason": reason}),
    )
    return f"Waiting for approval. Execution ARN: {response['executionArn']}"

Такой асинхронный подход позволяет выполнять неблокирующие операции, когда пользователям не приходится ждать согласований, которые могут занимать часы или дни, а выполнение агента может продолжаться независимо. Step Functions ведет подробные журналы аудита с полной историей выполнения, сохраняет состояние между тайм-аутами сессий и интегрируется с существующими корпоративными каналами связи, такими как электронная почта, Slack или Microsoft Teams. Пользователь, запускающий чувствительный рабочий процесс, инициирует State Function: агент возвращает пользователю подтверждение, что рабочий процесс был запущен. В любой момент пользователь может проверить обновление состояния, чтобы убедиться, что рабочий процесс завершился.

Метод 4: MCP elicitation

В протоколе MCP недавно был представлен протокол elicitation, который позволяет MCP-серверам запрашивать у пользователей дополнительную информацию или одобрение во время выполнения инструмента. Этот подход следует стандартам протокола и предоставляет динамический механизм для запроса у пользователей во время выполнения без необходимости жестко задавать параметры заранее. Его можно использовать для авторизации вызова инструмента и добавления делового обоснования.

Когда вызывается чувствительный инструмент, MCP-сервер приостанавливает выполнение и отправляет запрос на одобрение обратно через MCP-клиент конечному пользователю. Пользователь видит запрос, принимает решение, после чего сервер возобновляет работу — либо продолжая операцию, либо отказывая в доступе. Эта двусторонняя связь обеспечивается транспортом MCP streamable HTTP, который поддерживает состоявшееся соединение между клиентом и сервером.

На MCP-сервере логика одобрения сводится к одному вызову ctx.elicit() внутри каждого чувствительного инструмента:

@server.tool
async def get_patient_condition(patient_id: str, ctx: Context) -> str:
 """Получить состояние пациента. Чувствительный — требуется одобрение через MCP elicitation."""
    result = await ctx.elicit(
        f"⚠️ Одобрить доступ к ЧУВСТВИТЕЛЬНЫМ данным о состоянии пациента {patient_id}?"
    )
    if result.action != "accept":
        return f"Access to condition data for patient {patient_id} DENIED."
return f"Patient {patient_id} condition: Hypertension Stage 2, Type 2 Diabetes"

На стороне агента с MCP-клиентом регистрируется elicitation_callback. Когда сервер вызывает ctx.elicit(), этот callback срабатывает, передавая запрос на одобрение пользователю и возвращая его решение обратно на сервер. Для локальных агентов это приглашение в терминале. Для агентов, развернутых в AgentCore Runtime, мы используем соединение WebSocket, чтобы в реальном времени передавать elicitation удаленному конечному пользователю:

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

Заключение

Вы можете использовать эти конструкции human-in-the-loop (HITL) для создания безопасных и соответствующих требованиям развертываний ИИ-агентов в здравоохранении и науках о жизни. Внедрив подходящий HITL-шаблон для своего сценария, вы сможете разворачивать готовые к производству рабочие процессы, которые масштабируются от пилотных проектов до корпоративного уровня. Начните с определения операций в своем рабочем процессе, которые требуют человеческого контроля. Затем выберите HITL-подход, который соответствует вашим требованиям к согласованию: централизованный (метод 1), специфичный для инструмента (метод 2), асинхронный (метод 3) или в реальном времени (метод 4).

Подробнее об Amazon Bedrock AgentCore см. в документации Amazon Bedrock AgentCore.


Материал — перевод статьи с английского.

Оригинал: Human-in-the-loop constructs for agentic workflows in healthcare and life sciences