医療・生命科学分野におけるエージェントワークフローへの人間参加型構造
本文の状態
日本語全文を表示中
詳細モードで約12分の本文を読めます。
同じ出来事の情報源
この情報源を基点に整理
AWS Machine Learning Blog
医療・生命科学分野では、AIエージェントが臨床データ処理や規制申請、医療コーディングの自動化、医薬品開発の加速を支援するが、医療データの機密性やGxP準拠などの規制要件により、重要な意思決定ポイントでの人間の監視が必要である。人間参加型(HITL)構造が不可欠となる。
Continue in AI NEW LAB
このニュースを、実務の判断につなげる
AI NEW LABで、試したことや先に確認したい条件を共有できます。まずはログインなしで読めます。
AI NEW LABで論点を見るSource Article
元記事を日本語で読む
本文に関係しない購読案内、埋め込み通知、サイト内プロモーションは除いています。
医療およびライフサイエンス分野において、AIエージェントは組織が臨床データを処理し、規制関連の申請を提出し、医療コードの自動化を行い、創薬開発と商業化を加速することを支援します。しかし、医療データの機密性の高さやGxP(Good Practice:適正な運用規範)遵守といった規制要件により、重要な意思決定のポイントでは人間の監督が必要です。ここで重要となるのが、ヒューマン・イン・ザ・ループ(HITL:Human-in-the-loop)の仕組みです。本稿では、AWSサービスを用いてヒューマン・イン・ザ・ループの仕組みを実装するための4つの実用的なアプローチについて解説します。
医療分野においてヒューマン・イン・ザ・ループが重要な理由
医療およびライフサイエンス組織は、AIエージェントを導入する際に独自の課題に直面しています:
規制遵守 – GxP規制では、機密性の高い業務に対して人間の監督が義務付けられています。例えば、患者記録の削除や臨床試験プロトコルの改訂は、文書化された承認がない限り実行できません。
患者の安全 – 患者の治療に影響を与える医療判断は、実行前に臨床的な検証が必要です。
監査要件 – 医療システムでは、誰がどの行動をいつ承認したかという完全な追跡可能性が必要です。
データの機密性 – 保護医療情報(PHI:Protected Health Information)へのアクセスや改訂には、明示的な承認が必要です。
ヒューマン・イン・ザ・ループの仕組みは、これらの要件を満たしつつ、エージェント型自動化による効率化のメリットを維持するために必要な制御ポイントを提供します。
解決策の概要
ヒューマン・イン・ザ・ループ(HITL)をアジェンティック・ワークフローに実装するための、4つの補完的なアプローチをご紹介します。各ワークフローは、GxP環境におけるAIエージェント構築ガイドで説明されている通り、異なるシナリオやリスクプロファイルに適しています。これらのパターンは、Strands Agentsフレームワーク、Amazon Bedrock AgentCoreランタイム、およびModel Context Protocol(MCP)を使用して構築されており、独自のユースケースに適用可能なコード例も提供しています。
- エージェント・ループ・インターラプト(エージェント・フレームワーク・フック・システム) – 人間在ループのポリシーを適用するために、Strands Agent Framework のフック機能を使用します。このフックにより、ツール呼び出しの実行前にそれをインターセプト(傍受)することができます。
- ツール・コンテキスト・インターラプト – 人間在ループの承認ロジックは、ツール固有の細粒度な制御と柔軟性を実現するため、ツール内のロジック直接に実装することも可能です。セッションコンテキストを使用して、カスタムの承認ロジックを適用できます。
- リモート・ツール・インターラプト(AWS Step Functions) – 場合によっては、承認リクエストを非同期で第三者システムや担当者に送信したいことがあります。このパターンとして、Amazon Simple Notification Service(Amazon SNS)を使用して外部の承認者へ通知を送る例を示します。承認処理がバックグラウンドで進行している間、エージェントセッションはブロックされずに継続されます。
- MCP エリシテーション – MCP プロトコルは最近、エリシテーション(情報 elicitation)を導入しました。これは、サーバーがクライアントを介してユーザーから追加情報を要求するために使用されます。MCP のネイティブなエリシテーションプロトコルは、ステートフルな双方向通信のためにサーバー送信イベント(SSE)を用いたリアルタイムの対話型承認を可能にします。
アーキテクチャ
本ソリューションのアーキテクチャは、エージェントのライフサイクル管理およびインターラプト(中断)処理にStrands Agents Frameworkを使用し、サーバーレスのスケーラビリティとセッションの分離を実現するためにAmazon Bedrock AgentCore Runtime上にデプロイされています。AWS Step FunctionsはAmazon SNSと連携して非同期の承認ワークフローをオーケストレーションし、MCPサーバーはAgentCore Runtime上でデプロイされながら、エージェントにMCPを通じてツールを公開しています。
実装の詳細
これらのアーキテクチャパターンに関連するすべてのコードは、GitHubリポジトリで公開されています。
以下の各メソッドは、それぞれ独立したアプローチを示しています。エージェントはAmazon Bedrock AgentCore Runtime上にデプロイされ、異なる機密性レベルの医療関連ツールにアクセス可能です。患者名を検索するなどの低リスク操作は承認なしで実行されますが、バイタルサインや病状の取得といった高リスクアクションには人間の承認が必要です。患者の退院処理などの操作では、メール通知を通じて外部の監督者による承認が必要となります。
メソッド1:エージェントループフックローカルツールインターラプト
Strands Agent Frameworkは、エージェントループレベルでの実行前にツール呼び出しをインターセプトするフックシステムを提供します。これにより、ツール自体を変更することなく、機密性の高いツール全体にHITL(Human-in-the-Loop:人間を介したループ)ポリシーを一括適用できます。
HookProvider は BeforeToolCallEvent にコールバックを登録します。機密性の高いツールが呼び出されると、このフックはインターラプト(中断)を発生させ、人間の応答があるまでエージェントのループを一時停止します。ユーザーは「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") # trust tool for the rest of the session
このフックはコンストラクション時にエージェントにアタッチされ、ツールは承認ロジックを完全に認識しません:
agent = Agent(
hooks=[ApprovalHook()],
tools=[get_patient_name, get_patient_condition, get_patient_vitals],
)
Method 2: Tool context interrupt
中央集権型のフックではなく、承認ロジックは tool_context.interrupt() を使用して各ツール内に直接埋め込まれます。これにより、きめ細かなツールごとの制御が可能になります。各ツールはセッションコンテキストに基づいて独自のアクセスルールを実装できます。この例では、エージェントセッションには user_role が含まれています。共有関数 check_access はロールベースのアクセスを強制します。コード例では、非医師は完全にアクセスが拒否され、医師には承認プロンプトが表示されます。Method 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 # previously trusted
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 # approved
Method 3: Asynchronous tool approval using AWS Step Functions
In many enterprise scenarios, the approval flow requires authorization from a third-party approver who is not the person invoking the agent. This necessitates an asynchronous approval workflow that can operate independently of the agent session. One effective approach uses AWS Step Functions to orchestrate these external approval processes.
In this pattern, the agent tool triggers a Step Functions workflow that sends an approval request to an external approver through email notification through Amazon SNS. The tool polls for the approval result and updates the agent session state accordingly. The user can also check the approval status later using a separate check_discharge_status tool. The discharge_patient tool starts the Step Functions execution and polls for the result:
@tool(context=True)
def discharge_patient(tool_context, patient_id: str, reason: str) -> str:
# Skip workflow if already approved in this session
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 エリシテーション(情報引き出し)
MCP プロトコルは最近、ツール実行中にユーザーから追加の情報または承認を要求することを可能にするエリシテーションプロトコルを導入しました。このアプローチはプロトコルの標準に従い、パラメータを事前にハードコードする必要 없이実行時にユーザーにプロンプトを表示する動的なメカニズムを提供します。これにより、ツール呼び出しの承認と、それに付随するビジネス上の正当性を組み込むことができます。
機密性の高いツールが呼び出されると、MCP サーバーは実行を一時停止し、MCP クライアントを通じてエンドユーザーに承認プロンプトを送信します。ユーザーはプロンプトを確認し、意思決定を行い、その後サーバーが処理を再開します——操作を実行するか、アクセスを拒否するかのいずれかです。この双方向通信は、MCP のストリーミング HTTP トランスポートによって可能になります。これはクライアントとサーバーの間でステートフルな接続を維持します。
MCP サーバー側では、承認ロジックは各機密性のあるツール内の単一の ctx.elicit() 呼び出しです:
@server.tool
async def get_patient_condition(patient_id: str, ctx: Context) -> str:
"""Get patient condition. Sensitive — requires approval via MCP elicitation."""
result = await ctx.elicit(
f"⚠ Approve access to SENSITIVE condition data for patient {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() を呼び出すと、このコールバックが発火し、承認プロンプトをユーザーに中継して、その意思決定をサーバーに戻します。ローカルエージェントの場合、これはターミナルプロンプトとなります。AgentCore Runtime 上でデプロイされたエージェントの場合、WebSocket 接続を使用して、エリシテーション(elicitation)をリモートエンドユーザーにリアルタイムで中継します。
このアプローチにより、承認ロジックはMCPサーバーのツール定義内に完全に収まります。エージェント自体にはどのツールに承認が必要かの知識がないため、承認要件を独立して追加または変更することができます。
結論
これらのヒューマン・イン・ザ・ループ(HITL: Human-in-the-loop)コンストラクトを使用して、医療およびライフサイエンス分野における安全でコンプライアンス準拠のAIエージェント導入を実現できます。ユースケースに適したHITLパターンを実装することで、パイロットプロジェクトから企業全体の展開までスケーリング可能な本番環境対応のワークフローを展開できます。まず、ワークフロー内で人間の監督が必要な操作を特定することから始めます。次に、承認要件に一致するHITLパターン(中央集権型:Method 1、ツール固有型:Method 2、非同期型:Method 3、リアルタイム型:Method 4)を選択します。
Amazon Bedrock AgentCoreに関する詳細情報は、Amazon Bedrock AgentCoreドキュメントをご覧ください。
著者について

Pierre de Malliard
Pierre de Malliardは、Amazon Web ServicesのシニアAI/MLソリューションアーキテクトであり、医療およびライフサイエンス業界のお客様をサポートしています。Pierreは機械学習アプリケーションとプラットフォームの構築に10年以上の経験を持っています。余暇にはピアノを演奏したり、自然を楽しんだりすることを楽しんでいます。
原文を表示
In healthcare and life sciences, AI agents help organizations process clinical data, submit regulatory filings, automate medical coding, and accelerate drug development and commercialization. However, the sensitive nature of healthcare data and regulatory requirements like Good Practice (GxP) compliance require human oversight at key decision points. This is where human-in-the-loop (HITL) constructs become essential. In this post, you will learn four practical approaches to implementing human-in-the-loop constructs using AWS services.
Why human-in-the-loop matters in healthcare
Healthcare and life sciences organizations face unique challenges when deploying AI agents:
Regulatory compliance – GxP regulations require human oversight for sensitive operations. For example, deleting patient records or modifying clinical trial protocols can’t proceed without documented authorization.
Patient safety – Medical decisions affecting patient care must have clinical validation before execution.
Audit requirements – Healthcare systems need complete traceability of who approved what actions and when.
Data sensitivity – Protected Health Information (PHI) requires explicit authorization before access or modification.
HITL constructs provide the necessary control points while maintaining the efficiency gains of agentic automation to meet these requirements.
Solution overview
We present four complementary approaches to implementing HITL in agentic workflows. Each workflow is suited for different scenarios and risk profiles as described in our guide to building AI agents in GxP Environments. We build these patterns using the Strands Agents framework, Amazon Bedrock AgentCore Runtime, and the Model Context Protocol (MCP), with code examples that you can adapt for your own use cases.
- Agentic Loop Interrupt (Agent Framework Hook System) – We use the Strands Agent Framework Hooks to enforce the human-in-the-loop policy. With the hooks, we can intercept tool calls before their execution.
- Tool Context Interrupt – The human-in-the-loop approval logic can also be implemented within the tool logic directly for fine-grained, tool-specific control and flexibility. The session context can be used for custom approval logic.
- Remote Tool Interrupt (AWS Step Functions) – In some cases, one might want to send an approval request to a third party system or person asynchronously. We demonstrate this pattern by sending a notification to an external approver using Amazon Simple Notification Service (Amazon SNS). The agent session continues without blocking while approval proceeds in the background.
- MCP Elicitation – The MCP protocol recently introduced elicitation, which is used by servers to request additional information from users through the client during interactions. The MCP’s native elicitation protocol allows for real-time, interactive approval using server-sent events (SSE) for stateful, two-way communication.
Architecture
The solution architecture uses the Strands Agents Framework for agent lifecycle management and interrupt handling, deployed on Amazon Bedrock AgentCore Runtime for serverless scalability and session isolation. AWS Step Functions orchestrates asynchronous approval workflows with Amazon SNS, while MCP servers expose tools to the agent through the MCP—also deployed on AgentCore Runtime.
Implementation details
All the code for these architecture patterns is available publicly in the GitHub repository.
Each of the following methods demonstrates a self-contained approach. The agent deploys on Amazon Bedrock AgentCore Runtime with access to healthcare tools at different sensitivity levels. Low-risk operations, like looking up a patient’s name, execute without approval, while high-risk actions, like retrieving vitals or medical conditions, require human authorization. Operations such as patient discharge require external supervisor approval through email notification.
Method 1: Agentic loop hook local tool interrupt
The Strands Agent Framework provides a hook system that intercepts tool calls before execution at the agent loop level. This enforces a blanket HITL policy across sensitive tools without modifying the tools themselves.
A HookProvider registers a callback on BeforeToolCallEvent. When a sensitive tool is invoked, the hook fires an interrupt, pausing the agent loop until the human responds. The user can reply with “y” (approve once), “n” (deny), or “t” (trust—approve this tool for the rest of the session):
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
# Skip if user previously chose "trust always" for this tool
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") # trust tool for the rest of the session
The hook is attached to the agent at construction—tools remain completely unaware of the approval logic:
agent = Agent(
hooks=[ApprovalHook()],
tools=[get_patient_name, get_patient_condition, get_patient_vitals],
)
Method 2: Tool context interrupt
Instead of a centralized hook, the approval logic is embedded directly inside each tool using tool_context.interrupt(). This gives fine-grained, per-tool control: each tool can implement its own access rules based on session context. In this example, the agent session carries a user_role. A shared check_accessfunction enforces role-based access: In our code example, Non-Physicians are denied outright, while Physicians are prompted for approval: Like Method 1, the trust option caches approval for the session:
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 # previously trusted
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 # approved
Method 3: Asynchronous tool approval using AWS Step Functions
In many enterprise scenarios, the approval flow requires authorization from a third-party approver who is not the person invoking the agent. This necessitates an asynchronous approval workflow that can operate independently of the agent session. One effective approach uses AWS Step Functions to orchestrate these external approval processes.
In this pattern, the agent tool triggers a Step Functions workflow that sends an approval request to an external approver through email notification through Amazon SNS. The tool polls for the approval result and updates the agent session state accordingly. The user can also check the approval status later using a separate check_discharge_status tool. The discharge_patient tool starts the Step Functions execution and polls for the result:
@tool(context=True)
def discharge_patient(tool_context, patient_id: str, reason: str) -> str:
# Skip workflow if already approved in this session
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']}"
This asynchronous approach enables non-blocking operations where users aren’t forced to wait for approvals that can take hours or days, and agent execution can continue independently. Step Functions maintains detailed audit trails with complete execution history, persistent state management across session timeouts, and integration with existing enterprise communication channels like email, Slack, or Microsoft Teams. The user that starts a sensitive workflow will trigger a State Function: The agent returns a confirmation to the user that the workflow was launched. At all times, the user can check for a state update to make sure that the workflow completed.
Method 4: MCP elicitation
The MCP protocol recently introduced the elicitation protocol that allows MCP servers to request additional information or approval from users during tool execution. This approach follows protocol standards and provides a dynamic mechanism for prompting users at runtime without requiring parameters to be hardwired upfront. It can be used to authorize a tool call and include some business justification.
When a sensitive tool is called, the MCP server pauses execution and sends an approval prompt back through the MCP client to the end user. The user sees the prompt, makes a decision, and the server resumes—either proceeding with the operation or denying access. This two-way communication is enabled by MCP’s streamable HTTP transport, which maintains a stateful connection between client and server.
On the MCP server, the approval logic is a single ctx.elicit() call inside each sensitive tool:
@server.tool
async def get_patient_condition(patient_id: str, ctx: Context) -> str:
"""Get patient condition. Sensitive — requires approval via MCP elicitation."""
result = await ctx.elicit(
f"⚠ Approve access to SENSITIVE condition data for patient {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"
On the agent side, an elicitation_callback is registered with the MCP client. When the server calls ctx.elicit(), this callback fires, relaying the approval prompt to the user and returning their decision back to the server. For local agents, this is a terminal prompt. For agents deployed on AgentCore Runtime, we use a WebSocket connection to relay the elicitation to the remote end user in real time:
##
This approach keeps the approval logic entirely within the MCP server’s tool definitions. The agent itself has no knowledge of which tools require approval, so you can add or modify approval requirements independently.
まとめ
You can use these human-in-the-loop (HITL) constructs to build safe, compliant AI agent deployments in healthcare and life sciences. By implementing the appropriate HITL pattern for your use case, you can deploy production-ready workflows that scale from pilot projects to enterprise-wide deployments. Start by identifying which operations in your workflow require human oversight. Then, select the HITL pattern that matches your approval requirements—centralized (Method 1), tool-specific (Method 2), asynchronous (Method 3), or real-time (Method 4).
For more information about Amazon Bedrock AgentCore, visit the Amazon Bedrock AgentCore documentation.
About the author

Pierre de Malliard
Pierre de Malliard is a Senior AI/ML Solutions Architect at Amazon Web Services and supports customers in the Healthcare and Life Sciences Industry. Pierre has 10+ years of experience building Machine Learning Applications and Platforms. In his spare time, he enjoys playing the piano and enjoying nature.
関連記事
今日のまとめ
AIデイリーブリーフで今日の重要ニュースをまとめ読み