Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Step FunctionsでAIエージェント × 人の承認を試す / 20260705jaw...

Step FunctionsでAIエージェント × 人の承認を試す / 20260705jawsug-hokurikushinkansen-agentcore-hitl-workflow

2026/07/05 (日) 「JAWS-UG北陸新幹線 #6 上越新幹線直通 in 大宮」にて発表した資料。

イベントページ
https://jawsug-sainokuni-saitama.connpass.com/event/392213/

Avatar for kasacchiful

kasacchiful PRO

July 05, 2026

More Decks by kasacchiful

Other Decks in Programming

Transcript

  1. 笠原 宏 (@kasacchiful) クラスメソッド株式会社 データ事業本部 ビジネスソリューション部 ソリューション アーキテクト 新潟県新潟市在住 JAWS-UG新潟

    / Python機械学習勉強会 in 新潟 / JaSST Niigata / ASTER / SWANII / Cloudflare Meetup Niigata / AI CRAFT Hacks Niigata / KomeKaigi AWS Community Builder (Serverless) 2022, 2025 Japan AWS Top Engineer / 2022-2026 Japan All AWS Certifications Engineer AWS Samurai 2025 自己紹介 2
  2. AWS Step FunctionsからAgentCore HarnessでAIエージェントを直接実行できるようになっ た ただし呼び出しは Request-Response のみ 人の承認(Human-in-the-Loop) は

    waitForTaskToken の別ステートで受ける 「問い合わせ対応」を題材に、 「AIエージェントが起案」 → 「人が承認」 → 「送信 / 再生成」 を組んでみた AgentCore Harness 自体も CloudFormation(CDKでは L1の CfnHarness )で作れる 今日のお話 3
  3. Step FunctionsのTaskステートから、 arn:aws:states:::bedrockagentcore:invoke Harness で エージェントを直接実行 AgentCore Harness は「モデル推論」 「ツー

    ル利用」 「複数ターン会話」を束ねる「マネー ジドなエージェント実行ランタイム」 呼び出し時に SystemPrompt / Messages / Model / Tools を渡して挙動を指定 Lambda を書かずに「AI エージェントのステ ップ」をStep Functionsのステートマシンに 置ける AgentCore Harness 最適化統合(2026-06 追加) 5
  4. AgentDraftReply: Type: Task Resource: "arn:aws:states:::bedrockagentcore:invokeHarness" Arguments: HarnessArn: "${HarnessArn}" RuntimeSessionId: "{%

    $sessionId %}" Messages: # 今回 SystemPrompt は Harness 側にて定義 - Role: user Content: - Text: "{% ' 問い合わせ: ' & $inquiry %}" Assign: draft: "{% $states.result.Output.Message.Content[0].Text %}" # 返信案を変数へ Next: RequestHumanApproval InvokeHarness の呼び出し(ASL YAML / JSONata) 6
  5. エージェント実⾏と「⼈の承認」は別ステート InvokeHarness は待機できない。だから承認は waitForTaskToken の別タスクで受ける ① エージェント実⾏ invokeHarness ・Request-Response(同期・即答) ・最⼤

    15 分 ・⏸ 待機はできない(.waitForTaskToken ⾮対応) + ② ⼈の承認 lambda:invoke.waitForTaskToken ・Task Token コールバック ・SNS メールのリンクで承認 / 修正依頼 ・⏸ いつまでも待機できる 2 つを直列につなぐと「AI が起案 → ⼈が承認 → 実⾏」の Human-in-the-Loop になる 却下は失敗にせず SendTaskSuccess({ decision:'rejected' }) で返し、再⽣成へ回す waitForTaskTokenを使うと、最長1年は待てる Request-Response のみ対応 → 単独では長時間「待てない」 7
  6. Step Functions Lambda (notifier: 承認/ 却下リンク⽣成) Lambda (approval: SendTaskSuccess 実⾏)

    SNS API Gateway publish taskToken + draft テキスト SendTaskSuccess({ taskToken, decision }) 承認者 メール 承認クリック taskToken + decision Task Token で「人の応答待ち」を作る 9
  7. 実⾏者 Step Functions Bedrock AgentCore Harness Memory Bedrock Lambda (

    承認依頼発⾏) SNS Lambda ( 承認内容反映) API Gateway 承認者 waitForTaskToken sendTaskSuccess publish 承認者にメール送信 承認クリック invokeHarness AWS Cloud 構成図 11
  8. AgentDraftReply: Type: Task Resource: "arn:aws:states:::bedrockagentcore:invokeHarness" # Request-Response Arguments: HarnessArn: "${HarnessArn}"

    RuntimeSessionId: "{% $sessionId %}" Messages: - Role: user # 修正依頼時は前回の指摘 $feedback を反映 Content: [ { Text: "{% ' 問い合わせ: ' & $inquiry & ($feedback != '' ? ' / 指摘: ' & $feedback : '') %}" } ] Assign: draft: "{% $states.result.Output.Message.Content[0].Text %}" Next: RequestHumanApproval 応答は Converse 形状。最終メッセージ( Output.Message.Content[0].Text )を $draft に格納 エージェント実行(AgentCore Harness) 13
  9. RequestHumanApproval: Type: Task Resource: "arn:aws:states:::lambda:invoke.waitForTaskToken" Arguments: FunctionName: "${NotifierFunctionArn}" Payload: taskToken:

    "{% $states.context.Task.Token %}" # ← 再開の鍵 inquiry: "{% $inquiry %}" draft: "{% $draft %}" Assign: decision: "{% $states.result.decision %}" feedback: "{% $states.result.feedback ? $states.result.feedback : '' %}" Next: DidHumanApprove 通知 Lambda が承認/却下リンク付きメールを SNS 配信 → ここで待機 人の承認待ち(waitForTaskToken) 14
  10. DidHumanApprove: Type: Choice Choices: - Condition: "{% $decision = 'approved'

    %}" # 承認 → 送信 Next: SendReply - Condition: "{% $decision = 'escalate' %}" # 却下 → 即・人手へ Next: EscalateToHuman - Condition: "{% $attempt < 2 %}" # 修正依頼 → 作り直し Next: IncrementAttempt Default: EscalateToHuman # 上限 → 人手へ 人の判断は「承認」/「修正依頼」/「却下」の3択。いずれも SendTaskSuccess で decision を返す(失敗にしない) 修正依頼の再生成は上限で必ず打ち切り(無限ループ防止) 。却下は即エスカレーション 承認内容に基づく分岐と再生成 15
  11. // approval Lambda (API Gateway 配下): メールのリンクから呼ばれる await sfn.send(new SendTaskSuccessCommand({

    taskToken: token, // メールに埋めた Task Token output: JSON.stringify({ decision, feedback }), // approved / rejected を返す })); 承認 → そのまま送信 / 修正依頼 → 指摘入力フォーム → 再生成 承認者はメールのリンクを押すだけ。ワークフローは待っていて、押された瞬間に再開 承認リンク → ワークフロー再開 16
  12. const asl = yaml.load(fs.readFileSync('statemachine/inquiry-agent-hitl.asl.yaml', 'utf-8')); const sm = new sfn.StateMachine(this,

    'InquiryAgentHitl', { definitionBody: sfn.DefinitionBody.fromString(JSON.stringify(asl)), definitionSubstitutions: { // ${HarnessArn} などを解決 HarnessArn: harnessArn, NotifierFunctionArn: notifierFn.functionArn, }, tracingEnabled: true, logs: { destination: logGroup, level: sfn.LogLevel.ALL, includeExecutionData: true }, }); // Bedrock AgentCore の呼び出し権限を付与 sm.addToRolePolicy(new iam.PolicyStatement({ actions: ['bedrock-agentcore:InvokeHarness'], resources: [harnessArn], })); CDK でステートマシン定義(ASL YAML 読み込み) 17
  13. // L1 コンストラクトで定義 const harness = new agentcore.CfnHarness(this, 'InquiryAgentHarness', {

    harnessName: 'inquiry_support_agent', // 英数字と _ のみ(ハイフン不可) executionRoleArn: harnessRole.roleArn, // AgentCore が assume する実行ロール model: { bedrockModelConfig: { modelId: agentModelId, temperature: 0.3 } }, systemPrompt: [{ text: ' あなたは丁寧なカスタマーサポート担当です…' }], // システムプロンプト maxIterations: 10, timeoutSeconds: 300, }); 必須は harnessName / executionRoleArn / model の3つだけ 実行ロールに「Bedrock 呼び出し」 「ECR Public 取得」 「AgentCore Memory 操作(会話メモリ) 」権限が要る Harness も CDK で作る 18
  14. Step Functions × AgentCore が使える場面 AI の判断を「人が確認してから確定」したい(承認・監査が要る業務) リトライ・分岐・待機・並列を宣言的に書け、実行が可視化される 気づき InvokeHarness

    は Request-Response / 最大 15 分 → 長い待ちは Task Token 側で持つ必要 がある 承認却下は「失敗」ではなく分岐で判定( SendTaskSuccess で decision を返す) JSONataによる記述と変数 (Assign / $var) でステートの持ち回りがスッキリ 棲み分け エージェント自身の自律ループは AgentCore(Harness) 決まった業務フローや人の承認は Step Functions 使いどころと役割分担 21
  15. Step Functions から AgentCore Harness でエージェントを直接実行できる Human-in-the-Loop(waitForTaskToken) の別ステートを使うことで、長い待ち状態も解決 「AI が起案」→「人が承認」→「実行」のワークフローを、Step

    Functionsを使うことで宣言 的に組める まずは マネージメントコンソール で「AgentCore Harness」をクイックスタートで作ってみる のがおすすめ まとめ 22
  16. 2026/07/18 (土) 15:00 〜 HIDA office 2F (JR上越妙高駅西口より徒歩1分) https://jawsug- joetsumyoko.connpass.com/event/392732/

    上越・妙高には「北陸新幹線」で お越しください JAWS-UG上越妙高 StepFunctions ハンズオン 24
  17. 2026/07/10 (水) 19:00開始 (オンライン) JAWS-UG新潟#31 AWSサポートが言いたいセキュリティサービスあるある (AWS Expert Online for

    JAWS-UG #38) 2026/07/25 (土) - 07/26 (日) (現地開催) JAWS-UG新潟 in 佐渡 - Lightning Sado 2026 2026年秋 頃 (予定・現地開催) JAWS-UG新潟 開催 検討中 2026/12 頃 (予定・ハイブリッド開催) JAWS-UG新潟 AWS re:Invent 2026 re:Cap 毎週木曜夜21時 (オンライン) JAWS-UG新潟 プチキャッチアップ 新潟には「上越新幹線」でお越しください JAWS-UG新潟 今後の予定 25
  18. Invoke Amazon Bedrock AgentCore harness with Step Functions(AWS Docs) https://docs.aws.amazon.com/step-functions/latest/dg/connect-bedrockagentcore.html

    AWS Step Functions adds AgentCore-powered agentic reasoning step(What's New) https://aws.amazon.com/about-aws/whats-new/2026/06/aws-step-functions-agentcore/ Deploying a workflow that waits for human approval(AWS Docs) https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-human-approval.html 参考リンク 28