1. ¿Qué es Amazon Bedrock AgentCore?
Es la plataforma de AWS para construir, desplegar y operar agentes de IA en producción. aws.amazon
AgentCore está diseñado para ciclo de vida completo (observabilidad, optimización, A/B testing, memoria, seguridad). aws.amazon
Por qué importa optimizar system prompts: los agentes en producción fallan por prompts vagos, descripciones de herramientas imprecisas, o falta de iteración basada en datos reales.
2. El problema que resuelve la optimización de prompts
- Los equipos suelen editar prompts manualmente → intuición, no evidencia. dev
- En producción, los agentes generan traces (registros de ejecución) que contienen fallos, éxitos, feedback humano, etc.. aws.amazon
- Sin un proceso estructurado, es difícil saber qué cambiar y por qué. aws-news
3. ¿Cómo funciona AgentCore Optimization?
Explica el ciclo de optimización en 4 pasos:
- Recolección de traces: logs de ejecuciones reales del agente en CloudWatch. aws.amazon
-
Evaluación con métricas: usa evaluadores como
GoalSuccessRateo métricas personalizadas. gerardo - Recomendaciones automáticas: el motor "reflector" analiza patrones de fallo y propone cambios al system prompt o descripciones de herramientas. aws.amazon
- Validación y A/B testing: prueba offline o en producción con Configuration Bundles y Gateway. aws.amazon
4. Conceptos básicos
- System prompt: instrucciones base que definen el comportamiento del agente. aws.amazon
- Traces: registros de cada ejecución del agente (input, output, tool calls, métricas). aws.amazon
- Evaluadores: métricas que miden éxito/fracaso (ej. tasa de éxito, feedback humano). aws.amazon
- Configuration Bundles: prompts y descripciones externalizados, versionados y intercambiables sin redeploy. dev
- Reflector engine: componente que analiza traces y genera recomendaciones. aws.amazon
- GEPA: Nombre de un método antiguo de optimización de prompts. Es el "baseline" o punto de referencia para comparar mejoras.
- MIPROv2: Nombre de otro método de optimización, más avanzado que GEPA pero más lento.
- Single Agent Reflector: Método nuevo de AgentCore donde un solo agente analiza todas las conversaciones y genera recomendaciones de mejora.
- Sub-Agent Reflector: Método nuevo de AgentCore donde varios agentes analizan las conversaciones en paralelo para generar recomendaciones más diversas.
5. Demo
En el siguiente proyecto trato de mostrar como puedes usar AgentCore Optimization y ver los resultados. Es una demo de cómo un agente de IA puede mejorar automáticamente las instrucciones de otro agente.
La idea: tenés un agente de soporte al cliente que a veces mete la pata (por ejemplo, reembolsa un pedido sin chequear primero si corresponde). En vez de que un humano se siente a reescribir sus instrucciones a mano, armamos un segundo agente ("el Reflector") que:
- Lee un montón de ejemplos de conversaciones pasadas del agente (algunas buenas, algunas malas).
- Detecta el patrón de qué sale mal.
- Reescribe las instrucciones del agente para corregir ese patrón.
- Antes de aplicar el cambio, un sistema de "reglas de seguridad" (guardrails) revisa que la propuesta no sea absurdamente larga, no copie texto textual de los ejemplos, y no tenga frases peligrosas.
- Si la propuesta no pasa esas reglas, se la devuelve al Reflector con el motivo del rechazo para que la corrija — como una especie de ida y vuelta de revisión.
Después medimos si realmente mejoró: le damos al agente un examen con tickets nuevos que nunca vio, y comparamos cuántos resuelve bien antes vs. después del cambio de instrucciones.
Requisitos
- Tener Python instalado (versión 3.10 o más nueva).
- Una cuenta de AWS (Amazon Web Services)
- Acceso habilitado a Amazon Bedrock dentro de esa cuenta,
- Credenciales de AWS configuradas en la máquina
Pasos:
- Clonar el repositorio https://github.com/kevinlupera/agentcore-prompt-optimizer-demo
git clone https://github.com/kevinlupera/agentcore-prompt-optimizer-demo
- Instalar las dependencias
pip install -r requirements.txt
- Conectar la cuenta de AWS
aws configure
- Confirmar que el modelo esté habilitado: entrar a la consola de Bedrock en AWS y verificar que el modelo Claude esté activado
us.anthropic.claude-sonnet-4-6
- Ejecución
python gen_traces.py # Escribe tracas de ejemplo(4 pass, 4 fail)
python run_demo.py # Ejecuta el demo del agente
python eval.py # Evalua los resultados antes y despues de optimizar el prompt
python optimize.py # Ejecuta el proceso de optimización
Resultados
optimize.py
eval.py
Resultado propio — antes / después
python eval.py · mismo held-out set, dos prompts, tools mockeadas.
Métricas
A continuación detallo los resultados de las métricas obtenidas antes y despues de la optimización:
Entre más alto el porcentaje es mejor.
| Método | Grupo | Success | Δ vs baseline (72.62%) | Turns | Tiempo |
|---|---|---|---|---|---|
| GEPA | Baseline previo | 79.63% | +7.0 pts | 100 | 108 min |
| MIPROv2 | Baseline previo | 74.40% | +1.8 pts | 100 | 216 min |
| Single Agent Reflector | Reflector (AWS, este post) | 81.55% | +8.9 pts | 20 | 6 min |
| Sub-Agent Reflector | Reflector (AWS, este post) | 95.83% | +23.2 pts | 100 | 193 min |
Detalle — 8 tickets held-out (antes = original, después = prompt final tras 3 epochs)
| Ticket | Descripción | Esperado | Antes | Después |
|---|---|---|---|---|
| B200 | Orden nunca llegó, pide reembolso | issue_refund |
✅ refund | ✅ refund |
| B201 | Llegó roto, pide reembolso | issue_refund |
✅ refund | ✅ refund |
| B202 | Se arrepintió, orden en tránsito | reply |
❌ refund | ✅ reply |
| B203 | Producto equivocado, aún procesando | reply |
❌ refund | ✅ reply |
| B204 | Pide reembolso, ya estaba cancelada | reply |
❌ refund | ✅ reply |
| B205 | Cobro duplicado, urgente | escalate |
❌ refund | ✅ escalate |
| B206 | Solo consulta estado | reply |
✅ reply | ✅ reply |
| B207 | Se perdió en camino, pide reembolso | issue_refund |
✅ refund | ✅ refund |
Casos de prueba
Detalle — 8 tickets held-out
| Ticket | Descripción | Esperado | Antes | Después |
|---|---|---|---|---|
| B200 | Orden nunca llegó, pide reembolso | issue_refund |
✅ refund | ✅ refund |
| B201 | Llegó roto, pide reembolso | issue_refund |
❌ sin check | ✅ refund |
| B202 | Se arrepintió, orden en tránsito | reply |
❌ refund | ✅ reply |
| B203 | Producto equivocado, aún procesando | reply |
❌ refund | ❌ escalate |
| B204 | Pide reembolso, ya estaba cancelada | reply |
❌ refund | ❌ refund |
| B205 | Cobro duplicado, urgente | escalate |
❌ refund | ✅ escalate |
| B206 | Solo consulta estado | reply |
✅ reply | ✅ reply |
| B207 | Se perdió en camino, pide reembolso | issue_refund |
❌ sin check | ✅ refund |
6. Explicación
El agente Reflector (reflector.py) — inspecciona traces y devuelve prompt revisado en tag parseable:
MODEL_ID = "us.anthropic.claude-sonnet-4-6"
def build_reflector() -> Agent:
model = BedrockModel(model_id=MODEL_ID, temperature=0.2, max_tokens=1024)
return Agent(
model=model,
tools=[list_traces, file_read],
system_prompt=REFLECTOR_INSTRUCTIONS,
callback_handler=status_callback,
)
def propose_new_prompt(current_prompt: str, feedback: str | None = None) -> str:
reflector = build_reflector()
task = f"...Este es el system prompt actual...\n\n{current_prompt}\n\nInspeccioná ./traces y proponé el prompt revisado."
if feedback:
task += f"\n\nTu propuesta anterior fue RECHAZADA, motivo:\n{feedback}\n\nProponé una revisión más ajustada..."
result = reflector(task)
match = re.search(r"<NEW_PROMPT>(.*?)</NEW_PROMPT>", str(result), re.DOTALL)
return match.group(1).strip()
- Guardrails antes de promover (guardrails.py) — 3 checks del post de AWS:
LENGTH_CEILING = 0.20
def run_guardrails(old_prompt, new_prompt, traces_dir) -> tuple[bool, list[str], list[str]]:
checks = [
check_length_ceiling(old_prompt, new_prompt),
check_safety(new_prompt),
check_no_overfit(new_prompt, traces_dir),
]
passed = all(ok for ok, _ in checks)
return passed, [msg for _, msg in checks], [msg for ok, msg in checks if not ok]
- Loop propose → guardrail-check → retry (run_demo.py):
MAX_ATTEMPTS = 3
feedback = None
for attempt in range(1, MAX_ATTEMPTS + 1):
new_prompt = propose_new_prompt(old_prompt, feedback=feedback)
passed, report, failures = run_guardrails(old_prompt, new_prompt, traces_dir)
if passed:
break
feedback = "; ".join(failures)
- Loop multi-epoch con eval-feedback + presupuesto explícito (optimize.py) — la pieza más cercana al loop real de AgentCore Optimization, y la que destrabó 50%→100%:
def propose_within_guardrails(candidate, extra_feedback, traces_dir) -> str | None:
max_len = int(len(candidate) * (1 + LENGTH_CEILING))
budget_line = f"Presupuesto estricto: {len(candidate)} chars actuales, tope {max_len} chars."
feedback = f"{extra_feedback}\n\n{budget_line}" if extra_feedback else budget_line
for attempt in range(1, MAX_GUARDRAIL_ATTEMPTS + 1):
new_prompt = propose_new_prompt(candidate, feedback=feedback)
passed, report, failures = run_guardrails(candidate, new_prompt, traces_dir)
if passed:
return new_prompt
feedback = f"{budget_line}\n\nTu intento anterior tuvo {len(new_prompt)} chars, {len(new_prompt) - max_len} de más. Recortalo..."
return None
# por epoch: propone dentro de presupuesto → corre eval → retroalimenta tickets que fallan
for epoch in range(1, MAX_EPOCHS + 1):
new_prompt = propose_within_guardrails(candidate, eval_feedback, traces_dir)
pass_rate, results = run_eval(new_prompt)
if pass_rate == 1.0:
break
eval_feedback = format_eval_feedback([r for r in results if not r["passed"]])
candidate = new_prompt
7. Aprendizajes
No importa cuánto contexto le des al reflector, importa qué tan concreto sea. Pasarle solo la razón del guardrail (ej. "creciste 24%") funcionó mejor que pasarle la lista completa de tickets fallidos sin límite — eso lo empujó a escribir prompts largos y vagos que ni entraban bajo el guardrail. Lo que destrabó la convergencia (50%→100% en 3 epochs) fue darle un número exacto de caracteres, recalculado por epoch, en vez de un porcentaje. Mismo patrón en la referencia de AWS: Sub-Agent Reflector (95.8%) le gana a GEPA/MIPROv2 no por fuerza bruta sino por feedback mejor dirigido — a costo de más tiempo (193 min vs 6-108 min).
8. Errores comunes y cómo evitarlos
- No externalizar prompts en Configuration Bundles → requiere redeploy para cada cambio. dev
- Ignorar la validación → aplicar recomendaciones sin A/B testing puede empeorar el agente. aws.amazon
- Usar traces muy homogéneos → el reflector necesita diversidad para detectar patrones de fallo. aws.amazon
- No instrumentar con OpenTelemetry desde el inicio → sin traces, no hay optimización posible. aws.amazon





Top comments (0)