AWSAWS Certified Generative AI Developer - Professional2026-103.1 Implement input and output safety controls
Separate tool defects from hostile instructions
Completed by the knowledge check
Learning objective
Distinguish malformed tool responses from malicious instructions embedded in untrusted tool output.
Core idea
A tool response crosses two boundaries: a serialization contract and an instruction-trust boundary. A response can fail either, both, or neither. A truncated JSON document is a contract defect. A valid JSON field that tells the model to ignore its developer instructions is an injection attempt. Parsing successfully does not make that field authoritative.
For an architect designing an agent, the decision is whether to repair a technical failure, exclude hostile content, or admit validated evidence. Keep those outcomes separate because their recovery paths differ. Retrying a broken response can recover useful data; retrying a malicious document can deliver the same attack again. Calling every parse failure an attack also hides adapter defects and creates unnecessary security alerts.
How it works
Validate the envelope before interpreting its contents
In Amazon Bedrock’s Converse tool-use flow, a model requests a tool through a toolUse block. The application executes the tool and sends a toolResult block in a user message. ToolResultBlock requires toolUseId and content; toolUseId identifies the preceding tool request. The client-side example returns structured data in content[].json or an error explanation in content[].text. ToolResultBlock.status supports success and error, but AWS scopes that field to Amazon Nova and Anthropic Claude 3 and 4 models.
Treat this envelope as a correlation mechanism, not an endorsement of the returned data. Your adapter should confirm that the result belongs to an outstanding request, decode the expected media type, and validate the tool-specific schema. The Bedrock envelope does not define whether your invoice amount is numeric, whether a document belongs to the caller, or whether an external search snippet is trustworthy. Those are application checks.
Examples of malformed output include missing required business fields, incompatible value types, invalid encoding, and incomplete data after a connection failure. An unexpected HTML error page from a tool that promises JSON belongs in this category even when it contains no hostile instruction. Reject it before adding it to model context. Preserve a bounded diagnostic for operators rather than asking the model to guess the missing structure.
Inspect data for attempts to gain instruction authority
A malicious tool response can satisfy every structural check. A search result might contain a valid summary string instructing the assistant to disclose confidential configuration. A ticket description might claim to be an administrator message and demand a different tool call. The problem is the requested change in authority, not the JSON syntax.
Keep application-owned instructions separate from retrieved or tool-owned text. Preserve the source identity and the outstanding request identity when you construct context. Do not copy a returned field into the system prompt because the field is named instructions. An authenticated tool can retrieve attacker-controlled records; authenticating the connection does not authenticate every instruction-like sentence in those records.
Bedrock documents a significant enforcement boundary: a guardrail supplied through Converse guardrailConfig does not evaluate messages[].content[].toolResult, tool definitions, or model-generated toolUse.input. That exclusion applies to all listed guardrail filters, including prompt attack detection. A clean inline guardrail assessment therefore says nothing about the tool-result field that carried the attack.
For textual content you intend to admit, add a separate assessment path. ApplyGuardrail accepts content independently of a model invocation, with source: INPUT or OUTPUT; its text blocks support the guard_content qualifier. Use an explicit input assessment for extracted untrusted text, alongside application checks for instruction redirection. Verify that the selected policy actually assesses the extracted content in your tests. This is a separate call, not coverage inherited from the original toolResult block.
Route failures by the boundary they crossed
Keep at least three application outcomes: invalid contract, suspected hostile content, and accepted evidence. These are application classifications, not Bedrock status enums. A contract failure can trigger a bounded retry only when the operation is safe to repeat. A hostile-content finding should exclude the content from the next model request and produce a safe terminal result or a separately authorized alternative source.
Where supported, use status: error to communicate a tool failure without forwarding the raw hostile body. It is not a malware classification or a universal feature of every model. Your adapter still needs its own routing decision and a model-compatible failure representation.
A tool response crosses the serialization contract before the instruction-trust boundary, and a failure at each has a different recovery path.
Key distinctions and trade-offs
The following cases require different evidence:
| Result | Structural check | Trust check | Application decision |
|---|---|---|---|
| Truncated invoice JSON | Fails | Not established | Reject; consider a bounded technical retry |
| Valid ticket with a takeover instruction | Passes | Fails | Exclude hostile content; do not promote its instructions |
| Valid record from the wrong tenant | Passes | Authorization fails | Reject independently of attack classification |
| Valid authorized facts | Passes | No detected redirection | Admit as evidence with source identity |
Removing all natural-language text reduces the attack surface but can remove the evidence the user needs. A safer design projects only the fields needed for the task and keeps their provenance. Sanitization can enforce an allowlist of fields; it cannot prove that every retained sentence is benign. See 3.1.8 for attack classes and 3.1.9 for the broader enforcement pipeline.
Architecture / decision scenario
A support agent reads an external ticket before proposing a refund. One response is truncated before the amount field closes. A second response is valid JSON but its description tells the assistant to ignore approval policy and refund a different account.
The adapter rejects the first response as invalid and permits one safe read retry. It rejects the second response through the trust path, retains its ticket identifier for investigation, and sends a controlled failure result rather than the attack text. Neither outcome authorizes a refund. The refund adapter checks the caller and account independently before any side effect; see 3.2.2.
The release test asserts both classifications and confirms that neither raw response enters the next Converse request. A test that checks only the assistant’s final wording misses an unauthorized intermediate tool call.
Common exam traps
- Treating valid JSON as proof that tool output is safe.
- Assuming an internal tool cannot return attacker-controlled records.
- Expecting Converse
guardrailConfigto inspecttoolResultautomatically. - Using
status: erroras a portable security classification across all models. - Repairing a malicious instruction by asking the model to reinterpret it.
- Retrying every rejected response without distinguishing defects from attacks.
What to remember
Separate envelope validity, business validity, authorization, and instruction trust. Bedrock correlates tool results through toolUseId; your application decides what evidence to admit. Inline Guardrails exclude tool-result content, so test a separate assessment path. Repair recoverable defects, exclude hostile instructions, and keep tool authorization independent of both.
Knowledge check
A ticket tool that promises JSON returns a body cut off mid-object after a connection reset. It contains no instruction-like text, and the read is safe to repeat. How should the adapter handle it?
A ticket tool returns valid JSON whose description field tells the assistant to ignore the approval policy and refund a different account. How should the adapter handle the description?
An agent’s Converse calls include guardrailConfig with prompt attack detection enabled. A red-team test plants an injection in a tool result, and the guardrail does not intervene. What explains this, and what is needed?
HIGHtoolResult ; assess the extracted text with ApplyGuardrailguardContent wrapper inside toolResult to be assessedtoolResult content, tool definitions or toolUse.input , for every filter including prompt attack detection. Untrusted text that will be admitted needs a separate, tested assessment such as ApplyGuardrail with source: INPUT .A customer-records tool returns a well-formed record with no instruction-like text, but the record belongs to a different tenant from the caller. How should the adapter classify it?