· nervico-team · arquitectura-cloud · 11 min read
AWS Bedrock para IA: integración con agentes y aplicaciones
Guía técnica de AWS Bedrock: cómo integrar modelos fundacionales en aplicaciones, construir agentes de IA, implementar RAG y gestionar costes de inferencia en producción.
Integrar IA generativa en una aplicación de producción no es llamar a una API y mostrar la respuesta. Es gestionar latencia, costes, alucinaciones, seguridad de datos y disponibilidad. Y hacerlo en una infraestructura que ya tienes en AWS, sin mover datos a proveedores externos y sin gestionar GPUs.
AWS Bedrock es el servicio que resuelve ese problema. Ofrece acceso a modelos fundacionales de Anthropic (Claude), Meta (Llama), Mistral, Amazon (Titan) y otros, a través de una API unificada, sin necesidad de aprovisionar infraestructura de ML. Los datos no salen de tu cuenta de AWS. No se usan para entrenar los modelos. Y el escalado es automático.
Este artículo explica cómo funciona Bedrock en la práctica, cómo integrar modelos en aplicaciones, cómo construir agentes que ejecutan acciones, cómo implementar RAG con datos de tu empresa, y cuánto cuesta realmente.
Qué es AWS Bedrock
Servicio gestionado de modelos fundacionales
Bedrock no es un modelo de IA. Es una plataforma que da acceso a múltiples modelos a través de una API estándar. No necesitas entrenar modelos, gestionar GPUs ni instalar frameworks de ML.
Modelos disponibles (principales):
| Proveedor | Modelo | Contexto | Fortaleza |
|---|---|---|---|
| Anthropic | Claude 3.5 Sonnet | 200K tokens | Razonamiento, código, análisis |
| Anthropic | Claude 3 Haiku | 200K tokens | Velocidad, coste bajo |
| Meta | Llama 3.1 70B | 128K tokens | Open source, personalizable |
| Meta | Llama 3.1 8B | 128K tokens | Tareas ligeras, coste mínimo |
| Mistral | Mistral Large | 128K tokens | Multilingue, europeo |
| Amazon | Titan Text Express | 8K tokens | Coste bajo, tareas simples |
Lo que Bedrock gestiona por ti:
- Infraestructura de inferencia (GPUs, escalado, disponibilidad)
- Versionado de modelos
- Seguridad y compliance (datos en tu VPC, cifrado en tránsito y en reposo)
- Logging y monitorización con CloudWatch
- Rate limiting y throttling automático
Lo que Bedrock no hace
- No entrena modelos custom desde cero. Permite fine-tuning de algunos modelos, pero no entrenamiento completo.
- No garantiza latencia constante. Los tiempos de respuesta varían entre 1-30 segundos según el modelo y la longitud del prompt.
- No elimina alucinaciones. Los modelos siguen generando información incorrecta. Bedrock proporciona guardrails, pero la responsabilidad de la verificación es tuya.
Integración básica con la API
Invocación de modelos
La forma más directa de usar Bedrock es la API InvokeModel:
import boto3
import json
bedrock_runtime = boto3.client(
service_name='bedrock-runtime',
region_name='us-east-1'
)
def invoke_claude(prompt, max_tokens=1024):
body = json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": max_tokens,
"messages": [
{
"role": "user",
"content": prompt
}
],
"temperature": 0.3
})
response = bedrock_runtime.invoke_model(
modelId="anthropic.claude-3-5-sonnet-20241022-v2:0",
body=body,
contentType="application/json",
accept="application/json"
)
result = json.loads(response['body'].read())
return result['content'][0]['text']
# Ejemplo de uso
respuesta = invoke_claude(
"Analiza este log de errores y sugiere la causa raíz: "
"ERROR 2025-10-01 14:23:45 ConnectionPool exhausted, "
"max connections: 50, active: 50, waiting: 127"
)
print(respuesta)Streaming para respuestas largas
Para respuestas largas, el streaming reduce la latencia percibida:
def invoke_claude_streaming(prompt, max_tokens=2048):
body = json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": max_tokens,
"messages": [
{"role": "user", "content": prompt}
],
"temperature": 0.3
})
response = bedrock_runtime.invoke_model_with_response_stream(
modelId="anthropic.claude-3-5-sonnet-20241022-v2:0",
body=body,
contentType="application/json",
accept="application/json"
)
full_response = ""
for event in response['body']:
chunk = json.loads(event['chunk']['bytes'])
if chunk['type'] == 'content_block_delta':
text = chunk['delta'].get('text', '')
full_response += text
print(text, end='', flush=True)
return full_responseConverse API: interfaz unificada
La Converse API es la forma recomendada de interactuar con Bedrock desde 2024. Proporciona una interfaz consistente independientemente del modelo:
def converse_with_model(messages, model_id, system_prompt=None):
kwargs = {
"modelId": model_id,
"messages": messages,
"inferenceConfig": {
"maxTokens": 2048,
"temperature": 0.3,
"topP": 0.9
}
}
if system_prompt:
kwargs["system"] = [{"text": system_prompt}]
response = bedrock_runtime.converse(**kwargs)
return response['output']['message']['content'][0]['text']
# Uso con conversación multi-turno
messages = [
{
"role": "user",
"content": [{"text": "Soy CTO de una startup SaaS con 50K usuarios. Estamos en AWS."}]
},
{
"role": "assistant",
"content": [{"text": "Entendido. Puedo ayudarte con arquitectura, costes u operaciones en AWS."}]
},
{
"role": "user",
"content": [{"text": "Nuestra base de datos RDS está al 85% de CPU. Opciones?"}]
}
]
respuesta = converse_with_model(
messages=messages,
model_id="anthropic.claude-3-5-sonnet-20241022-v2:0",
system_prompt="Eres un arquitecto AWS senior. Responde con opciones concretas y costes estimados."
)Bedrock Agents: IA que ejecuta acciones
Qué son los Bedrock Agents
Los Bedrock Agents van más allá de generar texto. Pueden razonar sobre una tarea, decidir qué acciones ejecutar y llamar a APIs externas para completar el trabajo. El agente recibe una instrucción en lenguaje natural, descompone la tarea en pasos, ejecuta cada paso llamando a las herramientas disponibles, y devuelve el resultado.
Usuario: "Busca los pedidos del cliente ACME del último mes
y genera un resumen con el total facturado"
Agente:
1. Llama a la API de pedidos con filtro: cliente=ACME, fecha=último mes
2. Recibe la lista de pedidos
3. Calcula el total facturado
4. Genera un resumen en lenguaje natural
5. Devuelve el resultado al usuarioConfiguración de un agente
Un Bedrock Agent se compone de:
- Instrucciones: El prompt de sistema que define el comportamiento del agente.
- Action Groups: Las herramientas que el agente puede usar, definidas como API schemas (OpenAPI).
- Knowledge Bases: Bases de conocimiento (RAG) que el agente puede consultar.
import boto3
bedrock_agent = boto3.client('bedrock-agent', region_name='us-east-1')
# Crear agente
response = bedrock_agent.create_agent(
agentName='customer-support-agent',
agentResourceRoleArn='arn:aws:iam::123456789:role/bedrock-agent-role',
foundationModel='anthropic.claude-3-5-sonnet-20241022-v2:0',
instruction="""
Eres un agente de soporte técnico para una plataforma SaaS.
Tu objetivo es ayudar a los clientes a resolver problemas técnicos.
Reglas:
- Consulta el historial del cliente antes de responder.
- Si el problema requiere escalado, crea un ticket en el sistema.
- Nunca compartas información de un cliente con otro.
- Responde siempre en el idioma del cliente.
""",
idleSessionTTLInSeconds=1800
)Action Group con OpenAPI schema:
openapi: 3.0.0
info:
title: Customer API
version: 1.0.0
paths:
/customers/{customerId}/orders:
get:
summary: Get customer orders
operationId: getCustomerOrders
parameters:
- name: customerId
in: path
required: true
schema:
type: string
- name: dateFrom
in: query
schema:
type: string
format: date
- name: dateTo
in: query
schema:
type: string
format: date
responses:
'200':
description: List of orders
/tickets:
post:
summary: Create support ticket
operationId: createTicket
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
customerId:
type: string
subject:
type: string
priority:
type: string
enum: [low, medium, high, critical]
description:
type: stringEl agente decide cuándo y cómo llamar a cada endpoint basándose en la conversación con el usuario. No necesitas programar la lógica de decisión: el modelo fundacional la gestiona.
RAG con Bedrock Knowledge Bases
Qué es RAG y por qué importa
RAG (Retrieval-Augmented Generation) es el patrón que permite a un modelo de IA responder preguntas sobre los datos de tu empresa. En lugar de depender solo del conocimiento con el que fue entrenado, el modelo busca información relevante en tus documentos y la usa como contexto para generar la respuesta.
Sin RAG, el modelo alucinará sobre datos que no conoce. Con RAG, el modelo basa sus respuestas en documentos reales que tú controlas.
Configuración de Knowledge Base
Bedrock Knowledge Bases gestiona el pipeline completo de RAG:
- Ingestión: Carga documentos desde S3 (PDF, Word, HTML, texto plano, CSV).
- Chunking: Divide los documentos en fragmentos de tamaño configurable.
- Embedding: Convierte cada fragmento en un vector numérico usando un modelo de embedding.
- Almacenamiento: Guarda los vectores en una base de datos vectorial (OpenSearch Serverless, Aurora PostgreSQL con pgvector, Pinecone).
- Consulta: Cuando el usuario hace una pregunta, Bedrock busca los fragmentos más relevantes y los incluye en el prompt del modelo.
# Crear Knowledge Base
response = bedrock_agent.create_knowledge_base(
name='product-documentation',
description='Documentación técnica del producto',
roleArn='arn:aws:iam::123456789:role/bedrock-kb-role',
knowledgeBaseConfiguration={
'type': 'VECTOR',
'vectorKnowledgeBaseConfiguration': {
'embeddingModelArn': 'arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v2:0'
}
},
storageConfiguration={
'type': 'OPENSEARCH_SERVERLESS',
'opensearchServerlessConfiguration': {
'collectionArn': 'arn:aws:aoss:us-east-1:123456789:collection/my-collection',
'vectorIndexName': 'product-docs-index',
'fieldMapping': {
'vectorField': 'embedding',
'textField': 'text',
'metadataField': 'metadata'
}
}
}
)Estrategias de chunking
La forma en que divides los documentos afecta directamente a la calidad de las respuestas:
Fixed-size chunking: Divide en fragmentos de N tokens (300-500 es el rango óptimo para la mayoría de casos). Simple pero puede cortar información a mitad de una idea.
Hierarchical chunking: Crea chunks padre (secciones completas) y chunks hijo (párrafos). La búsqueda opera sobre los chunks hijo, pero el contexto incluye el chunk padre. Mejora la coherencia de las respuestas.
Semantic chunking: Divide en puntos donde el significado cambia. Más complejo de implementar pero produce fragmentos más coherentes.
# Configurar data source con chunking jerárquico
response = bedrock_agent.create_data_source(
knowledgeBaseId='kb-123456',
name='technical-docs',
dataSourceConfiguration={
'type': 'S3',
's3Configuration': {
'bucketArn': 'arn:aws:s3:::my-docs-bucket',
'inclusionPrefixes': ['docs/']
}
},
vectorIngestionConfiguration={
'chunkingConfiguration': {
'chunkingStrategy': 'HIERARCHICAL',
'hierarchicalChunkingConfiguration': {
'levelConfigurations': [
{'maxTokens': 1500}, # Chunks padre
{'maxTokens': 300} # Chunks hijo
],
'overlapTokens': 60
}
}
}
)Guardrails: control de la IA
Bedrock Guardrails
Los guardrails permiten definir políticas que el modelo debe cumplir. Filtran contenido no deseado, bloquean temas sensibles y verifican que las respuestas cumplen tus criterios.
Tipos de guardrails:
- Content filters: Bloquean contenido violento, sexual, discriminatorio o de odio.
- Denied topics: Impiden que el modelo hable sobre temas específicos (competidores, información financiera no pública, opiniones políticas).
- Word filters: Bloquean palabras o frases específicas en la respuesta.
- Sensitive information filters: Detectan y redactan PII (nombres, emails, números de teléfono, números de tarjeta de crédito).
- Contextual grounding: Verifican que la respuesta se basa en el contexto proporcionado (reduce alucinaciones en RAG).
# Crear guardrail
response = bedrock_agent.create_guardrail(
name='production-guardrail',
description='Guardrail para producción',
contentPolicyConfig={
'filtersConfig': [
{'type': 'SEXUAL', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'},
{'type': 'VIOLENCE', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'},
{'type': 'HATE', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'}
]
},
topicPolicyConfig={
'topicsConfig': [
{
'name': 'competitor-information',
'definition': 'Información sobre productos o servicios de competidores',
'examples': [
'Que opinas de [Competidor X]?',
'Es mejor tu producto o el de [Competidor Y]?'
],
'type': 'DENY'
}
]
},
sensitiveInformationPolicyConfig={
'piiEntitiesConfig': [
{'type': 'EMAIL', 'action': 'ANONYMIZE'},
{'type': 'PHONE', 'action': 'ANONYMIZE'},
{'type': 'CREDIT_DEBIT_CARD_NUMBER', 'action': 'BLOCK'}
]
}
)Costes de Bedrock
Modelo de facturación
Bedrock cobra por tokens procesados. La facturación separa tokens de entrada (prompt) y tokens de salida (respuesta):
| Modelo | Input (1M tokens) | Output (1M tokens) |
|---|---|---|
| Claude 3.5 Sonnet | 3,00 $ | 15,00 $ |
| Claude 3 Haiku | 0,25 $ | 1,25 $ |
| Llama 3.1 70B | 2,65 $ | 3,50 $ |
| Llama 3.1 8B | 0,22 $ | 0,22 $ |
| Titan Text Express | 0,20 $ | 0,60 $ |
Provisioned Throughput
Para cargas de trabajo predecibles, Provisioned Throughput ofrece capacidad reservada:
- Garantiza un número mínimo de tokens por minuto.
- Coste fijo por hora (independiente del uso).
- Útil si procesas más de 100.000 peticiones al día con el mismo modelo.
Ejemplo de coste mensual
| Caso de uso | Modelo | Peticiones/mes | Tokens promedio (in/out) | Coste mensual |
|---|---|---|---|---|
| Chatbot soporte (bajo) | Haiku | 10.000 | 500/200 | 3,75 $ |
| Chatbot soporte (medio) | Sonnet | 50.000 | 1.000/500 | 525 $ |
| Análisis de documentos | Sonnet | 5.000 | 5.000/2.000 | 225 $ |
| RAG empresarial | Sonnet + embedding | 20.000 | 2.000/1.000 | 420 $ |
Optimización de costes:
- Usa el modelo más pequeño que funcione: Para clasificación de texto o extracción simple, Haiku es 12 veces más barato que Sonnet y responde en milisegundos.
- Reduce el prompt: Cada token innecesario en el system prompt se multiplica por el número de peticiones. Un system prompt de 500 tokens con 100.000 peticiones/mes cuesta 150 dolares adicionales con Sonnet.
- Cachea respuestas para consultas repetitivas: Si el 20% de las preguntas se repiten, una caché en ElastiCache o DynamoDB reduce costes un 20%.
Arquitectura de producción
Patrón completo
Cliente → API Gateway → Lambda → Bedrock Runtime
|
┌─────────┼─────────┐
│ │ │
Guardrails Knowledge Agent
Base Actions
| |
OpenSearch Lambda
(RAG) (tools)Componentes:
- API Gateway: Punto de entrada con autenticación y rate limiting.
- Lambda: Orquesta la llamada a Bedrock, gestiona el contexto de la conversación y aplica lógica de negocio.
- Bedrock Runtime: Ejecuta la inferencia del modelo.
- Guardrails: Filtra entrada y salida.
- Knowledge Base: Proporciona contexto RAG.
- Agent Actions: Ejecuta herramientas (consultas a base de datos, llamadas a APIs internas).
Gestión del estado de conversación
Bedrock no mantiene estado entre llamadas. Tu aplicación debe gestionar el historial de la conversación:
import boto3
from datetime import datetime
dynamodb = boto3.resource('dynamodb')
conversations_table = dynamodb.Table('conversations')
def get_conversation_history(session_id, max_messages=20):
response = conversations_table.get_item(
Key={'session_id': session_id}
)
if 'Item' in response:
messages = response['Item'].get('messages', [])
return messages[-max_messages:]
return []
def save_message(session_id, role, content):
conversations_table.update_item(
Key={'session_id': session_id},
UpdateExpression='SET messages = list_append(if_not_exists(messages, :empty), :msg), updated_at = :now',
ExpressionAttributeValues={
':msg': [{'role': role, 'content': content, 'timestamp': datetime.utcnow().isoformat()}],
':empty': [],
':now': datetime.utcnow().isoformat()
}
)Errores comunes al integrar IA con Bedrock
Error 1: no gestionar la latencia
Una llamada a Claude 3.5 Sonnet con un prompt de 2.000 tokens tarda 3-8 segundos. Si tu API tiene un timeout de 3 segundos, las peticiones fallarán intermitentemente. Configura timeouts generosos (30-60 segundos) y usa streaming para mejorar la experiencia percibida.
Error 2: prompts de sistema demasiado largos
Cada token del system prompt se procesa en cada invocación. Un system prompt de 3.000 tokens con 50.000 peticiones al mes cuesta 450 dolares adicionales solo en tokens de entrada con Sonnet. Sé conciso.
Error 3: no implementar fallbacks
Si Bedrock devuelve un error (throttling, timeout, error del modelo), tu aplicación no debería mostrar un error genérico. Implementa:
- Retry con backoff exponencial para errores transitorios.
- Fallback a un modelo más ligero si el modelo principal no está disponible.
- Respuestas predefinidas para preguntas frecuentes que no necesitan IA.
Error 4: ignorar la seguridad de los prompts
Los usuarios pueden intentar inyectar instrucciones en el prompt para manipular el comportamiento del modelo. Usa guardrails, valida la entrada del usuario y nunca incluyas datos sensibles en el prompt que no quieras que el modelo pueda repetir.
Conclusión
AWS Bedrock simplifica la integración de IA generativa en aplicaciones de producción. Elimina la gestión de infraestructura de ML, mantiene los datos dentro de tu cuenta de AWS y proporciona herramientas de seguridad como guardrails y cifrado nativo.
Pero no es magia. Los modelos alucinan, la latencia es variable, y los costes se acumulan rápido si no optimizas los prompts y los modelos. La clave es empezar simple (una llamada API con el modelo adecuado), añadir RAG cuando necesites respuestas basadas en datos propios, y construir agentes solo cuando la tarea requiera ejecutar acciones.
Si estás evaluando cómo integrar IA en tu producto o necesitas ayuda para diseñar una arquitectura de IA en AWS, nuestro equipo tiene experiencia directa con Bedrock en producción. Solicita una auditoría gratuita para evaluar las oportunidades de IA en tu aplicación.