Human-in-the-Loopエスカレーション
信頼度が低い場合、破壊的な操作が行われようとしている場合、またはリトライ予算を使い切った場合に、エージェントを一時停止して人間の指示を求めるエスカレーション条件を定義します
「Human-in-the-Loopエスカレーション」はCoddyKit上の無料AI Engineering Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Engineering Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Engineering Academyコースには全4レッスンが含まれています。
エージェントに人間の指示が必要な場合
完全自律型のエージェントは、明確に定義された低リスクのタスクに適しています。しかし、曖昧な指示、モデルの確信度の低さ、元に戻せない破壊的な操作、失敗が重大な結果につながるタスクなど、人間の判断が必要な状況もあります。Human-in-the-loop(HITL)エスカレーションは、このような判断の時点でエージェントを一時停止し、続行前に人間の入力を求めます。これにより、自動化の効率と人間の判断力を組み合わせられます。
エスカレーションのトリガーを定義する
エスカレーションは、曖昧な直感ではなく、具体的で測定可能な条件によって発生させるべきです。アプリケーション用に明確なエスカレーションのトリガーを定義してください。一般的なトリガーには、モデルの確信度がしきい値を下回った場合、破壊的な操作を実行しようとしている場合、ポリシーの境界に近づいた場合、再試行予算を使い果たした場合、タスクが制限時間を超えた場合などがあります。制御フローのロジックを変更せずに調整できるよう、トリガーは名前付き定数としてコードに記述します。
from enum import Enum
class EscalationReason(Enum):
LOW_CONFIDENCE = 'low_confidence' # model uncertainty
DESTRUCTIVE_ACTION = 'destructive_action' # irreversible change
AMBIGUOUS_TASK = 'ambiguous_task' # unclear instructions
RETRY_BUDGET_EXHAUSTED = 'retry_exhausted' # too many failures
POLICY_BOUNDARY = 'policy_boundary' # approaching limit
HUMAN_REQUESTED = 'human_requested' # explicit request
TIMEOUT = 'timeout' # took too long
ESCALATION_THRESHOLDS = {
'min_confidence': 0.6,
'max_retries': 5,
'max_runtime_minutes': 30,
}確信度の低さを検出する
提案した操作を実行する前に、モデルに確信度を表明させます。確信度スコアが設定したしきい値を下回ったら、エスカレーションを発生させます。数値スコアと簡潔な理由の両方を含む構造化された確信度チェックを使用すると、人間のレビュアーはエージェントが不確かな理由を正確に理解できます。この理由により、人間はタスク履歴全体を確認するのではなく、対象を絞った指示を提供できます。
from pydantic import BaseModel
class ConfidenceCheck(BaseModel):
proposed_action: str
confidence: float # 0.0 to 1.0
uncertainty_reason: str | None
proceed: bool
async def check_confidence(context: str, proposed_action: str) -> ConfidenceCheck:
return await judge_client.chat.completions.create(
model='gpt-4o',
response_model=ConfidenceCheck,
messages=[{
'role': 'user',
'content': f'Context: {context}\n\nI am about to: {proposed_action}\n\nHow confident am I that this is correct? Be honest about uncertainty.'
}]
)破壊的な操作を検出する
不可逆な操作を実行するツールには destructive=True フラグを付け、実行前に人間の確認を必須にします。例として、ファイルの削除、実際のユーザーへのメール送信、ロールバックできないデータベースの変更、顧客への課金、コンテンツの一般公開などがあります。エージェントは、ほかの処理を自律的に実行している場合でも、これらの操作で一時停止し、人間による明示的な承認を待たなければなりません。
from dataclasses import dataclass
from typing import Callable
@dataclass
class Tool:
name: str
func: Callable
destructive: bool = False
description: str = ''
tools = [
Tool('search_web', search_web, destructive=False),
Tool('read_file', read_file, destructive=False),
Tool('write_file', write_file, destructive=True, description='Overwrites existing file'),
Tool('send_email', send_email, destructive=True, description='Sends real email to user'),
Tool('delete_records', delete_records, destructive=True, description='Permanent DB deletion'),
]
def requires_approval(tool: Tool) -> bool:
return tool.destructiveエージェントを一時停止して入力を待つ
エスカレーションのトリガーが発生したら、チェックポイントを保存してタスクを再開できるようにし、エスカレーションリクエストのレコードを作成して、人間のレビュアーに通知します。エージェントは処理を停止して待機します。人間はダッシュボードまたは通知からエスカレーションを確認し、指示または承認を提供します。その後、エージェントはその指示を履歴内の新しいメッセージとして含め、チェックポイントから再開します。
import asyncio
async def escalate_and_wait(task_id: str, reason: EscalationReason, context: str,
question: str, timeout_hours: int = 24) -> str:
# Save checkpoint
save_checkpoint(load_checkpoint(task_id))
# Create escalation record
escalation_id = create_escalation(task_id, reason, context, question)
# Notify reviewer
notify_reviewer(escalation_id, question)
# Wait for response (polling with timeout)
deadline = asyncio.get_event_loop().time() + timeout_hours * 3600
while asyncio.get_event_loop().time() < deadline:
response = get_escalation_response(escalation_id)
if response:
return response.guidance
await asyncio.sleep(60) # check every minute
raise TimeoutError(f'Escalation {escalation_id} not answered within {timeout_hours}h')レビュアーインターフェースの構築
人間のレビュアーがエスカレーションに対応するには、シンプルなインターフェースが必要です。最低限、タスクの説明、エージェントがそれまでに進めた内容、承認が必要な具体的な質問または提案されたアクション、そして「Approve」「Reject」「Provide Guidance」ボタンを表示します。監査のため、レビュアーの身元とタイムスタンプを添えて、すべてのレビュアーの判断を記録してください。Slack botでもシンプルなWebフォームでも、社内チームには十分効果的です。
# FastAPI escalation endpoint
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class EscalationResponse(BaseModel):
escalation_id: str
decision: str # 'approve', 'reject', 'guide'
guidance: str | None = None
reviewer_id: str
@app.post('/escalations/{escalation_id}/respond')
async def respond_to_escalation(esc_id: str, response: EscalationResponse):
escalation = get_escalation(esc_id)
if not escalation or escalation.status != 'pending':
return {'error': 'Escalation not found or already resolved'}
save_escalation_response(esc_id, response)
return {'status': 'response_recorded', 'task_will_resume': True}エージェントのコンテキストへの人間のガイダンスの注入
人間からの応答を受け取ったら、再開する前に、そのガイダンスをエージェントの会話履歴に新しいメッセージとして注入します。エージェント自身の観察結果と区別できるよう、「supervisor」からのメッセージとして扱います。これにより、エージェントは次のステップでこのガイダンスを参照できます。人間が提案されたアクションを却下した場合は、代わりに何をすべきかの指示も含めてください。
def inject_human_guidance(messages: list, decision: str, guidance: str | None) -> list:
if decision == 'approve':
messages.append({
'role': 'user',
'content': 'Supervisor: Your proposed action has been approved. Proceed.'
})
elif decision == 'reject':
messages.append({
'role': 'user',
'content': f'Supervisor: Your proposed action was rejected. Instead: {guidance}'
})
elif decision == 'guide':
messages.append({
'role': 'user',
'content': f'Supervisor: Additional guidance: {guidance}'
})
return messagesエスカレーション指標の追跡
エスカレーションの量、理由、応答時間を監視します。エスカレーションの量が多い場合、エージェントの確信度が不十分であることを示しています。タスクが曖昧すぎる、モデルにより良い指示が必要、または確信度のしきい値が低すぎる、といった原因が考えられます。応答時間が長い場合は、レビュアーの負荷に問題があることを示しています。これらの指標を使って自動化と人間の関与のバランスを調整し、本当にリスクのある判断では人間を関与させながら、不要な中断を最小限に抑えます。
def escalation_report(db_connection, days: int = 7) -> dict:
# SQL query (pseudocode)
rows = db_connection.execute('''
SELECT
reason,
COUNT(*) as count,
AVG(EXTRACT(EPOCH FROM (responded_at - created_at)) / 3600) as avg_response_hours,
SUM(CASE WHEN decision = 'approve' THEN 1 ELSE 0 END) as approvals,
SUM(CASE WHEN decision = 'reject' THEN 1 ELSE 0 END) as rejections
FROM escalations
WHERE created_at > NOW() - INTERVAL '%s days'
GROUP BY reason
ORDER BY count DESC
''' % days).fetchall()
return [dict(r) for r in rows]自律性の段階的な拡大
まずはエスカレーション感度を高く設定します(確信度のしきい値を低くし、破壊的なアクションはすべてエスカレーションします)。そのうえで、エージェントの動作に確信が持てるようになるにつれて、エスカレーションの頻度を徐々に下げます。各エスカレーションが承認となったのか、実際の修正につながったのかを追跡してください。特定のトリガー種別で承認率が一貫して高い場合は、そのトリガーを安全に自動化できます。これにより、適切な監督を維持しながら人間の負荷を減らせます。
# Autonomy expansion strategy:
# Week 1: escalate for ALL destructive actions
# Week 2: auto-approve file writes to /tmp (low-risk), escalate others
# Week 4: auto-approve all file writes, escalate only email/DB changes
# Week 8: auto-approve emails under 10 recipients, escalate mass emails
# Track approval rates per trigger type:
# Tool: write_file -> 98% approve -> safe to automate
# Tool: send_email -> 89% approve -> near-automate with content check
# Tool: delete_records -> 43% approve -> always escalate緊急オーバーライドとタスクのキャンセル
人間が実行中のエージェントタスクを直ちにキャンセルできる緊急オーバーライド機構を必ず用意してください。エージェントが本来呼び出すべきでないツールを呼び出したり、想定された範囲外のアクションを実行したりするなど、誤動作している場合、人間が数秒以内に停止できなければなりません。キャンセルシグナル(エージェントが各ステップで確認するデータベースフラグ)を実装し、ステップの途中でエージェントがキャンセルされた場合は、ツール呼び出しの結果が破棄されるようにしてください。
async def run_agent_with_cancel(task_id: str, messages: list) -> str:
for step in range(MAX_ITERATIONS):
# Check cancel flag at start of every step
if redis_client.get(f'agent:cancel:{task_id}'):
save_final_status(task_id, 'cancelled')
return 'Task cancelled by operator.'
response = await get_next_action(messages)
if response.is_final:
return response.answer
result = await execute_tool(response.tool, response.args)
messages.append({'role': 'user', 'content': result})
save_checkpoint_after_step(task_id, step, messages)
return 'Max iterations reached'エスカレーションしきい値の調整
エスカレーションのしきい値は調整が必要です。確信度のしきい値が高すぎると、エージェントはほぼすべてのアクションでエスカレーションし、レビュアーの負荷が過大になります。低すぎると、リスクのあるアクションが見逃されます。1週目は保守的なしきい値から始め、エスカレーション量とレビュアーの承認率を追跡して調整してください。安定したシステムでは、確信度の問題によるエスカレーションはタスクの5~15%、破壊的なアクションではほぼ100%とし、全体の承認率は80%を超える状態が目安です。
# Threshold tuning guide:
# Escalation rate vs quality trade-off:
#
# confidence_threshold=0.8 -> 35% escalation rate (too many)
# confidence_threshold=0.6 -> 12% escalation rate (target)
# confidence_threshold=0.4 -> 4% escalation rate (too few)
#
# Weekly review of escalation decisions:
# - Approval rate > 90%: lower threshold (too conservative)
# - Approval rate < 70%: raise threshold (not catching real issues)
# - Target: 75-85% approval rateクイックチェック
Human-in-the-loopエスカレーション設計についての理解度を確認します。
レッスンのまとめ
このレッスンでは、エスカレーショントリガーによって、エージェントが一時停止して人間のガイダンスを求めるべき正確な条件を定義できること、ツールの破壊的アクションフラグによって不可逆な操作に承認を必須にできること、そして自律性の段階的な拡大によって、エージェントが信頼を得るにつれて安全に自動化の範囲を広げられることを学びました。次は、capstoneプロジェクトの本番アーキテクチャを設計します。
よくある質問
「Human-in-the-Loopエスカレーション」レッスンは無料ですか?
はい。「Human-in-the-Loopエスカレーション」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Engineering Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Engineering Academyコースには全4レッスンが含まれています。
「Human-in-the-Loopエスカレーション」で何を学びますか?
信頼度が低い場合、破壊的な操作が行われようとしている場合、またはリトライ予算を使い切った場合に、エージェントを一時停止して人間の指示を求めるエスカレーション条件を定義します ブラウザで直接実行するハンズオンコードでAI Engineering Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
AI Engineering Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAI Engineering Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「Human-in-the-Loopエスカレーション」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAI Engineering Academyレッスンでコードを書いて実行できますか?
はい。すべてのAI Engineering Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- エージェントの失敗モードの分類
- 自己修正とリフレクティブプロンプティング
- チェックポイントとタスクの再開
- Human-in-the-Loopエスカレーション