Join our Newsletter — 33% off our NHI Course
Home› Guides› AWS Strands Agents SDK Security Guide: Securing tools,…
Guide MCP, Protocols & Agent Platforms

AWS Strands Agents SDK Security Guide: Securing tools, IAM credentials and MCP clients in code

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 14 November 2026 17 min read
On this page

A Strands agent runs inside your own process, so every tool it calls, every MCP server it connects to and every AWS API it reaches uses the credentials and permissions of that process, and the SDK settings you choose in code are the main control between a model's output and your systems. Strands Agents is an open-source SDK, published under the strands-agents GitHub organisation, for building agents in Python and TypeScript; its documentation describes it as "a library, not a platform", with Amazon Bedrock as the default model provider. This guide covers the SDK layer: model credentials and IAM, tool selection, MCP client authentication and filtering, approval interrupts and hooks, execution limits, session storage and telemetry. The hosting runtime is covered separately in the AWS Bedrock AgentCore Security Guide, so this page stays with what the developer controls in code. It is for platform engineers, application security teams and reviewers signing off Strands-based agents. Settings were checked against the Strands documentation on 14 November 2026.

This is an independent guide from NHI Mgmt Group, based on the Strands Agents public documentation as of November 2026. It is not sponsored or reviewed by AWS. Product features change, so confirm settings against the current Strands documentation.

Key takeaways

  • The host process is the permission boundary. The Strands tools documentation states that all tools execute code with the permissions of the host process, so the IAM role or credentials behind that process set the real blast radius, not the system prompt.
  • Scope the model permissions to specific models. Strands needs bedrock:InvokeModelWithResponseStream for streaming and bedrock:InvokeModel otherwise; the sample policy uses "Resource": "*" and the docs say to narrow it to model ARNs in production.
  • Filter MCP tools at the client. MCPClient accepts tool_filters with allowed and rejected lists, so an agent sees only the server tools it needs, and credentials can be kept out of config with ${VAR} interpolation.
  • Put approval in a hook, not a prompt. BeforeToolCallEvent lets code pause a call with event.interrupt() or block it with cancel_tool, which holds even when the model has been steered by injected content.
  • Session files and traces hold sensitive data. Sessions persist messages and agent state, and trace spans can include prompts and tool inputs and outputs, so both need access control, retention and redaction.

Where the SDK sits in the trust model

Strands runs an agent loop: the model receives the conversation and tool descriptions, returns text or tool calls, the SDK executes those calls and feeds results back, and the loop repeats until a stop reason is reached. Each element that touches the outside world is wired up in your code.

LayerWhat Strands providesWhat you configure and own
Model accessBedrockModel and other providers, boto3 credential chainWhich credentials, which region, which model ARNs the role may invoke
Tools@tool decorator, vended tools (shell, Python REPL, HTTP, file write and edit)The explicit tool list, what each tool can read, write and call
MCPMCPClient over stdio, Streamable HTTP and SSEWhich servers, their authentication, tool filters
Control pointsHooks, interrupts, HumanInTheLoop, limitsWhich calls need approval, quotas, deadlines
StateSession managers (local file, S3, custom repository)Session IDs, storage permissions, retention
TelemetryOpenTelemetry traces and metricsExporters, redaction, who can read traces

If the agent is deployed to AgentCore Runtime, the runtime adds a dedicated microVM per user session and inbound authentication; the SDK controls on this page still apply inside it.

Model credentials and IAM

Strands uses boto3 for Bedrock, so credentials resolve through the standard boto3 chain: environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN), shared config and profiles, or a custom boto3 Session passed as boto_session. TypeScript takes credentials in clientConfig.credentials. The docs also describe an api_key option for an Amazon Bedrock API key, which uses bearer token authentication instead of SigV4 signing.

  • Prefer roles to keys: run the agent under an IAM role (instance profile, task role, or the AgentCore execution role) so credentials are temporary. Long-lived access keys in environment variables or .env files are the pattern ATT&CK tracks as T1552.001 Credentials In Files. See the AWS IAM Roles vs IAM Users.
  • Treat a Bedrock API key as a secret: if you use api_key, store it in a secrets manager, rotate it and scope it, because a bearer token works for whoever holds it.
  • Pin the region: Python resolves the region from region_name, then the boto3 session region (AWS_DEFAULT_REGION or the profile), then AWS_REGION, then a default of us-west-2. The docs warn that AWS_REGION ranks below profile regions. Set region_name explicitly where data residency matters, and use the regional inference profile prefix (for example eu.) that matches it.
  • Pin the model: with no model specified the SDK picks a default based on the credentials' region. The production guide says to pass an explicit model configuration (model_id, max_tokens and sampling settings) instead of relying on defaults.
NeedIAM action (from the Strands Bedrock page)Scoping advice
Streaming responsesbedrock:InvokeModelWithResponseStreamResource: the specific foundation model or inference profile ARNs
Non-streaming responsesbedrock:InvokeModelSame model ARNs; grant only the mode you use
S3 document or media referencess3:GetObjectOnly the bucket and prefix the agent reads
Guardrail evaluationBedrock guardrail permissions per the Bedrock docsThe specific guardrail ARN and version
Tool calls to AWS servicesWhatever each tool's API calls needSeparate role or session policy per tool where practical

The last row is where most of the risk sits. A tool that calls AWS APIs uses the same process credentials as the model client unless you give it its own. Where a tool needs wider rights than the model client, have the tool assume a narrower role, or apply a session policy and a permissions boundary. See the AWS IAM Permissions Boundaries Guide and validate policies with the IAM Access Analyzer Guide.

Choosing and constraining tools

The production guide's first recommendation is to specify tools explicitly rather than loading everything available, and to keep automatic loading and reloading of tools disabled, which is the default (load_tools_from_directory=False). Turning directory loading on means any Python file written to that directory becomes a callable tool, which matters if anything, including the agent itself, can write there.

Tool typeTypical riskConstraint to apply
Shell or bashArbitrary command execution as the host userRun only in an isolated sandbox or container with no credentials; require approval per call
Python REPLArbitrary code, access to environment variables and filesSame as shell; never in a process holding production credentials
HTTP requestData exfiltration, server-side request forgery to metadata endpointsEgress allowlist at the network layer; block link-local addresses
File write and editOverwriting code, config or tool directoriesPath allowlist resolved with real paths; read-only mounts elsewhere
Custom @tool calling AWSOver-broad IAM, destructive operationsNarrow role per tool, approval for writes and deletes
Direct calls (agent.tool.name())Bypass interrupts, which the docs say do not apply to direct callsReserve for trusted application code paths, not model-driven flows

The Responsible AI page sets five tool design principles: least privilege, input validation, clear documentation, error handling and audit logging. In practice, validate tool arguments against an allowlist inside the tool, resolve file paths to their canonical form and compare against allowed directories with a trailing separator, and log the call with its arguments and outcome. Treat tool output as untrusted input to the next model turn: a web page or document fetched by one tool can carry instructions that target the next. For the wider pattern, see Agent Sandboxing vs Tool Allowlisting and Agent Egress Control and Network Isolation Guide.

MCP clients: authentication, filtering and lifecycle

Strands connects to MCP servers through MCPClient (Python) or McpClient (TypeScript), with stdio for local processes, Streamable HTTP for remote servers and SSE for older HTTP servers. Each connected server adds tools the model can call, so an MCP server is a supplier of capabilities and should go through the same review as code. See the MCP Security Guide and MCP Server Trust Assessment.

Authentication optionHow Strands configures itWhen to use
Static headersheaders on MCPClient (TypeScript: requestInit.headers)Servers that only accept a bearer token; load it from a secrets store, never a literal
OAuth client credentialsurl plus an auth block with client_id, client_secret, optional scopesMachine-to-machine access; tokens are fetched and refreshed automatically
Interactive OAuthauth_provider with an httpx.Auth implementation such as OAuthClientProviderAgents acting for a signed-in user (authorisation code flow)
AWS IAM (SigV4)aws_iam_streamablehttp_client from mcp-proxy-for-aws, with endpoint, region and serviceMCP servers hosted behind AWS IAM, such as AgentCore Gateway
  • Scopes are requests, not limits: the docs state that scopes is advisory and that scopes advertised by the server take precedence. Enforce least privilege on the authorisation server and the MCP server, not only in the client config. See the MCP Authorisation Specification Guide.
  • Keep secrets out of config files: in load_servers configuration, use ${VAR} placeholders for client_id and client_secret and inject the values from a secrets manager at start-up.
  • Filter tools: set tool_filters with an allowed list (strings or compiled regular expressions). In Python allowed is applied before rejected; in TypeScript rejection wins when both match. An allowlist is safer than a blocklist because new server tools stay hidden until reviewed.
  • Prefixes are labels, not controls: a prefix renames the tool for the agent only; calls still send the original server tool name. Use prefixes to avoid name collisions between servers, and write approval rules against the names the hook actually sees.
  • Handle elicitation deliberately: a server can pause a call and ask for input through elicitation. If you set elicitation_callback, route requests to a real user or decline them; never auto-answer with stored data.
  • Use managed lifecycle and timeouts: passing the client directly in Agent(tools=[...]) lets Strands manage the connection; the MCP page also recommends timeouts on tool calls.

For stdio servers, remember that the server is a child process running with your process's rights and environment. Pin the package version, avoid passing the full environment, and prefer remote servers with their own identity for anything that touches production data.

Approval, hooks and execution limits

Hooks are the SDK's enforcement points, and they run in code regardless of what the model decides. The events most relevant to security are BeforeToolCallEvent, AfterToolCallEvent, BeforeInvocationEvent, AfterInvocationEvent and the model call events.

ControlSDK mechanismSecurity use
Pause for approvalevent.interrupt(name, reason) on BeforeToolCallEvent; result has stop_reason == "interrupt"Human approval for writes, payments, deletes, external messages
Block a callevent.cancel_tool = "reason" (TypeScript: event.cancel)Deny by policy, for example tools outside business hours or over a quota
Rewrite argumentstool_use["input"] on BeforeToolCallEventForce fixed values such as a tenant ID or read-only flag
Inspect resultsresult on AfterToolCallEventRedact secrets or personal data before it reaches the model
Sanitise inputmessages on BeforeInvocationEventStrip or flag content before the loop starts
Vended approvalHumanInTheLoop with allowed_tools, classifier, enable_trustReady-made approval flow with optional session trust
  • Know the HumanInTheLoop defaults: tools in allowed_tools skip approval entirely and "*" disables the handler. Negated tools ("!tool_name") always prompt and cannot be trusted for the session. The docs note that "auto" mode may change in a minor release and that small decision models can rate risky calls as safe, so pin the strategy and negate tools that must always ask.
  • Bound the loop: set turn limits, invocation token limits and a wall-clock deadline (agent.cancel() from a watchdog in Python, a cancelSignal in TypeScript). The docs warn that token limits are checked between turns, so one model call can exceed the total. In multi-agent Swarm and Graph setups, bound both the orchestrator and each node.
  • Quota side-effecting tools: the documented Limit Tool Counts hook counts calls per tool and cancels calls past a limit, resetting on each invocation.

These controls address OWASP LLM06:2025 Excessive Agency and LLM10:2025 Unbounded Consumption. For design patterns beyond the SDK, see the Human-in-the-Loop for AI Agents Guide and Prompt Guardrails vs Policy Engines for AI Agent Actions.

Guardrails at the model boundary

BedrockModel accepts guardrail_id and guardrail_version to apply an Amazon Bedrock guardrail to model calls, with guardrail_trace for debugging. When a guardrail intervenes, the response has stop_reason == "guardrail_intervened". Input redaction (guardrail_redact_input) is on by default and overwrites the blocked input in conversation history; output redaction (guardrail_redact_output) is off by default, so turn it on if blocked output must not persist in sessions or traces. guardrail_latest_message limits evaluation to the newest user message, which reduces cost but means earlier content, including tool results, is not re-checked.

To trial a guardrail without blocking, the docs show a shadow mode: a hook calls the Bedrock ApplyGuardrail API on input and output and logs what would have been blocked. Run shadow mode in a pilot, review the hits, then switch to enforcing. Guardrails filter content; they do not authorise actions, so keep them alongside the hook and IAM controls above, not instead of them.

Sessions and state

Session managers persist conversation messages, agent state and conversation manager state; snapshots also include interrupt state, model state and the system prompt. Options include SnapshotSessionManager with LocalFileStorage or S3Storage, FileSessionManager, S3SessionManager and a custom RepositorySessionManager. With no storage configured, Python falls back to ./.strands/.

  • One session ID per user and conversation: the docs warn that agents sharing a session ID and agent ID write to the same history, and the default agent ID makes that collision easy. Derive session IDs server-side from the authenticated user, never from client input alone. See Agent Identity vs Agent Session Identity.
  • Session storage is trusted input: do not load sessions from untrusted sources such as files in a cloned repository; a tampered session can inject messages, state and approval decisions stored in agent.state.
  • Lock down storage: restrict filesystem permissions to the agent process. The docs note the SDK does not block symlinks in the storage directory, so in shared hosts use a dedicated directory no other user can write. For S3, use a dedicated bucket and prefix, block public access, encrypt with a customer managed KMS key and set lifecycle expiry.
  • Plan for concurrency: session managers are not thread-safe and use no distributed lock; serialise writes per session in your application.

Detection and measurement

Strands emits OpenTelemetry traces with spans for model and tool invocations. Model spans may include the system prompt, parameters, input and output messages and token usage; tool spans may include tool inputs and outputs. Route traces through an OpenTelemetry collector that redacts personal data and secrets, restrict who can read the trace store, and set retention. See Agent Observability vs Audit Logging.

Alongside traces, keep AWS-side evidence: CloudTrail records for Bedrock invocations and for every AWS API the tools call, tied to the role session name so calls can be traced to an agent run. Log every interrupt, approval, denial and cancel_tool decision with the tool name and arguments.

  • Tool allowlist coverage: share of agents whose tools are an explicit list and whose MCP clients use an allowed filter (target 100 per cent).
  • Approval coverage: share of side-effecting tools behind an interrupt or cancel_tool policy.
  • Denied and cancelled calls: count per agent per week; a sudden rise suggests injection attempts or a broken prompt.
  • Limit hits: how often turn, token and deadline limits are reached, which the production guide recommends tracking to tune limits.
  • Wildcard model permissions: number of agent roles still granting Bedrock invoke on "*" (target zero).
  • Guardrail interventions: rate of guardrail_intervened stop reasons, reviewed for false positives and real attacks.

Rollout plan

  1. Inventory: list every Strands agent, its model provider, tools, MCP servers, session storage and the identity it runs as. Record owners. The MCP Server Inventory Template covers the server side.
  2. Fix identity first: move agents from access keys to roles, scope Bedrock permissions to model ARNs, and split tool permissions into narrower roles where tools touch AWS resources.
  3. Constrain tools: replace any dynamic loading with explicit tool lists, add allowed filters to every MCPClient, and move shell, REPL and file tools into an isolated sandbox.
  4. Add control hooks in observe mode: log what an approval or quota hook would block, and run guardrails in shadow mode, for one or two weeks.
  5. Enforce: switch hooks to interrupt() and cancel_tool, enable guardrails, set turn, token and deadline limits. Pilot with one agent, then widen.
  6. Secure state and telemetry: move sessions to protected storage with server-side session IDs, add trace redaction, and set retention.
  7. Test and keep testing: add prompt injection and tool misuse cases to CI using the AI Agent Security Testing Checklist. Roll back by removing a tool or MCP server from the tool list and redeploying.

Common failure patterns

  • Developer credentials in production: an agent prototyped with aws configure keys ships with the same keys in an environment variable, giving the agent a human's rights.
  • Every tool available: a full vended tool set, including shell and Python REPL, left in a production agent that only needed two read tools.
  • MCP server with no filter: a connected server adds new write tools in an update and the agent can call them at once because there is no allowed list.
  • Approval rules in the prompt: "always ask before deleting" lives only in the system prompt, and injected content in a fetched document talks the model out of it. Put the rule in a hook.
  • Shared session IDs: a fixed or client-supplied session ID lets one user's history and trusted approvals load into another user's agent.
  • Traces as a data leak: full prompts and tool outputs, including customer records and tokens, exported to a tracing backend many people can read.

Framework mapping

Control areaNIST SP 800-53 Rev 5NIST CSF 2.0OWASP LLM Top 10 2025 / MITRE ATLAS
Scoped IAM for model and toolsAC-6 Least Privilege, AC-3 Access EnforcementPR.AA-05LLM06 Excessive Agency
Credentials for Bedrock and MCPIA-5 Authenticator ManagementPR.AA-05LLM02 Sensitive Information Disclosure
Approval hooks and tool filtersAC-3 Access EnforcementPR.AA-05LLM01 Prompt Injection; AML.T0053 AI Agent Tool Invocation
Guardrails at the model boundaryAC-3 Access EnforcementDE.CM-09LLM01 Prompt Injection; AML.T0051 LLM Prompt Injection
Execution limitsAC-6 Least PrivilegeDE.CM-09LLM10 Unbounded Consumption
Session storage protectionSC-28 Protection of Information at RestPR.AA-05LLM02 Sensitive Information Disclosure
Traces and audit logsAU-2 Event Logging, AU-12 Audit Record GenerationDE.CM-09LLM06 Excessive Agency

Relevant ATT&CK techniques for the identity side are T1078.004 Cloud Accounts, for misuse of the agent's role, and T1552.001 Credentials In Files, for keys left in config. See the OWASP Top 10 for LLM Applications Guide.

Practitioner checklist

  • Run every Strands agent under an IAM role with temporary credentials; no access keys in environment variables or files.
  • Scope bedrock:InvokeModel or bedrock:InvokeModelWithResponseStream to specific model or inference profile ARNs.
  • Set region_name and the model ID explicitly in code.
  • Pass an explicit tool list and keep load_tools_from_directory off.
  • Give every MCPClient an allowed tool filter and load MCP credentials from a secrets manager.
  • Gate side-effecting tools with BeforeToolCallEvent interrupts or cancel_tool policy, and negate must-ask tools in HumanInTheLoop.
  • Set turn, token and wall-clock limits at agent and multi-agent node level.
  • Enable Bedrock guardrails, and turn on output redaction where blocked output must not persist.
  • Derive session IDs server-side, protect session storage and never load untrusted sessions.
  • Redact traces in an OpenTelemetry collector, restrict access and set retention.

Standards and references

Related NHI Mgmt Group resources: AWS Bedrock AgentCore Security Guide · Amazon Bedrock Agents Security Guide · MCP Security Guide · Agent Identity and Access Guide · Non-Human Identity (NHI) Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 14 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.