En el step anterior aprendiste a no tirar excepciones. retornás { ok: false, error: ... } en lugar de crashear. Ese fue el primer 50%. el segundo 50% es qué metés adentro de error.
Hay una diferencia enorme entre estos dos errores:
// Inútil
{ ok: false, error: "no se puede" }
// Accionable
{
ok: false,
error: {
code: "capacity_too_small",
message: "Room room-B-04 has capacity 4, but you requested 8 people.",
available_capacity: 4,
requested_capacity: 8,
recovery_hint: "Try list_rooms({ min_capacity: 8 }) to find a bigger room."
}
}Con el segundo, el agente puede:
list_rooms con min_capacity: 8).Con el primero, el agente no sabe nada. lo más probable es que reintente, o le diga al usuario "no funcionó" y corte la conversación.
{
ok: false,
error: {
code: string, // machine-readable, snake_case
message: string, // human-readable
...extra_context // datos para razonar
}
}Los campos extra son lo que distingue un error útil de uno inútil. Cada code debería traer la info específica del caso:
not_found → qué buscabas (looked_up: "room-B-04").permission_denied → qué permiso falta (required_role: "admin").validation_failed → qué campo y qué regla (field: "amount", rule: "min:1").conflict → con qué entra en conflicto (conflicts_with: {...}).rate_limited → cuándo se puede reintentar (retry_after: "30s").recovery_hintUna técnica que paga: agregá recovery_hint como string libre, sugiriendo el siguiente paso. El agente lee esa frase y casi siempre la sigue. Es como darle un consejo de tu lado.
recovery_hint: "Try list_available_rooms({ min_capacity: 8, deck: 'B' }) to find a fitting room."A la derecha tenés book_room. El starter funciona en el happy path. Tu trabajo: cubrir 4 casos de error con mensajes ricos, cada uno con su code específico y datos extra para que el agente pueda actuar.
El agente solo es tan inteligente como la información que le das. Errores pobres = agente pobre. Errores ricos = agente que se autocorrige.