Strands Agents: el SDK de agentes de AWS
Strands Agents es el SDK de código abierto de AWS para construir y ejecutar agentes de IA en Python y TypeScript. Amazon lo usa en producción. Sigue un enfoque model-driven: le das al modelo un prompt y herramientas y el propio modelo planifica los pasos, en lugar de codificar cada decisión en un grafo.
Corre dentro de tu proceso, sin plano de control alojado. Su propuesta: úsalo cuando, de otro modo, escribirías tu propio agent loop — ya trae límites de turnos, presupuesto de tokens, cancelación, trazas y hooks.
Piezas del proyecto
Sección titulada «Piezas del proyecto»El monorepo strands-agents/harness-sdk agrupa:
| Pieza | Paquete | Qué es |
|---|---|---|
| Strands harness (Python) | strands-harness | Agente ya montado con create_harness() |
| Strands harness (TS) | @strands-agents/harness | Lo mismo con createHarness() |
| CLI | @strands-agents/cli | Prototipar y chatear con un agente harness desde la terminal |
| SDK de Python | strands-agents | Agent loop, proveedores de modelos, herramientas |
| SDK de TypeScript | @strands-agents/sdk | Lo mismo para Node.js y navegador |
| Herramientas | strands-agents-tools | Herramientas listas (calculadora, HTTP, archivos…) |
| Documentación | site/ | El sitio strandsagents.com (Astro/Starlight) |
Dos niveles: harness o SDK
Sección titulada «Dos niveles: harness o SDK»Harness: un agente completo y optimizado en una línea. Es el camino recomendado para empezar.
pip install strands-harnessfrom strands_harness import create_harness
agent = create_harness()agent("Find the slowest test in this repo and explain why it's slow")pnpm add @strands-agents/harnessbun add @strands-agents/harnessnpm install @strands-agents/harnessimport { createHarness } from "@strands-agents/harness"
const agent = await createHarness()await agent.invoke("Find the slowest test in this repo and explain why it's slow")SDK: cuando quieres controlar el loop, las herramientas, el proveedor, la memoria y los hooks.
pip install strands-agents strands-agents-toolsfrom strands import Agentfrom strands_tools import calculator
agent = Agent(tools=[calculator])agent("What is the square root of 1764")pnpm add @strands-agents/sdkbun add @strands-agents/sdknpm install @strands-agents/sdkimport { Agent } from "@strands-agents/sdk"
const agent = new Agent()const result = await agent.invoke("What is the square root of 1764?")console.log(result)El proveedor por defecto es Amazon Bedrock: necesita credenciales de AWS y acceso habilitado al modelo en tu región. Para otro proveedor, pásale un model.
El agent loop
Sección titulada «El agent loop»Cada invocación repite el mismo ciclo hasta que el modelo responde sin pedir herramientas o se alcanza un límite:
prompt + historial + herramientas → modelo └─ ¿pide una herramienta? → ejecutarla → añadir el resultado → volver al modelo └─ ¿respuesta final? → devolver AgentResultEl loop registra cada decisión por defecto (trazas OpenTelemetry, métricas de tokens, latencia y ciclos) y expone hooks en cada paso.
Proveedores de modelos
Sección titulada «Proveedores de modelos»Soporte de primera clase para Amazon Bedrock, Anthropic, OpenAI y Gemini, y además Cohere, LiteLLM, llama.cpp, LlamaAPI, Mistral, Ollama, OpenAI Responses API, SageMaker, Writer y proveedores propios.
from strands import Agentfrom strands.models import BedrockModelfrom strands.models.ollama import OllamaModel
bedrock = BedrockModel(model_id="us.amazon.nova-pro-v1:0", temperature=0.3, streaming=True)local = OllamaModel(host="http://localhost:11434", model_id="llama3")
agent = Agent(model=local)import { Agent } from "@strands-agents/sdk"import { OpenAIModel } from "@strands-agents/sdk/models/openai"
// Lee OPENAI_API_KEY del entornoconst agent = new Agent({ model: new OpenAIModel({ api: "chat" }) })Herramientas
Sección titulada «Herramientas»En Python, un decorador; el docstring es lo que el modelo lee para decidir cuándo usarla:
from strands import Agent, tool
@tooldef word_count(text: str) -> int: """Count words in text.""" return len(text.split())
agent = Agent(tools=[word_count])Agent(load_tools_from_directory=True) vigila ./tools/ y recarga en caliente.
En TypeScript, con esquemas de Zod que tipan la entrada:
import { Agent, tool } from "@strands-agents/sdk"import { z } from "zod"
const weather = tool({ name: "get_weather", description: "Get the current weather for a specific location.", inputSchema: z.object({ location: z.string() }), callback: (input) => `The weather in ${input.location} is 72°F and sunny.`})
const agent = new Agent({ tools: [weather] })Salida estructurada
Sección titulada «Salida estructurada»const Person = z.object({ name: z.string(), age: z.number() })const agent = new Agent({ structuredOutputSchema: Person })const result = await agent.invoke("John Smith is a 30 year-old software engineer")result.structuredOutput.age // 30Si el modelo devuelve algo inválido, el agente reintenta con el error de validación; si al final falla, lanza StructuredOutputError.
MCP nativo
Sección titulada «MCP nativo»Un servidor MCP se conecta como fuente de herramientas:
from strands import Agentfrom strands.tools.mcp import MCPClientfrom mcp import stdio_client, StdioServerParameters
docs = MCPClient(lambda: stdio_client( StdioServerParameters(command="uvx", args=["awslabs.aws-documentation-mcp-server@latest"])))
with docs: agent = Agent(tools=docs.list_tools_sync()) agent("Tell me about Amazon Bedrock")En TypeScript, new McpClient({ transport }) se pasa directamente en tools. El SDK de Python funciona con las versiones 1.x y 2.x del paquete mcp.
Un hook event marca un punto del ciclo de vida; un callback se registra para ese evento y recibe un objeto tipado. Sirven para logging, validación, guardrails y métricas.
from strands import Agentfrom strands.hooks import BeforeToolCallEvent
def log_tool(event: BeforeToolCallEvent) -> None: print(f"Tool called: {event.tool_use['name']}")
agent = Agent()agent.add_hook(log_tool) # el tipo del evento se infiere del type hintLos orquestadores multiagente emiten sus propios eventos (BeforeNodeCallEvent, AfterNodeCallEvent). Varios hooks relacionados se empaquetan como plugins.
Estado, sesiones y memoria
Sección titulada «Estado, sesiones y memoria»| Concepto | Para qué |
|---|---|
| Estado del agente | Historial, estado clave-valor y estado por invocación |
| Snapshots | Guardar y restaurar el agente en un punto: checkpoints, deshacer, ramas de conversación |
| Sesiones | Persistir la conversación entre reinicios con un session_id |
| Memoria a largo plazo | Hechos destilados que se recuperan entre sesiones, con backend configurable |
| Gestión de contexto | Ventana deslizante o resumen cuando la conversación crece |
from strands import Agentfrom strands.session import FileSessionManager
session = FileSessionManager(session_id="user-123", storage_dir="./sessions")agent = Agent(session_manager=session)En Python, SnapshotSessionManager es el recomendado para sesiones nuevas; FileSessionManager (disco local) y S3SessionManager (Amazon S3) siguen soportados como ruta de compatibilidad.
Multiagente
Sección titulada «Multiagente»| Patrón | Idea | Ciclos |
|---|---|---|
| Agents as tools | Un orquestador llama a agentes especialistas como si fueran herramientas | — |
| Graph | Tú defines nodos y aristas; el flujo es controlado pero puede ramificar según el resultado | Sí |
| Swarm | Un equipo de agentes se pasa la tarea de forma autónoma con memoria compartida | Sí |
| Workflow | Un DAG de tareas predefinidas con dependencias, ejecutadas en orden | No |
import { Agent, Graph } from "@strands-agents/sdk"
const researcher = new Agent({ id: "researcher", systemPrompt: "Research the topic." })const writer = new Agent({ id: "writer", systemPrompt: "Write the article." })
const graph = new Graph({ nodes: [researcher, writer], edges: [["researcher", "writer"]] })Graph y Swarm aceptan interrupciones para aprobación humana y comparten estado por invocación.
Agent2Agent (A2A)
Sección titulada «Agent2Agent (A2A)»El protocolo abierto A2A permite que un agente de Strands llame a agentes de otras plataformas y al revés.
pip install 'strands-agents[a2a]'npm install @strands-agents/sdk @a2a-js/sdk expressfrom strands.agent.a2a_agent import A2AAgent
remote = A2AAgent(endpoint="http://localhost:9000")result = remote("Show me 10 ^ 6")Para exponer tu agente: A2AServer(agent_factory=...) en Python o A2AExpressServer en TypeScript. La fábrica crea un agente nuevo por contexto para que los llamantes queden aislados.
Streaming bidireccional (experimental)
Sección titulada «Streaming bidireccional (experimental)»Conversaciones de voz en tiempo real con interrupciones, sobre Amazon Nova Sonic, Gemini Live y OpenAI Realtime:
pip install "strands-agents[bidi]" # solo servidorpip install "strands-agents[bidi-all]" # todos los proveedores y E/S de terminalLa API puede cambiar entre versiones.
Producción
Sección titulada «Producción»La documentación incluye guías para desplegar en Amazon Bedrock AgentCore Runtime (serverless y aislado por sesión), Lambda, Fargate, App Runner, EKS, EC2, Docker, Kubernetes y Terraform, además de observabilidad con OpenTelemetry, guardrails, human-in-the-loop y prácticas de IA responsable.
Antes de producción:
- fija límites de turnos, tokens y tiempo por invocación;
- da a cada herramienta los permisos mínimos y valida sus argumentos;
- pide aprobación humana antes de acciones irreversibles;
- guarda trazas con el modelo y las herramientas usadas;
- aísla los agentes remotos (A2A) como cualquier servicio externo.
Cuándo elegirlo
Sección titulada «Cuándo elegirlo»- Quieres un agente en tu propio proceso, sin plataforma alojada, y cambiar de proveedor sin reescribir.
- Ya estás en AWS (Bedrock, AgentCore, Lambda) y quieres el camino con mejor integración.
- Necesitas multiagente o A2A sin montar la orquestación a mano.
Si tu app es sobre todo un chat en una web con React, el AI SDK de Vercel encaja mejor en el frontend.