Skip to lesson

AWSAWS Certified Generative AI Developer - Professional2026-102.1 Implement agentic AI solutions and tool integrations

Bound the loop before granting tools

Completed by the knowledge check

Learning objective

Implement the agent loop with Strands Agents model, tools, state, and termination criteria.

Core idea

An agent loop lets a model choose the next action after observing the previous result. In Strands Agents, an Agent combines the model, its instructions, and its available tools. The SDK handles the repeated exchange between model inference and tool execution until the model produces a final answer.

For a production design, distinguish model completion from application completion. A final answer ends the reasoning loop, but it does not prove that an order was changed, a tool succeeded, or the evidence supports the answer. You define the business success condition and enforce resource and permission boundaries outside the model’s instructions.

Treat autonomy as a bounded search for an acceptable result. Give the agent enough tools to discover a path, a state representation that preserves what happened, and a terminal outcome when the path cannot be completed safely. A prompt that says “stop after several attempts” is guidance, not an execution limit.

How it works

Select the model and tool contract

The Agent constructor accepts model, tools, and system_prompt. For Amazon Bedrock, the BedrockModel provider accepts model_id and region_name. Set these explicitly so that the deployed configuration identifies the model and invocation Region. Model eligibility and inference-profile boundaries belong to 1.2.1 and 1.2.4; an agent framework does not remove those constraints.

Define Python tools with the @tool decorator and register them in tools. Strands uses the function’s type hints and docstring to describe its contract to the model. A clear tool description separates reading an order from submitting a cancellation. Ambiguous descriptions make the model choose between operations without knowing their consequences.

The model proposes a tool name and arguments; application code performs the operation. Validate identifiers and business preconditions inside that code. Bind the caller’s authorization context through trusted application data rather than accepting a tenant or customer identity supplied by the model. A well-typed argument can still name an unauthorized resource.

Preserve observations and working state

Strands maintains conversation history in agent.messages. The history contains the context used for subsequent reasoning, including observations from tool use. The loop incorporates a tool result before asking the model what to do next. This is the feedback path that distinguishes an agent from a single inference call.

Keep authoritative application state separate from conversational assertions. For example, your application can track an order revision, the number of attempted lookups, a deadline, and whether an approval exists. Those fields are your design, not automatically created Strands properties. Update them from validated tool outcomes, not from a sentence in the assistant’s response. An AfterToolCallEvent callback receives event.result, including toolUseId, status, and content, after execution and before the result reaches the agent. Use it to classify outcomes and update attempt counters; it can also replace event.result, for example with status: "error" when validation fails.

A retry needs the observation that caused it. Preserve whether the tool returned no matching record, rejected permission, or failed operationally. Those outcomes call for different behavior: clarify an identifier, stop an unauthorized action, or retry a transient failure. Do not flatten all three into “try another tool.” Session persistence and AgentCore Memory are covered in 2.1.3.

Enforce termination at execution boundaries

Use separate terminal conditions for success, missing input, denied action, exhausted budget, and infrastructure failure. A successful run needs a verified result; a blocked run needs an explanation that does not imply the requested operation occurred.

Strands exposes lifecycle callbacks through HookProvider, registered using HookRegistry, and accepts hook instances through the hooks constructor parameter. A BeforeToolCallEvent callback can inspect event.tool_use before execution and set event.cancel_tool to cancel that tool call. This is a concrete interception point for checking your application-maintained attempt budget or approval requirement before another side effect.

Canceling a tool call is not equivalent to terminating all reasoning. The agent may receive the cancellation and continue. Enforce an overall deadline and inference-attempt budget in the code that owns execution as well. Count nested calls and retries against the same request budget; otherwise, each layer can obey its local limit while the complete request keeps running.

For an AgentCore-hosted agent, LifecycleConfiguration provides idleRuntimeSessionTimeout and maxLifetime. Their defaults are 900 and 28,800 seconds respectively. For microVM compute, each accepts 60–28,800 seconds; Instances compute accepts up to 1,209,600 seconds, or 14 days. These are compute-lifecycle settings, not business step limits. An active loop is not idle, and a long compute lifetime does not authorize more tool calls.

Key distinctions and trade-offs

Model autonomy versus application control: The model chooses among exposed operations. Your code controls whether their arguments and effects are permitted. Strands tool registration describes capability; it does not establish business authorization.

Conversation history versus authoritative state: History supports reasoning. A validated tool result establishes that an operation occurred. A model-generated summary cannot replace the operation’s returned identifier or status.

Natural completion versus bounded termination: A final answer is the loop’s ordinary completion path. A deadline or exhausted attempt budget is an application terminal outcome. Design both, because an agent can finish too early or continue without progress.

A larger tool set increases the available solution paths but also increases selection ambiguity and the number of privileged operations you must protect. Start with task-specific tools. Add a general-purpose operation only when the use case needs it and its authorization boundary remains enforceable.

Architecture / decision scenario

A support agent must explain why a delivery is late and cancel an order only when the customer requests cancellation and the order is eligible. The team configures Agent with an explicit BedrockModel, a read-only order-status tool, and a separate cancellation tool.

The backend binds the authenticated customer’s identity before entering the loop. It records the authoritative order revision from the lookup result and maintains a shared attempt count and deadline. These application controls prevent an uncertain lookup from becoming an unlimited investigation.

A BeforeToolCallEvent hook cancels a cancellation request when the required approval or remaining budget is absent. The cancellation tool independently checks ownership and eligibility before acting. If the operation succeeds, the tool returns its operation identifier, which becomes the evidence for completion.

If the model produces an answer claiming cancellation without that identifier, the application rejects the completion claim. If the tool fails transiently, the application permits a bounded retry; if ownership fails, it stops the action. The agent can still explain delivery status without presenting a denied cancellation as successful.

Common exam traps

  • Treating system_prompt instructions as a hard execution or authorization limit.
  • Assuming the model executes a tool directly without application enforcement.
  • Treating a final answer as proof that the requested side effect succeeded.
  • Using agent.messages as the authoritative record of a business transaction.
  • Assuming event.cancel_tool terminates the entire agent loop.
  • Using an idle-session timeout to bound an active reasoning loop.
  • Giving every nested agent its own fresh budget and calling the complete run bounded.

What to remember

  • Configure Agent with an explicit model, tool set, and instructions.
  • Use @tool contracts to describe operations and application code to authorize them.
  • Preserve observations while keeping business state authoritative outside model prose.
  • Use lifecycle hooks to intercept calls and execution-owner controls to bound the complete run.
  • Verify success separately from model completion.

Knowledge check

References