{"slug": "has-any-one-ever-used-strands-the-ai-agent-sdk-by-aws", "title": "Has any one ever used Strands – the AI Agent SDK by AWS", "summary": "AWS has released Strands, an open-source AI agent SDK for building production agents, available via pip and npm. The SDK includes tools, hooks, and MCP server integrations for coding agents like Claude and Cursor. Strands supports Python and JavaScript, with features such as tool cancellation and source citation enforcement.", "body_md": "# The open source toolkit for buildingproduction agents.\n\n`pip install strands-agents`\n\n`npm install @strands-agents/sdk`\n\n``` python\nfrom strands import Agent, tool\nfrom strands.hooks import BeforeToolCallEvent\nfrom pathlib import Path\n\n@tool\ndef save_report(title: str, content: str) -> str:\n    \"\"\"Save a research report to disk.\"\"\"\n    path = f\"reports/{title}.md\"\n    Path(path).write_text(content)\n    return f\"Saved {path}\"\n\ndef require_sources(event: BeforeToolCallEvent):\n    name = event.tool_use[\"name\"]\n    inp = str(event.tool_use[\"input\"])\n    if name == \"save_report\" and \"[source]\" not in inp:\n        event.cancel_tool = \"Add source citations.\"\n\nagent = Agent(\n    tools=[save_report],\n    hooks=[require_sources],\n)\nagent(\"Research AI agent frameworks\")\npython\nfrom strands import Agent, tool\nfrom strands.hooks import BeforeToolCallEvent\nfrom pathlib import Path\n\n@tool\ndef save_report(title: str, content: str) -> str:\n    \"\"\"Save a research report to disk.\"\"\"\n    path = f\"reports/{title}.md\"\n    Path(path).write_text(content)\n    return f\"Saved {path}\"\n\ndef require_sources(event: BeforeToolCallEvent):\n    name = event.tool_use[\"name\"]\n    inp = str(event.tool_use[\"input\"])\n    if name == \"save_report\" and \"[source]\" not in inp:\n        event.cancel_tool = \"Add source citations.\"\n\nagent = Agent(\n    tools=[save_report],\n    hooks=[require_sources],\n)\nagent(\"Research AI agent frameworks\")\njs\nimport {\n  Agent, tool, BeforeToolCallEvent\n} from '@strands-agents/sdk'\nimport z from 'zod'\nimport { writeFileSync } from 'fs'\n\nconst saveReport = tool({\n  name: 'save_report',\n  description: 'Save a research report.',\n  inputSchema: z.object({\n    title: z.string(),\n    content: z.string(),\n  }),\n  callback: ({ title, content }) => {\n    writeFileSync(`reports/${title}.md`, content)\n    return `Saved ${title}.md`\n  },\n})\n\nconst agent = new Agent({ tools: [saveReport] })\n\nagent.addHook(BeforeToolCallEvent, (event) => {\n  const inp = String(event.toolUse.input)\n  if (event.toolUse.name === 'save_report') {\n    if (!inp.includes('[source]')) {\n      event.cancel = 'Add source citations.'\n    }\n  }\n})\n\nawait agent.invoke('Research AI agent frameworks')\njs\nimport {\n  Agent, tool, BeforeToolCallEvent\n} from '@strands-agents/sdk'\nimport z from 'zod'\nimport { writeFileSync } from 'fs'\n\nconst saveReport = tool({\n  name: 'save_report',\n  description: 'Save a research report.',\n  inputSchema: z.object({\n    title: z.string(),\n    content: z.string(),\n  }),\n  callback: ({ title, content }) => {\n    writeFileSync(`reports/${title}.md`, content)\n    return `Saved ${title}.md`\n  },\n})\n\nconst agent = new Agent({ tools: [saveReport] })\n\nagent.addHook(BeforeToolCallEvent, (event) => {\n  const inp = String(event.toolUse.input)\n  if (event.toolUse.name === 'save_report') {\n    if (!inp.includes('[source]')) {\n      event.cancel = 'Add source citations.'\n    }\n  }\n})\n\nawait agent.invoke('Research AI agent frameworks')\n```\n\nSet up with your coding agent\n\nRun in your terminal:\n\n```\nclaude mcp add strands uvx strands-agents-mcp-server\nclaude mcp add strands uvx strands-agents-mcp-server\n```\n\nAdd to ~/.cursor/mcp.json:\n\n```\n{\n  \"mcpServers\": {\n    \"strands-agents\": {\n      \"command\": \"uvx\",\n      \"args\": [\"strands-agents-mcp-server\"]\n    }\n  }\n}\n{\n  \"mcpServers\": {\n    \"strands-agents\": {\n      \"command\": \"uvx\",\n      \"args\": [\"strands-agents-mcp-server\"]\n    }\n  }\n}\n```\n\nAdd to ~/.kiro/settings/mcp.json:\n\n```\n{\n  \"mcpServers\": {\n    \"strands-agents\": {\n      \"command\": \"uvx\",\n      \"args\": [\"strands-agents-mcp-server\"],\n      \"disabled\": false,\n      \"autoApprove\": [\"search_docs\", \"fetch_doc\"]\n    }\n  }\n}\n{\n  \"mcpServers\": {\n    \"strands-agents\": {\n      \"command\": \"uvx\",\n      \"args\": [\"strands-agents-mcp-server\"],\n      \"disabled\": false,\n      \"autoApprove\": [\"search_docs\", \"fetch_doc\"]\n    }\n  }\n}\n```\n\nAdd to your mcp.json:\n\n```\n{\n  \"servers\": {\n    \"strands-agents\": {\n      \"command\": \"uvx\",\n      \"args\": [\"strands-agents-mcp-server\"]\n    }\n  }\n}\n{\n  \"servers\": {\n    \"strands-agents\": {\n      \"command\": \"uvx\",\n      \"args\": [\"strands-agents-mcp-server\"]\n    }\n  }\n}\n```\n\nOr paste this prompt:\n\n## Build your way\n\nAny model, any cloud. You get context management, execution limits, and observability before you write a line of config. Swap backends when you scale. Your code stays the same.\n\n``` python\nfrom strands import Agent, tool\n\n@tool\ndef search_logs(query: str, hours: int = 24) -> list:\n    \"\"\"Search application logs by keyword.\"\"\"\n    return log_api.search(query, hours)\n\nagent = Agent(\n    tools=[search_logs],\n)\n\nagent(\"Find all timeout errors from the last 6 hours\")\npython\nfrom strands import Agent, tool\n\n@tool\ndef search_logs(query: str, hours: int = 24) -> list:\n    \"\"\"Search application logs by keyword.\"\"\"\n    return log_api.search(query, hours)\n\nagent = Agent(\n    tools=[search_logs],\n)\n\nagent(\"Find all timeout errors from the last 6 hours\")\npython\nimport { Agent, tool } from '@strands-agents/sdk'\nimport z from 'zod'\n\nconst searchLogs = tool({\n  name: 'search_logs',\n  description: 'Search logs by keyword.',\n  inputSchema: z.object({\n    query: z.string(),\n    hours: z.number().default(24),\n  }),\n  callback: ({ query, hours }) =>\n    logApi.search(query, hours),\n})\n\nconst agent = new Agent({ tools: [searchLogs] })\n\nawait agent.invoke(\n  'Find all timeout errors from the last 6 hours'\n)\npython\nimport { Agent, tool } from '@strands-agents/sdk'\nimport z from 'zod'\n\nconst searchLogs = tool({\n  name: 'search_logs',\n  description: 'Search logs by keyword.',\n  inputSchema: z.object({\n    query: z.string(),\n    hours: z.number().default(24),\n  }),\n  callback: ({ query, hours }) =>\n    logApi.search(query, hours),\n})\n\nconst agent = new Agent({ tools: [searchLogs] })\n\nawait agent.invoke(\n  'Find all timeout errors from the last 6 hours'\n)\n```\n\nProgressive complexity. Zero lock-in.\n\n``` python\nfrom strands.agent import SummarizingConversationManager\n\n# Same agent, now with summarization.\nagent = Agent(\n    tools=[search_logs],\n    conversation_manager=SummarizingConversationManager(),\n)\npython\nfrom strands.agent import SummarizingConversationManager\n\n# Same agent, now with summarization.\nagent = Agent(\n    tools=[search_logs],\n    conversation_manager=SummarizingConversationManager(),\n)\njs\nimport {\n  SummarizingConversationManager,\n} from '@strands-agents/sdk'\n\n// Same agent, now with summarization.\nconst agent = new Agent({\n  tools: [searchLogs],\n  conversationManager:\n    new SummarizingConversationManager(),\n})\njs\nimport {\n  SummarizingConversationManager,\n} from '@strands-agents/sdk'\n\n// Same agent, now with summarization.\nconst agent = new Agent({\n  tools: [searchLogs],\n  conversationManager:\n    new SummarizingConversationManager(),\n})\n```\n\n## Stay in control\n\nMonitor, modify, and debug with hooks. The agent loop traces every decision by default. Hooks let you intercept any step to log it, validate it, or redirect it.\n\n``` python\nfrom strands import Agent\nfrom strands.hooks import AfterToolCallEvent\n\ndef log_tool_calls(event: AfterToolCallEvent):\n    \"\"\"Log every tool call.\"\"\"\n    print(f\"Tool: {event.tool_use['name']}\")\n    print(f\"Result: {event.result['status']}\")\n\nagent = Agent(\n    tools=[search_logs, query_database],\n    hooks=[log_tool_calls],\n    trace_attributes={\n        \"service\": \"ops-agent\",\n        \"env\": \"production\",\n    },\n)\npython\nfrom strands import Agent\nfrom strands.hooks import AfterToolCallEvent\n\ndef log_tool_calls(event: AfterToolCallEvent):\n    \"\"\"Log every tool call.\"\"\"\n    print(f\"Tool: {event.tool_use['name']}\")\n    print(f\"Result: {event.result['status']}\")\n\nagent = Agent(\n    tools=[search_logs, query_database],\n    hooks=[log_tool_calls],\n    trace_attributes={\n        \"service\": \"ops-agent\",\n        \"env\": \"production\",\n    },\n)\njs\nimport {\n  Agent, AfterToolCallEvent,\n} from '@strands-agents/sdk'\n\nconst agent = new Agent({\n  tools: [searchLogs, queryDatabase],\n  traceAttributes: {\n    service: 'ops-agent',\n    env: 'production',\n  },\n})\n\nagent.addHook(AfterToolCallEvent, (event) => {\n  console.log(`Tool: ${event.toolUse.name}`)\n  console.log(`Status: ${event.result.status}`)\n})\njs\nimport {\n  Agent, AfterToolCallEvent,\n} from '@strands-agents/sdk'\n\nconst agent = new Agent({\n  tools: [searchLogs, queryDatabase],\n  traceAttributes: {\n    service: 'ops-agent',\n    env: 'production',\n  },\n})\n\nagent.addHook(AfterToolCallEvent, (event) => {\n  console.log(`Tool: ${event.toolUse.name}`)\n  console.log(`Status: ${event.result.status}`)\n})\n```\n\nBuilt-in observability.\n\n## Deliver outcomes that work\n\nGuardrails catch mistakes before they run.\n\n``` python\nfrom strands import Agent\nfrom strands.hooks import BeforeToolCallEvent\n\nWRITE_OPS = [\"INSERT\", \"UPDATE\", \"DELETE\", \"DROP\"]\n\ndef read_only_guard(event: BeforeToolCallEvent):\n    \"\"\"Block writes. This agent is read-only.\"\"\"\n    if event.tool_use[\"name\"] == \"query_database\":\n        sql = event.tool_use[\"input\"].get(\"query\", \"\")\n        if any(kw in sql.upper() for kw in WRITE_OPS):\n            event.cancel_tool = \"Read-only access.\"\n\nagent = Agent(\n    tools=[query_database],\n    hooks=[read_only_guard],\n)\npython\nfrom strands import Agent\nfrom strands.hooks import BeforeToolCallEvent\n\nWRITE_OPS = [\"INSERT\", \"UPDATE\", \"DELETE\", \"DROP\"]\n\ndef read_only_guard(event: BeforeToolCallEvent):\n    \"\"\"Block writes. This agent is read-only.\"\"\"\n    if event.tool_use[\"name\"] == \"query_database\":\n        sql = event.tool_use[\"input\"].get(\"query\", \"\")\n        if any(kw in sql.upper() for kw in WRITE_OPS):\n            event.cancel_tool = \"Read-only access.\"\n\nagent = Agent(\n    tools=[query_database],\n    hooks=[read_only_guard],\n)\n```\n\nThen the harness gives specific feedback: \"add a WHERE clause,\" \"check permissions first.\" The agent corrects itself. You get reliable outcomes without micromanaging every step.\n\n```\nfrom strands.vended_plugins.steering import (\n    SteeringHandler, Guide, Proceed,\n)\n\nclass QueryQualityPolicy(SteeringHandler):\n    async def steer_before_tool(\n        self, *, agent, tool_use, **kwargs\n    ):\n        sql = tool_use[\"input\"].get(\"query\", \"\").upper()\n        if \"SELECT\" in sql and \"WHERE\" not in sql:\n            return Guide(\n                reason=\"Add a WHERE clause and LIMIT.\"\n            )\n        if sql.upper().count(\"JOIN\") > 3:\n            return Guide(\n                reason=\"4+ joins. Break into smaller queries.\"\n            )\n        return Proceed(reason=\"Query looks good.\")\n\nagent = Agent(\n    tools=[query_database],\n    plugins=[QueryQualityPolicy()],\n)\nfrom strands.vended_plugins.steering import (\n    SteeringHandler, Guide, Proceed,\n)\n\nclass QueryQualityPolicy(SteeringHandler):\n    async def steer_before_tool(\n        self, *, agent, tool_use, **kwargs\n    ):\n        sql = tool_use[\"input\"].get(\"query\", \"\").upper()\n        if \"SELECT\" in sql and \"WHERE\" not in sql:\n            return Guide(\n                reason=\"Add a WHERE clause and LIMIT.\"\n            )\n        if sql.upper().count(\"JOIN\") > 3:\n            return Guide(\n                reason=\"4+ joins. Break into smaller queries.\"\n            )\n        return Proceed(reason=\"Query looks good.\")\n\nagent = Agent(\n    tools=[query_database],\n    plugins=[QueryQualityPolicy()],\n)\n```\n\n**82.5%**.\n\nHard-coded workflows scored\n\n**80.8%**.\n\nAgents with Strands steering handlers recovered from every mistake.\n\n[See the benchmark →](/blog/steering-accuracy-beats-prompts-workflows/)\n\nAt Smartsheet, we chose Strands for our next generation of AI capabilities because it provided the perfect balance of enterprise-ready features and development efficiency. Its robust conversation memory and dynamic tool registration systems were crucial for creating a responsive, context-aware intelligent AI assistant. With Strands, we were able to quickly implement a secure and scalable solution, giving us a production-ready foundation to deliver a secure, high-performance, and enterprise-grade AI experience.\n\nTransform traditional error alerts into intelligent incident responses using Amazon Bedrock, RAG with Amazon OpenSearch, Multi-Agent Orchestration with Strands SDK, and Kiro AI IDE - reducing MTTR by 60% without manual coding.\n\nStrands’ SDK and great integration with AWS native services streamlined Landchecker’s development of agents. With easier integration of AgentCore Runtime, Bedrock Guardrails, and built-in support for OpenTelemetry, we could focus on what we do best – developing property information tools and data integrations.\n\nAt Swisscom, we need an agentic AI backbone that is both enterprise-ready and future-proof. Strands Agents gives us the best of both worlds: a native fit with our cloud environment, yet fully open source and flexible. That combination allowed us to build proof-of-concepts within just a few weeks and now sets us on the path to scale multi-agent systems with confidence, while keeping our focus on delivering real value to customers and the business.\n\nThe advisor is where things get interesting. We use the Strands Agents SDK to define an agent with a tool, a function the model can call during its reasoning loop.\n\nWe chose Strands because it’s AWS-native, intuitive, and made agent development accessible across our engineering team. Its abstraction layer and built-in multi-agent patterns (like Agent-as-Tool and Swarm) let us focus on remediation logic instead of infrastructure work. We’ve already built multiple agents, and wiring them together has been seamless. On top of that, we layered our\n\n[Agentic Remediation™]capability to automate vulnerability fixes and configuration validation/fault correction workflows, coordinating cross-agent remediation with precision\n\nScaling our global trading platform required reimagining our support capabilities, and Strands Agents was the key to making it happen at enterprise scale. What would traditionally take months of development, Strands allowed us to achieve in just 10 days - delivering a secure, robust, production-ready agentic solution. The results speak for themselves: investigation time dropped on average from 30 minutes to 45 seconds, investigation quality improved by 94%, and we saved $5M in operational costs. Strands didn’t just accelerate our development - it gave us the confidence to explore other agentic AI use cases across our entire business, including launching our Agentic Security Operations Center\n\nAdding bidirectional voice to my existing Strands agent was surprisingly straightforward. BidiAgent handles the WebSocket complexity and interruption logic, my @tool functions carried over unchanged, and the same code deploys to AgentCore without modification. Strands made real-time voice feel like a natural extension, not a separate project.\n\nWe see Strands as a great fit to power TeamForm’s next evolution of Agentic AI. Our customers need enterprise-grade security and scalability, which is exactly what Strands delivers. Its seamless integration with AWS and simplicity enables us to focus on innovating our AI capabilities and delivering value to our customers.\n\nFor Jit’s infrastructure drift detection agent, we leverage Strands Agents, an open-source framework developed by AWS for building production-ready AI agents. Strands Agents provides several advantages including simplified development, native AWS integration, and built-in security.\n\nAs someone who builds agents with LangGraph daily at work, Strands was a genuine surprise. The model-driven approach cut my setup from 40 lines to 3 — and for the 80% case, it just works without sacrificing flexibility.\n\nStrands Agents on Bedrock turns autonomous agents into an enterprise product: governed, observable, and safe by design. Together with Claude models, we analyze live webpages and generate code responsibly - helping customers reduce risk while accelerating delivery. Safety is non-negotiable in offensive security. On Amazon Bedrock, Strands Agents plus Claude let us scale autonomous pen-testing with Bedrock Guardrails - increasing coverage without increasing risk.\n\nThe combination of the Strands Agents SDK and Tavily represents a significant advancement in enterprise-grade research agent development. This integration can help organizations build sophisticated, secure, and scalable AI agents while maintaining the highest standards of security and performance. Learn more in this\n\n[blog].\n\nStrands was used to build a growing set of agents that run a company to do actual tasks.\n\nAt Smartsheet, we chose Strands for our next generation of AI capabilities because it provided the perfect balance of enterprise-ready features and development efficiency. Its robust conversation memory and dynamic tool registration systems were crucial for creating a responsive, context-aware intelligent AI assistant. With Strands, we were able to quickly implement a secure and scalable solution, giving us a production-ready foundation to deliver a secure, high-performance, and enterprise-grade AI experience.\n\nTransform traditional error alerts into intelligent incident responses using Amazon Bedrock, RAG with Amazon OpenSearch, Multi-Agent Orchestration with Strands SDK, and Kiro AI IDE - reducing MTTR by 60% without manual coding.\n\nStrands’ SDK and great integration with AWS native services streamlined Landchecker’s development of agents. With easier integration of AgentCore Runtime, Bedrock Guardrails, and built-in support for OpenTelemetry, we could focus on what we do best – developing property information tools and data integrations.\n\nAt Swisscom, we need an agentic AI backbone that is both enterprise-ready and future-proof. Strands Agents gives us the best of both worlds: a native fit with our cloud environment, yet fully open source and flexible. That combination allowed us to build proof-of-concepts within just a few weeks and now sets us on the path to scale multi-agent systems with confidence, while keeping our focus on delivering real value to customers and the business.\n\nThe advisor is where things get interesting. We use the Strands Agents SDK to define an agent with a tool, a function the model can call during its reasoning loop.\n\nWe chose Strands because it’s AWS-native, intuitive, and made agent development accessible across our engineering team. Its abstraction layer and built-in multi-agent patterns (like Agent-as-Tool and Swarm) let us focus on remediation logic instead of infrastructure work. We’ve already built multiple agents, and wiring them together has been seamless. On top of that, we layered our\n\n[Agentic Remediation™]capability to automate vulnerability fixes and configuration validation/fault correction workflows, coordinating cross-agent remediation with precision\n\nScaling our global trading platform required reimagining our support capabilities, and Strands Agents was the key to making it happen at enterprise scale. What would traditionally take months of development, Strands allowed us to achieve in just 10 days - delivering a secure, robust, production-ready agentic solution. The results speak for themselves: investigation time dropped on average from 30 minutes to 45 seconds, investigation quality improved by 94%, and we saved $5M in operational costs. Strands didn’t just accelerate our development - it gave us the confidence to explore other agentic AI use cases across our entire business, including launching our Agentic Security Operations Center\n\nAdding bidirectional voice to my existing Strands agent was surprisingly straightforward. BidiAgent handles the WebSocket complexity and interruption logic, my @tool functions carried over unchanged, and the same code deploys to AgentCore without modification. Strands made real-time voice feel like a natural extension, not a separate project.\n\nWe see Strands as a great fit to power TeamForm’s next evolution of Agentic AI. Our customers need enterprise-grade security and scalability, which is exactly what Strands delivers. Its seamless integration with AWS and simplicity enables us to focus on innovating our AI capabilities and delivering value to our customers.\n\nFor Jit’s infrastructure drift detection agent, we leverage Strands Agents, an open-source framework developed by AWS for building production-ready AI agents. Strands Agents provides several advantages including simplified development, native AWS integration, and built-in security.\n\nAs someone who builds agents with LangGraph daily at work, Strands was a genuine surprise. The model-driven approach cut my setup from 40 lines to 3 — and for the 80% case, it just works without sacrificing flexibility.\n\nStrands Agents on Bedrock turns autonomous agents into an enterprise product: governed, observable, and safe by design. Together with Claude models, we analyze live webpages and generate code responsibly - helping customers reduce risk while accelerating delivery. Safety is non-negotiable in offensive security. On Amazon Bedrock, Strands Agents plus Claude let us scale autonomous pen-testing with Bedrock Guardrails - increasing coverage without increasing risk.\n\nThe combination of the Strands Agents SDK and Tavily represents a significant advancement in enterprise-grade research agent development. This integration can help organizations build sophisticated, secure, and scalable AI agents while maintaining the highest standards of security and performance. Learn more in this\n\n[blog].\n\nStrands was used to build a growing set of agents that run a company to do actual tasks.\n\n### Automate workflows\n\nClassify, score, and route. One agent, one job. Replace brittle scripts with tools that adapt when your process changes.\n\n``` python\nfrom strands import Agent, tool\n\n@tool\ndef classify_lead(email: str, company: str) -> dict:\n    \"\"\"Score and classify an inbound lead.\"\"\"\n    firmographics = crm.lookup(company)\n    return {\n        \"score\": compute_icp_score(firmographics),\n        \"segment\": firmographics[\"industry\"],\n    }\n\n@tool\ndef route_to_rep(lead_id: str, region: str) -> str:\n    \"\"\"Assign a lead to the right sales rep.\"\"\"\n    rep = crm.get_rep_for_region(region)\n    crm.assign(lead_id, rep)\n    return f\"Assigned to {rep}\"\n\nagent = Agent(\n    tools=[classify_lead, route_to_rep],\n)\n\nagent(\"New lead: jane@acme.com, Acme Corp, US-West\")\npython\nfrom strands import Agent, tool\n\n@tool\ndef classify_lead(email: str, company: str) -> dict:\n    \"\"\"Score and classify an inbound lead.\"\"\"\n    firmographics = crm.lookup(company)\n    return {\n        \"score\": compute_icp_score(firmographics),\n        \"segment\": firmographics[\"industry\"],\n    }\n\n@tool\ndef route_to_rep(lead_id: str, region: str) -> str:\n    \"\"\"Assign a lead to the right sales rep.\"\"\"\n    rep = crm.get_rep_for_region(region)\n    crm.assign(lead_id, rep)\n    return f\"Assigned to {rep}\"\n\nagent = Agent(\n    tools=[classify_lead, route_to_rep],\n)\n\nagent(\"New lead: jane@acme.com, Acme Corp, US-West\")\npython\nimport { Agent, tool } from '@strands-agents/sdk'\nimport z from 'zod'\n\nconst classifyLead = tool({\n  name: 'classify_lead',\n  description: 'Score and classify a lead.',\n  inputSchema: z.object({\n    email: z.string(),\n    company: z.string(),\n  }),\n  callback: ({ email, company }) => {\n    const data = crm.lookup(company)\n    return {\n      score: computeIcpScore(data),\n      segment: data.industry,\n    }\n  },\n})\n\nconst routeToRep = tool({\n  name: 'route_to_rep',\n  description: 'Assign a lead to a rep.',\n  inputSchema: z.object({\n    leadId: z.string(),\n    region: z.string(),\n  }),\n  callback: ({ leadId, region }) => {\n    const rep = crm.getRepForRegion(region)\n    crm.assign(leadId, rep)\n    return `Assigned to ${rep}`\n  },\n})\n\nconst agent = new Agent({\n  tools: [classifyLead, routeToRep],\n})\n\nawait agent.invoke(\n  'New lead: jane@acme.com, Acme Corp, US-West'\n)\npython\nimport { Agent, tool } from '@strands-agents/sdk'\nimport z from 'zod'\n\nconst classifyLead = tool({\n  name: 'classify_lead',\n  description: 'Score and classify a lead.',\n  inputSchema: z.object({\n    email: z.string(),\n    company: z.string(),\n  }),\n  callback: ({ email, company }) => {\n    const data = crm.lookup(company)\n    return {\n      score: computeIcpScore(data),\n      segment: data.industry,\n    }\n  },\n})\n\nconst routeToRep = tool({\n  name: 'route_to_rep',\n  description: 'Assign a lead to a rep.',\n  inputSchema: z.object({\n    leadId: z.string(),\n    region: z.string(),\n  }),\n  callback: ({ leadId, region }) => {\n    const rep = crm.getRepForRegion(region)\n    crm.assign(leadId, rep)\n    return `Assigned to ${rep}`\n  },\n})\n\nconst agent = new Agent({\n  tools: [classifyLead, routeToRep],\n})\n\nawait agent.invoke(\n  'New lead: jane@acme.com, Acme Corp, US-West'\n)\n```\n\n### Build AI assistants\n\nGround agents in your knowledge base via MCP. Context management keeps long conversations in bounds. Interrupts pause for human approval before sensitive actions.\n\n``` python\nfrom strands import Agent, tool\nfrom strands.tools.mcp import MCPClient\nfrom strands.hooks import BeforeToolCallEvent\nfrom strands.agent import SlidingWindowConversationManager\nfrom mcp import stdio_client, StdioServerParameters\n\nkb = MCPClient(lambda: stdio_client(\n    StdioServerParameters(command=\"uvx\", args=[\"kb-server\"])\n))\n\n@tool\ndef issue_refund(order_id: str, amount: float) -> str:\n    \"\"\"Process a customer refund.\"\"\"\n    return payments.refund(order_id, amount)\n\ndef approve_refunds(event: BeforeToolCallEvent):\n    \"\"\"Pause for human approval before processing refunds.\"\"\"\n    if event.tool_use[\"name\"] == \"issue_refund\":\n        response = event.interrupt(\n            \"refund_approval\", reason=event.tool_use[\"input\"]\n        )\n        if response != \"APPROVE\":\n            event.cancel_tool = \"Refund not approved.\"\n\nagent = Agent(\n    system_prompt=\"Support assistant. Use the KB. \"\n    \"Refunds require approval.\",\n    tools=[kb, issue_refund],\n    hooks=[approve_refunds],\n    conversation_manager=SlidingWindowConversationManager(\n        window_size=20\n    ),\n)\npython\nfrom strands import Agent, tool\nfrom strands.tools.mcp import MCPClient\nfrom strands.hooks import BeforeToolCallEvent\nfrom strands.agent import SlidingWindowConversationManager\nfrom mcp import stdio_client, StdioServerParameters\n\nkb = MCPClient(lambda: stdio_client(\n    StdioServerParameters(command=\"uvx\", args=[\"kb-server\"])\n))\n\n@tool\ndef issue_refund(order_id: str, amount: float) -> str:\n    \"\"\"Process a customer refund.\"\"\"\n    return payments.refund(order_id, amount)\n\ndef approve_refunds(event: BeforeToolCallEvent):\n    \"\"\"Pause for human approval before processing refunds.\"\"\"\n    if event.tool_use[\"name\"] == \"issue_refund\":\n        response = event.interrupt(\n            \"refund_approval\", reason=event.tool_use[\"input\"]\n        )\n        if response != \"APPROVE\":\n            event.cancel_tool = \"Refund not approved.\"\n\nagent = Agent(\n    system_prompt=\"Support assistant. Use the KB. \"\n    \"Refunds require approval.\",\n    tools=[kb, issue_refund],\n    hooks=[approve_refunds],\n    conversation_manager=SlidingWindowConversationManager(\n        window_size=20\n    ),\n)\njs\nimport {\n  Agent, tool, McpClient,\n  BeforeToolCallEvent,\n  SlidingWindowConversationManager,\n} from '@strands-agents/sdk'\nimport { StdioClientTransport } from\n  '@modelcontextprotocol/sdk/client/stdio.js'\nimport z from 'zod'\n\nconst kb = new McpClient({\n  transport: new StdioClientTransport({\n    command: 'npx',\n    args: ['kb-server'],\n  }),\n})\n\nconst issueRefund = tool({\n  name: 'issue_refund',\n  description: 'Process a refund.',\n  inputSchema: z.object({\n    orderId: z.string(),\n    amount: z.number(),\n  }),\n  callback: ({ orderId, amount }) =>\n    payments.refund(orderId, amount),\n})\n\nconst agent = new Agent({\n  systemPrompt: 'Support assistant. '\n    + 'Use KB. Refunds require approval.',\n  tools: [kb, issueRefund],\n  conversationManager:\n    new SlidingWindowConversationManager({\n      windowSize: 20,\n    }),\n})\n\n// Cancel refunds (interrupt coming soon to TS)\nagent.addHook(BeforeToolCallEvent, (event) => {\n  if (event.toolUse.name === 'issue_refund') {\n    event.cancel = 'Refund approval required.'\n  }\n})\njs\nimport {\n  Agent, tool, McpClient,\n  BeforeToolCallEvent,\n  SlidingWindowConversationManager,\n} from '@strands-agents/sdk'\nimport { StdioClientTransport } from\n  '@modelcontextprotocol/sdk/client/stdio.js'\nimport z from 'zod'\n\nconst kb = new McpClient({\n  transport: new StdioClientTransport({\n    command: 'npx',\n    args: ['kb-server'],\n  }),\n})\n\nconst issueRefund = tool({\n  name: 'issue_refund',\n  description: 'Process a refund.',\n  inputSchema: z.object({\n    orderId: z.string(),\n    amount: z.number(),\n  }),\n  callback: ({ orderId, amount }) =>\n    payments.refund(orderId, amount),\n})\n\nconst agent = new Agent({\n  systemPrompt: 'Support assistant. '\n    + 'Use KB. Refunds require approval.',\n  tools: [kb, issueRefund],\n  conversationManager:\n    new SlidingWindowConversationManager({\n      windowSize: 20,\n    }),\n})\n\n// Cancel refunds (interrupt coming soon to TS)\nagent.addHook(BeforeToolCallEvent, (event) => {\n  if (event.toolUse.name === 'issue_refund') {\n    event.cancel = 'Refund approval required.'\n  }\n})\n```\n\n### Build research agents\n\nWake up to a briefing instead of a to-do list. Structured output keeps results typed and predictable.\n\n``` python\nfrom pydantic import BaseModel, Field\nfrom strands import Agent\nfrom strands_tools import http_request\nfrom pathlib import Path\n\nclass Briefing(BaseModel):\n    headline: str = Field(description=\"One-line summary\")\n    developments: list[str] = Field(\n        description=\"Key developments\"\n    )\n    sources: list[str] = Field(\n        description=\"URLs consulted\"\n    )\n\nagent = Agent(\n    system_prompt=\"Research assistant. Search the web, \"\n    \"find developments from the last 24 hours, \"\n    \"and produce a briefing with citations.\",\n    tools=[http_request],\n)\n\nresult = agent(\n    \"What happened in AI agent frameworks yesterday?\",\n    structured_output_model=Briefing,\n)\n\nbriefing = result.structured_output\nPath(\"briefings/daily.md\").write_text(\n    f\"# {briefing.headline}\\n\\n\"\n    + \"\\n\".join(f\"- {d}\" for d in briefing.developments)\n)\npython\nfrom pydantic import BaseModel, Field\nfrom strands import Agent\nfrom strands_tools import http_request\nfrom pathlib import Path\n\nclass Briefing(BaseModel):\n    headline: str = Field(description=\"One-line summary\")\n    developments: list[str] = Field(\n        description=\"Key developments\"\n    )\n    sources: list[str] = Field(\n        description=\"URLs consulted\"\n    )\n\nagent = Agent(\n    system_prompt=\"Research assistant. Search the web, \"\n    \"find developments from the last 24 hours, \"\n    \"and produce a briefing with citations.\",\n    tools=[http_request],\n)\n\nresult = agent(\n    \"What happened in AI agent frameworks yesterday?\",\n    structured_output_model=Briefing,\n)\n\nbriefing = result.structured_output\nPath(\"briefings/daily.md\").write_text(\n    f\"# {briefing.headline}\\n\\n\"\n    + \"\\n\".join(f\"- {d}\" for d in briefing.developments)\n)\njs\nimport { Agent } from '@strands-agents/sdk'\nimport { httpRequest } from '@strands-agents/tools'\nimport z from 'zod'\nimport { writeFileSync } from 'fs'\n\nconst BriefingSchema = z.object({\n  headline: z.string().describe('Summary'),\n  developments: z.array(z.string())\n    .describe('Key developments'),\n  sources: z.array(z.string())\n    .describe('URLs consulted'),\n})\n\nconst agent = new Agent({\n  systemPrompt: 'Research assistant. '\n    + 'Search the web. Cite sources.',\n  tools: [httpRequest],\n})\n\nconst result = await agent.invoke(\n  'AI agent frameworks: what happened yesterday?',\n  { structuredOutputSchema: BriefingSchema },\n)\n\nconst briefing = result.structuredOutput\nwriteFileSync('briefings/daily.md',\n  `# ${briefing.headline}\\n\\n`\n  + briefing.developments\n    .map((d: string) => `- ${d}`)\n    .join('\\n')\n)\njs\nimport { Agent } from '@strands-agents/sdk'\nimport { httpRequest } from '@strands-agents/tools'\nimport z from 'zod'\nimport { writeFileSync } from 'fs'\n\nconst BriefingSchema = z.object({\n  headline: z.string().describe('Summary'),\n  developments: z.array(z.string())\n    .describe('Key developments'),\n  sources: z.array(z.string())\n    .describe('URLs consulted'),\n})\n\nconst agent = new Agent({\n  systemPrompt: 'Research assistant. '\n    + 'Search the web. Cite sources.',\n  tools: [httpRequest],\n})\n\nconst result = await agent.invoke(\n  'AI agent frameworks: what happened yesterday?',\n  { structuredOutputSchema: BriefingSchema },\n)\n\nconst briefing = result.structuredOutput\nwriteFileSync('briefings/daily.md',\n  `# ${briefing.headline}\\n\\n`\n  + briefing.developments\n    .map((d: string) => `- ${d}`)\n    .join('\\n')\n)\n```\n\n", "url": "https://wpnews.pro/news/has-any-one-ever-used-strands-the-ai-agent-sdk-by-aws", "canonical_source": "https://strandsagents.com/", "published_at": "2026-08-18 20:20:40+00:00", "updated_at": "2026-08-18 20:41:03.803672+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-tools", "ai-infrastructure"], "entities": ["AWS", "Strands", "Claude", "Cursor", "Kiro"], "alternates": {"html": "https://wpnews.pro/news/has-any-one-ever-used-strands-the-ai-agent-sdk-by-aws", "markdown": "https://wpnews.pro/news/has-any-one-ever-used-strands-the-ai-agent-sdk-by-aws.md", "text": "https://wpnews.pro/news/has-any-one-ever-used-strands-the-ai-agent-sdk-by-aws.txt", "jsonld": "https://wpnews.pro/news/has-any-one-ever-used-strands-the-ai-agent-sdk-by-aws.jsonld"}}