Steering and structure: controls outside the prompt
Every team's first instinct for controlling an agent is to add a sentence to the prompt. Sometimes that is right; often it is the weakest tool on the shelf reached for first. This chapter arranges the model plane's control surfaces into a ladder, from negotiable to absolute, and decodes the AWS pieces (structured output, Bedrock Guardrails, and their agent-shaped gaps) so that Part 8 can later build the full trust story on named parts.
The ladder
Four rungs, ordered by how a failure looks:
| Rung | Mechanism | A failure looks like | Lives in |
|---|---|---|---|
| Ask | Prompt instructions | The model, having weighed your request, does something else | The prompt |
| Constrain | Schemas: structured output, strict tool arguments | Cannot occur; invalid shapes are unrepresentable | The API request |
| Filter | Guardrails: content policies applied to text crossing the boundary | Flagged or blocked text, with a machine-readable reason | The platform, per call |
| Forbid | Permissions and policy: IAM, and rules enforced outside the loop | Denied action, regardless of what any text said | The platform, always |
The ladder's law: push every control to the lowest rung that can express it. Prompts are for judgment ("prefer primary sources"). Anything with a checkable shape belongs in a schema. Anything about acceptable content belongs in a filter. Anything about what the agent may do belongs in permissions, where models cannot negotiate at all. The recurring production failure is rung inversion: a prompt begging "never call delete_user twice" doing a job that an idempotency key and an IAM policy do perfectly.
Constrain: schemas as guarantees
Rung two got a full chapter from the tool side (tool design); the model plane adds its symmetric twin. Structured output constrains the model's response to a JSON Schema you supply: the platform enforces shape, so the parsing code downstream stops being defensive. Strict tool use does the same for tool arguments: enforced validity, not just likely validity. Between them, an agent's entire data interface (what it emits and what it calls) can be made schema-valid by construction, and every error class you make unrepresentable here is a guardrail or a try/except you do not write later.
The limit of rung two is meaning. A schema guarantees severity is one
of three strings; it cannot guarantee the severity is warranted.
Shape is checkable, truth is not, which is why the rungs above and
below both still exist, and why Part 6 ultimately adds verification
agents: judged truth, purchased with more tokens.
Filter: Bedrock Guardrails, decoded
Guardrails is Bedrock's managed content-filtering service. You define a guardrail as configuration (versioned, reusable across models), and the platform evaluates text against it. Inside one guardrail, several policy types compose:
- Content filters: classifiers for the standard harm categories, with adjustable thresholds per category.
- Denied topics: subjects defined in natural language that the system should refuse to engage ("investment advice"), enforced by a classifier rather than your prompt's willpower.
- Sensitive information: pattern and entity detection for PII, with a choice per entity type of blocking the text or redacting it (masking the entity and letting the rest through), which for agent pipelines is usually the useful mode: the document flows on, the account numbers do not.
- Prompt-attack detection: a classifier for injection-shaped input (jailbreak phrasing, instruction-smuggling), the platform's contribution to the injection defenses of Part 8.
- Contextual grounding: checks a response against supplied source text, flagging claims the source does not support, a first mechanical whack at hallucination in retrieval-backed answers.
Mechanically there are two ways to invoke all this. Attached to a model
call, the guardrail wraps that call's input and output automatically.
Standalone, via the ApplyGuardrail API, you evaluate any text you
like, wherever you are in your own control flow, no model call
involved; and a 2026 addition (InvokeGuardrailChecks) streamlines the
detect-only version of the same idea for exactly the use this book
cares about: checking text mid-agent-loop without managing guardrail
attachments per call.
That standalone mode matters because of a gap worth stating plainly: a guardrail wraps a model call's edges, and an agent's most dangerous text does not always arrive at those edges. The classic wrap sees the user's input and the model's final answer. But in the loop, tool results enter the conversation between those edges, and a tool result fetched from the outside world (a web page, a document, a ticket body) is exactly where injected instructions ride in. The platform's own guidance for agentic systems agrees: run the checks yourself at the tool boundary. In Hive, that is a one-liner in the loop, the same place the event store hooks: tool returned, check the text, then append it.
The follow-along shape (T1, illustrative output; a guardrail must exist first, created in the console or by API):
import boto3
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
verdict = bedrock.apply_guardrail(
guardrailIdentifier="gr-abc123",
guardrailVersion="1",
source="INPUT",
content=[{"text": {"text": tool_result_text}}],
)
print(verdict["action"])
(illustrative)
GUARDRAIL_INTERVENED
with the response detailing which policy fired and, for sensitive-info policies, the redacted text to use instead. What the loop does on intervention is a design decision from the tool-design chapter's error playbook: replace the result with an error message the model can act on ("the fetched page was withheld by content policy"), log the event, and continue.
What filters cannot do
The honest paragraph, before Part 8 relies on it. Guardrails are classifiers: probabilistic, bypassable by sufficiently novel phrasing, and blind to authorization. A perfectly polite, perfectly on-topic request to read another tenant's records sails through every content policy, because nothing about it is a content problem; it is a permissions problem, rung four's job. And the injection arms race is real: prompt-attack detection catches the known shapes cheaply, which is worth having, and the defense that does not decay is capping what a fooled agent can do (tools, IAM, egress), not perfecting the detection of fooling. Rung three earns its place as a cost-effective sieve and a compliance surface (the PII redaction especially), never as the boundary the design leans on.
Don't be confused: Guardrails vs Policy vs IAM. Three "the agent is not allowed" mechanisms, three different subjects. Guardrails judge content: text crossing a boundary. AgentCore's Policy judges behavior: which actions an agent may take, rules compiled to Cedar and enforced outside the reasoning loop (decoder ring). IAM judges identity: what the credentials behind an action may touch, regardless of any text or rule about the agent itself. Complete designs use all three, and confusion between them is how systems end up with a content filter guarding a permissions hole.
👉 Next: throughput engineering, where the model plane stops being a single call and becomes a shared pipe, and a lab manufactures a 429 storm in order to abolish it.