Skip to lesson

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

Validate tool contracts at every boundary

Completed by the knowledge check

Learning objective

Validate Strands and Lambda tool contracts with typed function schemas, parameter checks, and explicit error handling

Core idea

For an engineer connecting an agent to a tool, a schema communicates what the model can request; the implementation decides what it can execute. Type annotations and JSON schemas improve the interface, but a syntactically valid argument can still identify another tenant’s record, exceed an allowed amount, or request a forbidden operation.

Validate the contract at both ends. Check parameters before the side effect, then check and normalize the returned result before it enters the agent’s context. Keep transport errors, function-execution errors, business rejection, and uncertain execution distinct. The next action depends on which outcome occurred.

Strands tools and Lambda functions occupy different layers. A Strands tool can wrap a Lambda invocation, but Lambda does not automatically inherit the tool’s schema or business validation. The adapter must map arguments, trusted caller context, invocation responses, and tool results explicitly.

How it works

Publish a typed and narrow interface

Strands discovers Python tools through the @tool decorator. The decorator uses the function’s docstring and type hints as the tool contract. Choose names and descriptions that make required inputs, units, and side effects clear. A string named amount leaves more ambiguity than a documented integer representing minor currency units.

Use the narrowest operation that the caller needs. A tool that retrieves a customer record should not accept an arbitrary AWS action, table name, or unrestricted query. Keep trusted tenant identity and execution identity in server-side context rather than giving the model responsibility for selecting them.

For Bedrock tool-use interfaces, ToolSpecification carries name, description, and inputSchema. The schema is required; the tool name is required, limited to 1–64 characters, and accepts letters, numbers, underscores, and hyphens. A useful schema specifies required properties and their intended types, while the implementation enforces the same contract.

Keep discovery and execution contracts consistent. If the description says the tool is read-only but the implementation writes an audit-sensitive business record, the interface misrepresents its effect. If the function expects an identifier and the schema publishes a display name, the model cannot reliably construct a valid call. Treat a contract revision as a coordinated change across the decorator, adapter, and executor.

Check parameters before execution

The AWS Strands security guidance identifies BeforeToolCallEvent as the boundary for inspecting tool parameters. A hook reads event.tool_use, and setting event.cancel_tool cancels a rejected call before the action occurs. This supports shared checks such as tool-name allowlists and parameter validation without putting all policy text into the prompt; see 2.1.1 for hook registration.

Apply deterministic checks for structure and business constraints. Verify required fields, types, allowed values, size bounds, identifier syntax, and relationships among fields. Then check the target against authenticated caller context and business state. A positive amount can pass a type check while exceeding the reviewer’s authorized limit; a valid customer identifier can belong to another tenant.

Repeat the essential checks inside the Lambda executor. The agent hook is an early rejection boundary, while the executor protects the action if another authorized caller invokes the function directly. Use the same contract definition or explicitly version the two representations so their rules cannot drift unnoticed.

Do not silently repair consequential arguments. Normalizing harmless whitespace can be part of a defined contract. Replacing an unknown customer with a similar name or rounding a payment amount changes the requested action. Return a precise rejection and require a corrected request instead.

Validate and normalize outputs

The Strands AfterToolCallEvent hook can inspect a tool’s result and replace unsafe content before it reaches the agent. AWS’s example replaces event.result with a structured error containing toolUseId, status, and content. Use that boundary for output schema checks as well as content-policy checks.

A returned JSON object needs validation just as much as input JSON. Verify identifiers, required fields, numeric units, and the declared result version. Preserve source references and distinguish “not found” from “lookup unavailable.” An empty object that erases those differences encourages the model to invent a successful result.

Bedrock ToolResultBlock.toolUseId binds the response to the request that produced it, and content carries the result blocks. Its optional status accepts success or error; AWS documents support for that field specifically for Amazon Nova and Anthropic Claude 3 and 4 models. Do not assume every model interface interprets the field identically. Keep the application’s own error handling independent of whether the model understands that marker.

Tool output remains data, even when it contains instructions. A returned web page must not alter the registered tool set or the validation rules. Model-level content controls do not replace checks at these tool boundaries; the concrete Strands hooks let the application inspect the interaction itself.

Map Lambda outcomes without losing meaning

When an adapter calls Lambda Invoke, use InvocationType: RequestResponse if it needs a result for the agent’s next step. The invocation response includes StatusCode, optional FunctionError, and Payload. A 200 status means the synchronous invocation request succeeded; FunctionError indicates an error during function execution, whose details appear in the payload.

Do not treat successful invocation as successful business execution. A function can complete normally and return your application’s rejected-result envelope. The adapter must check both the Lambda-level outcome and the documented payload contract. Parse the payload, verify its schema, and map it to a successful observation, correctable rejection, transient failure, or uncertain action result.

InvocationType: Event returns an asynchronous acceptance status of 202 rather than a synchronous tool result. Do not feed that acceptance to the agent as the completed lookup or write. If your design uses asynchronous work, provide a separate completion mechanism and keep the action pending until it resolves.

A synchronous invocation reaches the agent only after the adapter checks both the Lambda-level outcome and the payload contract, while an asynchronous acceptance keeps the action pending.

A synchronous result reaches the agent only after both checks, while an asynchronous acceptance keeps the action pendingStarts at Lambda Invoke. With InvocationType Event, a 202 acceptance keeps the action pending. With RequestResponse, a present FunctionError is a function-execution error; otherwise the adapter parses the payload, verifies its schema, and maps it to one of four outcomes: a successful observation, a correctable rejection, a transient failure, or an uncertain action result.EventRequestResponsepresentabsentmap it toLambda Invoke202 acceptanceKeep the actionpendingFunctionError?Function-executionerrorParse payload,verify schemaSuccessfulobservation,correctablerejection,transient failure,or uncertain actionresult

If Step Functions invokes the executor through its optimized Lambda integration, an exception raised in the Lambda function fails the Task, and the integration parses the response Payload into JSON. Choose which failures raise exceptions and which return business decisions. A returned rejection envelope needs explicit routing; it does not automatically activate a workflow Catch.

Key distinctions and trade-offs

The checks have different responsibilities:

BoundaryRequired interpretation
Type hints and published schemaWhat arguments the tool advertises
BeforeToolCallEventWhether the proposed call should reach the executor
Lambda executor validationWhether this caller and business state permit execution
Lambda invocation responseWhether invocation and function execution completed
AfterToolCallEventWhether the observation is valid and safe to return

Detailed errors help the model correct its arguments, but unrestricted exception text can disclose sensitive implementation details. Return bounded public error codes and useful correction hints, while retaining diagnostic detail in trusted operational records.

Architecture / decision scenario

A Strands purchasing assistant exposes a typed reserve_inventory tool whose documented inputs are product identifier and integer quantity. The wrapper supplies tenant and execution identity from trusted context and invokes a Lambda executor synchronously.

The BeforeToolCallEvent hook rejects a negative quantity before invocation. The Lambda function independently checks the same constraint, resolves the product within the tenant, and verifies available stock. Insufficient stock returns an explicit business rejection; an unexpected execution exception produces FunctionError, which the adapter handles separately from the rejection payload.

A successful result includes the reservation identifier, quantity, and operation identifier. The adapter validates those fields and retains the request’s toolUseId. AfterToolCallEvent rejects a malformed result before it enters the agent’s context. If the invocation connection fails after a possible reservation, the adapter records an uncertain outcome and reconciles by operation identifier instead of creating another reservation. See 2.1.7 for shared retry limits.

Common exam traps

  • Treating type hints or inputSchema as authorization.
  • Protecting the Strands hook while leaving the Lambda executor unchecked.
  • Reading Lambda status 200 as proof of business success.
  • Reading asynchronous status 202 as the completed tool result.
  • Assuming a returned rejection activates Step Functions Catch.
  • Losing toolUseId or assuming universal support for the result status field.

What to remember

  • Advertise a typed contract and enforce it before the side effect.
  • Validate inputs at the hook and executor boundaries.
  • Inspect Lambda FunctionError and the business payload separately.
  • Normalize and validate output before returning it to the agent.
  • Preserve request identity and reconcile uncertain writes before retrying.

Knowledge check

References