Introducción a Strands Agents: de responder a actuar
Un modelo de lenguaje puede responder preguntas, pero no puede hacer cosas. Esa distinción parece menor hasta que intentas que un LLM te dé el clima actual, ejecute una función o decida por sí mismo qué herramienta necesita para resolver una tarea. Ahí entra en juego el concepto de agente. En este capítulo fijamos la base teórica que usaremos en el resto del libro: qué es un agente, de qué se compone, por qué Strands Agents adopta un enfoque model-driven y qué aspecto tiene todo esto en Python.
Un modelo no es un agente
Un LLM puro —ChatGPT, Claude, Gemini, etc.— es como una persona brillante encerrada en una habitación. Puede razonar, recordar hechos, redactar, programar y argumentar. Lo que no puede hacer es consultar el dato de hoy, leer tus archivos, ejecutar código ni actuar sobre el mundo exterior. Está limitado a lo que aprendió durante su entrenamiento y a lo que tú le escribas en el prompt.
Un agente, en cambio, es esa misma inteligencia con puertas hacia el exterior. Puede:
- Consultar una API para conocer el clima o la tasa de cambio del dólar.
- Leer un documento, una base de datos o un bucket de S3.
- Ejecutar una función de Python, generar una imagen o enviar un mensaje.
- Decidir qué herramienta usar según el contexto de la conversación.
La inteligencia es la misma; lo que cambia es la capacidad de actuar. El mecanismo que hace esto posible es el agent loop, que veremos en detalle más adelante.
Resumen rápido: un LLM responde, un agente actúa.
Los tres ingredientes de un agente
Un agente no es magia. Es un programa que, dado un objetivo, decide y ejecuta los pasos necesarios para cumplirlo. Esa capacidad surge de combinar tres piezas: el modelo, las herramientas y el system prompt. Cada una tendrá su propio capítulo más adelante; por ahora, veamos su papel.
El modelo: el cerebro
Es el que razona, planifica y decide. En Strands Agents, el modelo es además el orquestador: tú no escribes un flujo rígido paso a paso; le das un objetivo, unas herramientas y unas reglas, y él decide cómo avanzar. Strands permite usar distintos modelos de Amazon Bedrock —Claude, Llama, etc.— siempre que soporten tool use y streaming.
Las herramientas: las manos
Una herramienta es cualquier función que el modelo puede invocar durante su razonamiento para obtener información o producir efectos en el mundo real: recuperar datos de una base de datos vectorial, calcular un valor complejo, generar una imagen, llamar a una API externa… Cualquier acción que amplíe lo que el LLM puede hacer por sí solo.
Un matiz importante: el modelo nunca ejecuta la herramienta directamente. La solicita, y es el servidor que ejecuta el agente quien la corre y le devuelve el resultado para que continúe razonando.
El system prompt: la personalidad
Es distinto del prompt que escribe el usuario. El prompt de usuario es la pregunta concreta del momento; el system prompt define el rol del agente: su objetivo, su tono, qué sabe y qué no debe hacer. Es el equivalente a decirle al modelo: “Compórtate como un experto en finanzas con 3 años de experiencia.”
Ejemplo: Si no lo defines, Strands con Amazon Bedrock usa Claude por defecto. Ante "¿cuántas r hay en strawberry?", el modelo verifica sus herramientas y decide llamar a contar_letras.
Workflow-driven vs model-driven
Los primeros frameworks de agentes —LangGraph, AutoGen, CrewAI, LlamaIndex— eran principalmente workflow-driven. El desarrollador construía explícitamente la orquestación: máquinas de estados, grafos de decisión, flujos paso a paso. El ingeniero tenía que anticipar cada camino posible y codificarlo.
El problema de ese enfoque es la fragilidad. Si la conversación se sale del guion, el agente falla porque no hay rama programada para ese caso. El control vive en el código del flujo.
El enfoque model-driven —el que sigue Strands Agents— desplaza ese control. En lugar de intentar predecir cada escenario, deja que el modelo de lenguaje dirija su propio comportamiento. Tú le das las herramientas, el contexto y los objetivos; el modelo decide sobre la marcha cuándo usar cada herramienta y cómo recuperarse de errores o imprevistos.
| Enfoque | Orquestador | Ventaja principal | Riesgo principal |
|---|---|---|---|
| Workflow-driven | El desarrollador | Control explícito, flujo predecible | Frágil ante casos no previstos |
| Model-driven | El modelo | Adaptación dinámica, menos código | Requiere evaluación más rigurosa |
Usar un modelo como orquestador no significa renunciar al control. El control se desplaza: pasas de microgestionar cada rama a definir piezas, límites y observar el comportamiento. Strands Agents ofrece una interfaz sencilla para empezar, pero también configuraciones más potentes para producción: límites de ejecución, gestión de contexto, guardrails y observabilidad.
Clave: en el model-driven, el control no desaparece; se desplaza del flujo explícito a las reglas, las herramientas y la evaluación.
El agent loop paso a paso
El agente funciona en un bucle casi mecánico:
- El usuario envía una solicitud.
- El modelo razona y decide que necesita ejecutar una herramienta.
- El servidor que levantó la tarea ejecuta la herramienta y devuelve el resultado al modelo.
- Con el resultado ya en su contexto, el modelo decide si necesita otra herramienta o si puede responder.
- El bucle se repite hasta que el modelo considera que tiene todo lo necesario para dar la respuesta final.
Puedes recorrer el ciclo completo con un caso concreto de dos iteraciones:
La fuerza de este bucle está en la acumulación de contexto. En cada iteración, el modelo no solo ve la pregunta original, sino también cada herramienta que ha llamado y cada resultado que ha recibido. Esa memoria acumulada es lo que permite el razonamiento multipaso: el modelo construye su comprensión de la tarea iteración a iteración, y en cada vuelta decide de forma autónoma si actuar o si terminar.
Primer ejemplo en Python
El ejemplo más pequeño que ilustra estas tres piezas es un agente con tres herramientas: calculadora, fecha actual y conteo de letras. El objetivo es responder a una pregunta como “¿Cuántas ‘r’ hay en la palabra strawberry?”. El agente decide cuándo usar cada herramienta sin que tú le indiques el flujo.
import datetime
from strands import Agent, tool
@tool
def calculadora(a: float, b: float) -> float:
"""Calcula la suma de dos números."""
return a + b
@tool
def fecha_actual() -> str:
"""Devuelve la fecha actual del sistema."""
return datetime.date.today().isoformat()
@tool
def contar_letras(palabra: str, letra: str) -> int:
"""Cuenta cuántas veces aparece una letra en una palabra."""
return palabra.lower().count(letra.lower())
agente = Agent(
tools=[calculadora, fecha_actual, contar_letras],
system_prompt="""
Eres un asistente útil. Antes de responder, decide si necesitas
alguna de tus herramientas para obtener datos o realizar cálculos.
"""
)
respuesta = agente("¿Cuántas 'r' hay en la palabra strawberry?")
print(respuesta)
Fíjate en que los docstrings no son decorativos: son la descripción que el modelo lee para decidir cuándo usar cada herramienta. Lo que ocurre bajo la superficie es puramente model-driven:
- El agente recibe la pregunta.
- El modelo verifica qué herramientas tiene disponibles y decide usar
contar_letras. - El servidor ejecuta
contar_letras("strawberry", "r")y devuelve el resultado al modelo. - El modelo recibe
3y decide que ya puede responder.
En este ejemplo no hay ni una sola línea de orquestación manual. El flujo emerge de las herramientas disponibles y del contexto de la conversación.
Nota sobre el modelo: si no se especifica un modelo en Strands Agents con Amazon Bedrock, el SDK suele usar Claude por defecto. Ese comportamiento puede cambiar en el futuro, así que en producción conviene declararlo explícitamente.
¿Por qué Strands Agents?
Strands Agents es un SDK open source de AWS bajo licencia Apache 2.0. Está diseñado para equipos que construyen sobre la infraestructura de AWS y quieren una integración nativa con sus servicios. Ya está probado en producción dentro del propio AWS: equipos como Amazon Q Developer, Amazon Glue o Kiro lo utilizan, y el ecosistema incluye aportes de empresas como Anthropic, Meta y Accenture.
Para quién es ideal:
- Equipos que ya operan en AWS y quieren integración nativa.
- Proyectos que necesitan seguridad, escalabilidad y cumplimiento empresarial.
- Desarrolladores que prefieren empezar con poco código y escalar hacia configuraciones más complejas.
El punto de partida es deliberadamente simple: unas pocas líneas de Python para registrar herramientas y un agente que las orquesta. El recorrido es hacia producción: evaluación, guardrails, observabilidad y despliegue en entornos reales.
Resumen
- Un LLM puro responde preguntas pero no actúa sobre el mundo; un agente añade herramientas para consultar datos, ejecutar funciones y tomar decisiones dinámicas.
- Un agente se compone de modelo (cerebro), herramientas (manos) y system prompt (personalidad).
- El enfoque workflow-driven codifica el flujo paso a paso; el model-driven delega la orquestación en el modelo, lo que lo hace más adaptable a imprevistos.
- El agent loop es el mecanismo que permite que el modelo solicite herramientas, reciba resultados y refine su respuesta iteración tras iteración.
- Strands Agents es un SDK open source de AWS para construir agentes model-driven con integración nativa en la nube de AWS.
En el siguiente capítulo pasaremos del papel a la máquina: prepararemos un proyecto Python con uv, instalaremos el SDK, crearemos las credenciales de Amazon Bedrock y ejecutaremos nuestro primer agente.
Autoevaluación
Antes de pasar al siguiente capítulo, comprueba que los conceptos clave han quedado claros.
1. ¿Qué distingue fundamentalmente a un agente de un LLM puro?
2. ¿Cuál de las siguientes NO es uno de los tres ingredientes de un agente en Strands Agents?
3. Cuando el modelo decide que necesita usar una herramienta, ¿quién la ejecuta realmente?
4. En el enfoque model-driven que sigue Strands Agents, ¿quién actúa como orquestador?
5. ¿Qué es lo que permite el razonamiento multipaso del agente a lo largo del agent loop?
6. En el ejemplo de Python del capítulo, ¿para qué sirve el docstring dentro de una función decorada con @tool?