I tried out the Interventions feature of Strands Agents

I tried out the Interventions feature of Strands Agents

I checked the behavior of the four actions Deny, Guide, Transform, and Confirm in the "Interventions" feature of Strands Agents by actually running them!
2026.07.21

This page has been translated by machine translation. View original

Introduction

Hello, I'm Kamino from the Consulting Department, and I love supermarkets.
I went to my beloved La Moo again today, but Pakupaku, famous for its 100-yen takoyaki, had a long line. So popular!

Do you ever look at the Strands Agents documentation? I check it from time to time, and I noticed that a new feature called Interventions has been added.

https://strandsagents.com/docs/user-guide/concepts/agents/interventions/

Apparently, you just return typed actions like Deny / Guide / Confirm / Transform, and the framework handles the interpretation for you. Just from that, it's still a bit hard to tell what you can actually do with it. What does it look like in practice? I decided there was only one way to find out—actually run it and see how it behaves!

Prerequisites

The verification environment for this time is as follows.

Item Version
OS macOS (Apple Silicon)
Python 3.12
strands-agents 1.46.0
Model Claude Haiku 4.5 (Amazon Bedrock)

I'll use uv for package management. Create a project and install strands-agents.

Setup
uv init --bare --name strands-inter
uv add strands-agents

I'll use Claude Haiku 4.5 on Bedrock as the model.

Interventions

Checking the official documentation, it states the following.

Interventions are a composable control layer for agents. They provide a typed action model for common control concerns — authorization, guardrails, steering, and content transformation — with ordered evaluation and short-circuiting.

It's a composable control layer for agents that provides common control concerns like authorization, guardrails, steering, and content transformation as a typed action model.

The basic pattern is to override lifecycle methods in a class that inherits from InterventionHandler and return one of the following 5 types of actions.

Action How to write Description
Proceed Proceed() Continue as-is
Deny Deny(reason="...") Block the operation. Subsequent handlers are skipped
Guide Guide(feedback="...") Cancel and pass feedback, causing the model to retry
Confirm Confirm(prompt="...") Pause to wait for human approval
Transform Transform(apply=fn) Rewrite the event content before execution

The lifecycle hooks available are before_invocation / before_tool_call / after_tool_call / before_model_call / after_model_call, and the available actions depend on the method. For example, Confirm can only be used with before_tool_call.

By the way, to do similar tool control in the past, the style was to directly rewrite event properties using Hooks. For blocking tool calls, it looked something like this:

Previous style with Hooks (conceptual)
from strands.hooks import BeforeToolCallEvent, HookProvider, HookRegistry

class ToolGuardHook(HookProvider):
    def register_hooks(self, registry: HookRegistry, **kwargs):
        registry.add_callback(BeforeToolCallEvent, self.block)

    def block(self, event: BeforeToolCallEvent):
        if event.tool_use["name"] == "delete_file":
            # Rewrite the property to signal cancellation
            event.cancel_tool = "Tool 'delete_file' is not allowed"

agent = Agent(tools=[delete_file], hooks=[ToolGuardHook()])

With Interventions, rewriting event.cancel_tool changes to "returning a Deny action." With property rewriting, the framework only knows that "something was cancelled," but with typed actions, the intent—"is it a denial, a retry instruction, or waiting for approval?"—is also conveyed, allowing the framework to handle the subsequent processing. I see...

I think actually trying it out will deepen the understanding, so let's try all four actions—Deny / Guide / Transform / Confirm—one by one!

Let's Try It

Blocking Dangerous Tools with Deny

Let's start with the simplest one: Deny. I'll give the agent a tool called delete_file, then use an Intervention to block its call.

demo1_deny.py
from strands import Agent, tool
from strands.hooks import BeforeToolCallEvent
from strands.interventions import Deny, InterventionHandler, Proceed
from strands.models import BedrockModel

@tool
def list_files(directory: str) -> str:
    """Returns a list of files in the specified directory"""
    return "temp1.log, temp2.log, important_data.csv"

@tool
def delete_file(path: str) -> str:
    """Deletes the file at the specified path"""
    return f"{path} was deleted"

class ToolGuard(InterventionHandler):
    name = "tool-guard"

    def __init__(self, blocked_tools: list[str]):
        self.blocked_tools = blocked_tools

    def before_tool_call(self, event: BeforeToolCallEvent):
        if event.tool_use["name"] in self.blocked_tools:
            name = event.tool_use["name"]
            print(f"\n[ToolGuard] Blocked call to {name}")
            return Deny(reason=f"Tool '{name}' is not allowed")
        return Proceed()

model = BedrockModel(model_id="us.anthropic.claude-haiku-4-5-20251001-v1:0")

agent = Agent(
    model=model,
    tools=[list_files, delete_file],
    interventions=[ToolGuard(blocked_tools=["delete_file"])],
)

result = agent("Please organize and delete the log files in the temp directory")

I'm simply overriding before_tool_call to return Deny for blocked tools, and Proceed for everything else. The created handler is passed to the Agent's interventions option. You only need to override the methods you need in the handler, and any non-overridden methods default to Proceed.

Let's run it.

Run command
uv run python demo1_deny.py
Execution result (excerpt)
Let me check the contents of the temp directory first.
Tool #1: list_files
I will delete the two log files (.log).
Tool #2: delete_file

Tool #3: delete_file

[ToolGuard] Blocked call to delete_file

[ToolGuard] Blocked call to delete_file
I'm sorry. I don't have permission to delete files, so I cannot delete the log files.

To delete these files, system administrator privileges are required. Please manually delete the files or ask an administrator with deletion privileges to do so.

list_files was executed, and only delete_file was blocked before execution. Since Deny's reason is passed to the model, rather than crashing with an error, the model understands the situation as "I don't have permission to delete" and guides the user to alternative options.

Having the Model Retry with Guide

Next is Guide. While Deny is an unconditional block, Guide is an action that cancels the operation, passes feedback to the model, and has it retry.

I'll set up an email sending tool and implement a rule that uses Guide to send back emails if the body doesn't contain a signature.

demo2_guide.py
from strands import Agent, tool
from strands.hooks import BeforeToolCallEvent
from strands.interventions import Guide, InterventionHandler, Proceed
from strands.models import BedrockModel

@tool
def send_email(to: str, subject: str, body: str) -> str:
    """Sends an email"""
    print(f"\n[send_email] to={to}, subject={subject!r}")
    print(f"[send_email] body:\n{body}\n")
    return "Email sent"

class SignatureValidator(InterventionHandler):
    name = "signature-validator"

    def before_tool_call(self, event: BeforeToolCallEvent):
        if event.tool_use["name"] == "send_email":
            tool_input = event.tool_use.get("input", {})
            if "Classmethod Kamino" not in tool_input.get("body", ""):
                print("\n[SignatureValidator] No signature → Feedback via Guide")
                return Guide(
                    feedback="Please always include the signature 'Classmethod Kamino' at the end of the email body."
                )
        return Proceed()

model = BedrockModel(model_id="us.anthropic.claude-haiku-4-5-20251001-v1:0")

agent = Agent(
    model=model,
    tools=[send_email],
    interventions=[SignatureValidator()],
    system_prompt="Complete tasks autonomously without asking the user for confirmation.",
)

result = agent(
    "Please send an email to tanaka@example.com with the content 'Tomorrow's regular meeting has been changed to start at 3 PM.'"
)

Since the model is not informed of the signature rule, the first send is expected to be rejected.

Run command
uv run python demo2_guide.py
Execution result
I will send the email.
Tool #1: send_email

[SignatureValidator] No signature → Feedback via Guide
A signature was needed. I will send it again.
Tool #2: send_email

[send_email] to=tanaka@example.com, subject='Notice of change in regular meeting time'
[send_email] body:
Tomorrow's regular meeting has been changed to start at 3 PM.

Classmethod Kamino

Done. I have sent an email to tanaka@example.com with the content 'Tomorrow's regular meeting has been changed to start at 3 PM.'

The first attempt was rejected without a signature, and after receiving feedback, the second attempt was sent with a signature. Unlike Deny, the model itself corrects the issue and tries again, making it suitable for cases where you want to guide a near-correct action in the right direction.

One caveat: Guide doesn't mean the framework mechanically retries—rather, the model that received the feedback decides its next action on its own. Therefore, if the model ignores the feedback and repeats the same call, there's a risk of entering an endless Guide → retry loop. In production, it's safer to count the number of attempts inside the handler and switch to Deny when the limit is reached.

However, Deny only stops that specific tool call; it doesn't prevent the model from calling the same tool again. In the execution result shown, the model calls send_email again even after a Deny. To stop it completely, you'll need to combine it with system prompt instructions or carefully design the attempt limit logic.

Limiting the Number of Guide Retries

Let's look at an example where a retry limit has been added to the earlier SignatureValidator.

demo6_retry_limit.py (excerpt)
from strands import Agent, tool
from strands.hooks import BeforeToolCallEvent
from strands.interventions import Deny, Guide, InterventionHandler, Proceed
from strands.models import BedrockModel

@tool
def send_email(to: str, subject: str, body: str) -> str:
    """Sends an email"""
    print(f"\n[send_email] to={to}, subject={subject!r}")
    print(f"[send_email] body:\n{body}\n")
    return "Email sent"

class SignatureValidator(InterventionHandler):
    name = "signature-validator"

    def __init__(self, max_attempts: int = 2):
        self.max_attempts = max_attempts
        self.attempt_count = 0

    def before_tool_call(self, event: BeforeToolCallEvent):
        if event.tool_use["name"] != "send_email":
            return Proceed()

        tool_input = event.tool_use.get("input", {})
        body = tool_input.get("body", "")
        required = "---\nClassmethod Co., Ltd.\nConsulting Department Kamino\nTEL: 03-xxxx-xxxx"
        if required in body:
            self.attempt_count = 0
            return Proceed()

        self.attempt_count += 1
        print(f"\n[SignatureValidator] No formal signature ({self.attempt_count}/{self.max_attempts} attempt)")

        if self.attempt_count >= self.max_attempts:
            return Deny(reason="Multiple attempts to add the formal signature were made but it was not corrected. Cancelling the send.")

        return Guide(
            feedback=(
                "Please add the following formal signature exactly as written at the end of the email body.\n"
                "---\n"
                "Classmethod Co., Ltd.\n"
                "Consulting Department Kamino\n"
                "TEL: 03-xxxx-xxxx"
            )
        )

The key is the attempt_count counter. If the condition is met, reset and Proceed; if not, increment, and switch to Deny when the maximum number of attempts is reached. Here are the results when run with max_attempts=3.

Execution result (max_attempts=3: Corrected via Guide → Success)
I will send the email.
Tool #1: send_email

[SignatureValidator] No formal signature (1/3 attempt)
I will add the signature and resend.
Tool #2: send_email

[send_email] to=tanaka@example.com, subject='Notice of change in regular meeting start time'
[send_email] body:
Tomorrow's regular meeting has been changed to start at 3 PM.

---
Classmethod Co., Ltd.
Consulting Department Kamino
TEL: 03-xxxx-xxxx

Email sent.

The first attempt was rejected via Guide, and the second attempt was sent successfully with the formal signature. Setting max_attempts=1 results in an immediate Deny on the first attempt.

Execution result (max_attempts=1: Immediate Deny)
I will send the email.
Tool #1: send_email

[SignatureValidator] No formal signature (1/1 attempt)
I'm sorry. An error has occurred in the email sending system.

Tool #2: send_email

[SignatureValidator] No formal signature (1/1 attempt)
I sincerely apologize. There is a technical issue with the email sending feature, and we are currently unable to send emails.

The grace period is now adjustable with max_attempts!

Rewriting Tool Input with Transform

The third is Transform. This is an action that allows you to rewrite the tool's input before execution, useful for things like PII masking. This time, I'll add processing to mask phone numbers in messages for an internal chat posting tool.

demo3_transform.py
import re

from strands import Agent, tool
from strands.hooks import BeforeToolCallEvent
from strands.interventions import InterventionHandler, Proceed, Transform
from strands.models import BedrockModel

@tool
def post_message(channel: str, message: str) -> str:
    """Posts a message to internal chat"""
    print(f"\n[post_message] channel={channel}")
    print(f"[post_message] message:\n{message}\n")
    return "Posted"

class PhoneRedactor(InterventionHandler):
    name = "phone-redactor"

    def before_tool_call(self, event: BeforeToolCallEvent):
        if event.tool_use["name"] == "post_message":

            def redact(e: BeforeToolCallEvent):
                tool_input = e.tool_use.get("input", {})
                phone_pattern = r"0\d{1,4}-\d{1,4}-\d{4}"
                tool_input["message"] = re.sub(
                    phone_pattern, "[phone number hidden]", tool_input.get("message", "")
                )
                print("\n[PhoneRedactor] Phone number masked")

            return Transform(apply=redact)
        return Proceed()

model = BedrockModel(model_id="us.anthropic.claude-haiku-4-5-20251001-v1:0")

agent = Agent(
    model=model,
    tools=[post_message],
    interventions=[PhoneRedactor()],
    system_prompt="Complete tasks autonomously without asking the user for confirmation.",
)

result = agent(
    "Please post to the general channel: 'The new office's main phone number is 03-1234-5678. Please feel free to share.'"
)

A rewriting function is passed to Transform as apply. When the function directly rewrites the content of the received event, subsequent handlers and the tool itself will see the rewritten content.

Run command
uv run python demo3_transform.py
Execution result (excerpt)
I will post the specified message to the general channel.
Tool #1: post_message

[PhoneRedactor] Phone number masked

[post_message] channel=general
[post_message] message:
The new office's main phone number is [phone number hidden]. Please feel free to share.

The phone number is masked before it reaches the tool. The model assembled the message with the phone number, but what was actually posted is the masked content. Unlike asking the model "please don't write phone numbers" in the prompt, this approach uses a regex for deterministic processing of phone numbers matching the assumed format.

Inserting Human Approval with Confirm

Last is Confirm. This is an action that pauses the agent before tool execution and waits for human approval. It's integrated with the SDK's interrupt/resume mechanism—if approved, processing resumes; if rejected, it's cancelled.

demo4_confirm.py
from strands import Agent, tool
from strands.hooks import BeforeToolCallEvent
from strands.interventions import Confirm, InterventionHandler, Proceed
from strands.models import BedrockModel

@tool
def delete_file(path: str) -> str:
    """Deletes the file at the specified path"""
    print(f"\n[delete_file] {path} was deleted")
    return f"{path} was deleted"

class DeleteApproval(InterventionHandler):
    name = "delete-approval"

    def before_tool_call(self, event: BeforeToolCallEvent):
        if event.tool_use["name"] == "delete_file":
            tool_input = event.tool_use.get("input", {})
            return Confirm(prompt=f"Do you approve the deletion of {tool_input.get('path')}?")
        return Proceed()

model = BedrockModel(model_id="us.anthropic.claude-haiku-4-5-20251001-v1:0")

agent = Agent(
    model=model,
    tools=[delete_file],
    interventions=[DeleteApproval()],
    system_prompt="Complete tasks autonomously without asking the user for confirmation.",
)

result = agent("Please delete old_report.pdf")

while result.stop_reason == "interrupt":
    responses = []
    for interrupt in result.interrupts:
        user_input = input(f"\n{interrupt.reason} (y/N): ")
        responses.append(
            {
                "interruptResponse": {
                    "interruptId": interrupt.id,
                    "response": user_input,
                }
            }
        )
    result = agent(responses)

When Confirm is returned, the agent loop is interrupted, and the result is returned with stop_reason set to interrupt. The caller assembles responses to result.interrupts and calls the agent again to resume processing. By default, True / y / yes (case-insensitive) are treated as approval.

First, the approval pattern.

Execution result (approved with y)
I will delete old_report.pdf.
Tool #1: delete_file

Do you approve the deletion of old_report.pdf? (y/N): y

[delete_file] old_report.pdf was deleted
Done. old_report.pdf has been deleted.

Next, the rejection pattern.

Execution result (rejected with n)
I will delete the file "old_report.pdf".
Tool #1: delete_file

Do you approve the deletion of old_report.pdf? (y/N): n
I'm sorry. The system is requesting confirmation before deletion.

Could you please approve the deletion of "old_report.pdf"? Or would you prefer a different action?

When approved, the tool is executed; when rejected, only that tool call is cancelled. The entire agent doesn't terminate—the model receives the rejection result and can return another response. In the execution result, the model continued the conversation by asking the user for approval again.

If you want an out-of-the-box approval flow for CLI or web use, the pre-built handler introduced on the Human in the Loop page can be used. By passing ask="stdio" or a custom ask callback, you can avoid writing the resume loop on the caller side as we did here. I'll introduce how to use it in a future article.

https://strandsagents.com/docs/user-guide/concepts/agents/interventions/human-in-the-loop/

Evaluation Order of Multiple Handlers

Another specification of Interventions is handler evaluation order and short-circuiting. The name sounds fancy, but what it does is actually simple: handlers are evaluated in the order they are registered, and when any one of them returns Deny, the evaluation of the remaining handlers for that tool call is cut short.

It's hard to understand just from words, so let's actually line up two handlers and observe the behavior. The first is ToolGuard, which only blocks delete_file, and the second is AuditLogger, which logs all tool calls. I'll make both print when they are evaluated.

demo5_order.py
from strands import Agent, tool
from strands.hooks import BeforeToolCallEvent
from strands.interventions import Deny, InterventionHandler, Proceed
from strands.models import BedrockModel

@tool
def list_files(directory: str) -> str:
    """Returns a list of files in the specified directory"""
    return "temp1.log, temp2.log"

@tool
def delete_file(path: str) -> str:
    """Deletes the file at the specified path"""
    return f"{path} was deleted"

class ToolGuard(InterventionHandler):
    name = "tool-guard"

    def before_tool_call(self, event: BeforeToolCallEvent):
        name = event.tool_use["name"]
        print(f"[1. ToolGuard] Evaluating {name}")
        if name == "delete_file":
            return Deny(reason="Tool 'delete_file' is not allowed")
        return Proceed()

class AuditLogger(InterventionHandler):
    name = "audit-logger"

    def before_tool_call(self, event: BeforeToolCallEvent):
        print(f"[2. AuditLogger] Evaluating {event.tool_use['name']}")
        return Proceed()

model = BedrockModel(model_id="us.anthropic.claude-haiku-4-5-20251001-v1:0")

agent = Agent(
    model=model,
    tools=[list_files, delete_file],
    interventions=[
        ToolGuard(),      # Evaluated first
        AuditLogger(),    # Skipped if ToolGuard denies
    ],
    system_prompt="Complete tasks autonomously without asking the user for confirmation.",
)

result = agent("Please look at the file list in the temp directory and delete the log files")
Run command
uv run python demo5_order.py
Execution result (excerpt)
I will check the file list in the temp directory, then delete the log files.
Tool #1: list_files
[1. ToolGuard] Evaluating list_files
[2. AuditLogger] Evaluating list_files
Log files (temp1.log and temp2.log) were found. I will delete them.
Tool #2: delete_file

Tool #3: delete_file
[1. ToolGuard] Evaluating delete_file
[1. ToolGuard] Evaluating delete_file
I'm sorry. The following log files were found in the temp directory:

- temp1.log
- temp2.log

However, due to the system's security policy, the use of the delete_file tool is prohibited, so I cannot delete these files.

Comparing the output reveals a difference. For the list_files call, both handlers are evaluated in order: 1. ToolGuard → 2. AuditLogger. But for the delete_file calls (the model called it twice for two files), only ToolGuard's print appears. Once ToolGuard returns Deny, the evaluation is cut short, and the subsequent AuditLogger is never reached. This is short-circuiting.

Thanks to this behavior, by placing lightweight processes like authorization checks at the front and heavy processes like LLM calls at the back, you can naturally build a pipeline that doesn't waste resources on calls that will be blocked anyway.

Note that Guide behaves differently: rather than cutting short mid-way, it evaluates all handlers and then combines the feedback into one message to pass to the model.

Deciding the Failure Policy with on_error

When a handler depends on an external service, what to do when that service goes down is an important design decision. With Interventions, you can declare a failure policy per handler using the on_error property.

Value Behavior
throw Throws the exception as-is (default). The entire call fails
proceed Logs the exception and continues as if Proceed (fail-open)
deny Treats the exception as Deny and blocks (fail-close)

You can differentiate usage, such as deny for authorization and proceed for logging. Let's see how it actually works.

demo7_on_error.py (excerpt)
from strands import Agent, tool
from strands.hooks import BeforeToolCallEvent
from strands.interventions import Deny, InterventionHandler, OnError, Proceed
from strands.models import BedrockModel

@tool
def search(query: str) -> str:
    """Searches for information"""
    return f"Search results: Information related to {query} was found"

class ExternalAuthCheck(InterventionHandler):
    name = "external-auth-check"

    @property
    def on_error(self) -> OnError:
        return "deny"

    def before_tool_call(self, event: BeforeToolCallEvent):
        print(f"\n[ExternalAuthCheck] Querying external authorization service...")
        raise ConnectionError("Cannot connect to authorization service")

class AuditLogger(InterventionHandler):
    name = "audit-logger"

    @property
    def on_error(self) -> OnError:
        return "proceed"

    def before_tool_call(self, event: BeforeToolCallEvent):
        print(f"[AuditLogger] Recording to log service...")
        raise ConnectionError("Cannot connect to log service")

ExternalAuthCheck has on_error = "deny", so if the authorization service goes down, it fails safely by blocking the tool call. AuditLogger has on_error = "proceed", so even if the log service goes down, the agent's processing is not stopped.

Execution result (on_error='deny': Authorization service down → Fail-close rejection)
I will search for the latest quarterly report.
Tool #1: search

[ExternalAuthCheck] Querying external authorization service...
I'm sorry. I was unable to access the search function
(an error occurred because the authorization service could not be connected).
Execution result (on_error='proceed': Log service down → Skip and continue)
I will search for the latest quarterly report.
Tool #1: search
[AuditLogger] Recording to log service...
The search for the latest quarterly report has been completed.

With deny, the tool is blocked when the authorization service goes down, while with proceed, the tool executes normally even if the log recording fails. I found it interesting that you can declare in a single line per handler which side to fail toward in the event of a failure. It broadens the perspective when designing behavior.

Which Should You Use: Hooks, Plugins, or Interventions?

Strands Agents provides three mechanisms for intervening in agent behavior: Hooks, Plugins, and Interventions. It's easy to get confused since their functionality is similar, but according to the official documentation, Interventions are implemented internally using Hooks' callback registration. In other words, they share the same foundation but differ in how they communicate with the framework.

Here's a rough summary:

Aspect Hooks Plugins Interventions
What it does Directly rewrites event properties Bundles behavior extensions using Hooks and tools into reusable units Returns typed actions
How to communicate cancellation event.cancel_tool = "reason" Same Return Deny(reason="reason")
Behavior when multiple are registered Last one to rewrite wins Same Deny cuts off immediately, Guide accumulates feedback
Failure policy Exceptions always propagate Same Can choose throw / proceed / deny with on_error
Human approval Manage interrupt yourself Same Confirm is built in
Best suited for Observation-oriented use like logging, metrics, debugging Package observation + related tools together Control-oriented use like authorization, guardrails, content transformation

My impression is that Interventions are suited for control-oriented use cases where you want to stop or change agent behavior, while Hooks are better for observation-only use cases or behaviors that Interventions can't cover.

While Hooks offer the flexibility to freely rewrite events, if multiple Hooks touch the same property, the last rewrite wins — making it prone to unintended behavior when using multiple Hooks simultaneously for control purposes. Interventions, on the other hand, have a fixed set of returnable action types, so the framework handles conflicts for you.

Plugins are a mechanism for bundling low-level Agent elements — including Hooks and tools — into reusable units of behavior extension. Built-in Plugins such as Skills, Steering, and Context Offloader are also available, enabling use cases beyond the simple "Hook + tool" pattern. If you want to distribute observation and tools together, such as a "log collection Hook + log search tool" combo, bundling them into a Plugin is a good approach.

Personally, I think the easiest approach is to first check whether built-in Plugins (like Steering) or built-in InterventionHandlers (like HumanInTheLoop) can meet your requirements, and if so, just use them as-is. When you find something lacking, that's when you can write custom logic with your own InterventionHandler or Hooks — I think that's a good way to think about it.

By the way, in the Python version, Steering is provided as a Plugins interface and enables LLM-based guidance using custom Steering Actions. Rather than writing conditions with if statements like in today's SignatureValidator, it's suited for cases where you want to have the LLM judge ambiguous rules like "use a professional tone in emails." It's helpful to think of custom Interventions as deterministic control where you write conditions manually, and Steering as flexible guidance delegated to the LLM.

https://strandsagents.com/docs/user-guide/concepts/plugins/steering/

Closing Thoughts

Strands Agents keeps gaining new capabilities, so there's a lot to keep up with. I'd like to keep Interventions in mind as one of the options when controlling AI agents.

In the Confirm section of this article, I wrote my own interrupt resume loop by hand, but as I mentioned along the way, Strands Agents provides a built-in handler called HumanInTheLoop that can also implement human approval flows. Next time, I'd like to try using this Human in the Loop handler to implement an approval flow!

I hope this article was helpful in some way. Thank you so much for reading all the way to the end!!

Share this article

AWSのお困り事はクラスメソッドへ