Observabilidad: registrar llamadas, errores y cancelaciones
En producción, "el agente no pudo reservar" solo se resuelve con registro. Cada llamada de tool, en cualquier puerta, deja una línea: superficie, tool, resultado y tiempo. Sin datos personales. En esta lección provocas los desenlaces posibles y lees lo que cada uno deja en el log.
4Por qué el log guarda el nombre del campo y no el valor
Objetivo: registrar cada llamada en las tres superficies con resultado y tiempo, sin datos personales, y leer los desenlaces posibles en el log.
01 · Del pedido a la línea en el log
El registro queda en la frontera, no dentro de la regla. Haz clic en cada etapa.
Haz clic en cada bloque del diagrama para ver qué hace.
02 · Los desenlaces que importan
Cada uno pide una acción distinta de quien opera el sitio.
1. erro
Una entrada que la regla no acepta: tema inválido, taller sin cupo.
Muchos errores en la misma herramienta = descripción o schema confusos para el agente.
Kitmotivo: tema inválido: cobol
2. recusado
La confirmación funcionó. No es una falla del sitio.
Muchos rechazos = el agente está proponiendo lo que no debe; mira qué pidió.
3. cancelado
El agente desistió (o la persona se fue) antes de la respuesta: el executeTool se canceló por el signal.
Medido en el kit: la cancelación llega al execute como AbortError y la reserva no ocurre.
4. pediu-pessoa
En MCP 2026-07-28, la 1ª vuelta de una acción con confirmación devuelve input_required.
Por eso una reserva por MCP deja dos líneas: el pedido y el desenlace.
03 · El envoltorio
El mismo archivo sirve a la página y al servidor. En la página, en producción, la línea iría a tu backend (sendBeacon, por ejemplo); en el kit queda en memoria.
Archivo · kit/pagina/registro.mjs
// registro.mjs — observabilidade nas fronteiras: uma linha por chamada de ferramenta, em qualquer superfície.
// Roda no navegador (página) e no Node (servidor MCP). Não guarda dado pessoal: só o NOME dos campos de entrada.
// Resultado: ok | erro (regra recusou) | recusado (a pessoa disse não) | cancelado (AbortSignal) | excecao
// | pediu-pessoa (MCP: a 1ª volta do MRTR devolve input_required e o cliente pergunta ao usuário).
const linhas = [];
let destino = null; // função que recebe cada linha (no servidor: grava JSONL; na página: sendBeacon em produção)
export function aoRegistrar(fn) { destino = fn; }
export function linhasRegistradas() { return linhas.map(l => ({ ...l })); }
export function classificar(r) {
if (r && typeof r === 'object') {
if (r.resultType === 'input_required') return 'pediu-pessoa';
if ('erro' in r) return 'erro';
if (r.reservado === false) return 'recusado';
}
return 'ok';
}
export function anotar(linha) {
const l = { t: new Date().toISOString(), ...linha };
linhas.push(l);
globalThis.__registro = linhas; // os testes leem daqui
destino?.(l);
return l;
}
// Embrulha o execute de uma ferramenta: mede o tempo e anota o resultado, sem mudar o que ela devolve.
export function observado(superficie, ferramenta, fn) {
return async (input = {}, opcoes) => {
const inicio = performance.now();
const base = { superficie, ferramenta, campos: Object.keys(input).sort() };
try {
const r = await fn(input, opcoes);
anotar({ ...base, resultado: classificar(r), ms: Math.round(performance.now() - inicio), ...(r?.erro ? { motivo: r.erro } : {}) });
return r;
} catch (e) {
anotar({ ...base, resultado: e.name === 'AbortError' ? 'cancelado' : 'excecao', ms: Math.round(performance.now() - inicio), motivo: e.name });
throw e;
}
};
}
04 · Provocar los desenlaces y leer el log
El script busca, se equivoca de tema, rechaza, cancela y reserva por MCP con rechazo. Graba logs/chamadas.jsonl.
== Chromium 156.0.8078.4 (Playwright) · modo: nativo
html buscar_oficinas ok 0 ms
webmcp buscar_oficinas ok 0 ms
webmcp buscar_oficinas erro 3 ms · tema inválido: cobol
webmcp reservar_vaga recusado 184 ms
webmcp reservar_vaga cancelado 319 ms · AbortError
mcp buscar_oficinas ok 0 ms
mcp reservar_vaga pediu-pessoa 26 ms
mcp reservar_vaga recusado 2 ms
REGISTRO: 8 chamadas · ok 3 · erro 1 · recusado 2 · cancelado 1 · pediu-pessoa 1 · dado pessoal no registro: não
gravado em logs/chamadas.jsonl
saída: 0
{"t":"2026-10-19T20:03:13.159Z","superficie":"mcp","ferramenta":"reservar_vaga","campos":["id","nome"],"resultado":"recusado","ms":2}
La última línea es una línea real del archivo: los campos id y nome aparecen por su nombre, nunca por su valor. Los milisegundos varían en cada ronda.
Alguien cambió campos por entrada: input "para depurar". El nombre de las personas terminó en el log, y el script sale con 1. Un log con datos personales se vuelve un pasivo (LGPD): registra lo que ayuda a operar, no lo que identifica a alguien.
05 · El ensayo de la fuga
En una copia desechable del kit.
Terminal · log con datos personales
cd ~/projetos/formacao-webmcp-expert-v72/kit
E=$(bash scripts/copia.sh a3)
# o erro comum: registrar a entrada inteira "para depurar"
sed -i 's/campos: Object.keys(input).sort()/entrada: input/' $E/pagina/registro.mjs
cd $E && node scripts/observar.mjs nativo | grep "REGISTRO"; echo "saída: ${PIPESTATUS[0]}"
06 · Práctica
Leer el log, ver cómo se detecta la fuga y decidir qué registra tu sitio. Cada ejercicio termina en un listo cuando.
E1 · Los desenlaces en el log
5 min
Corre el bloque del registro y cuenta las líneas por desenlace.
Listo cuando:node scripts/observar.mjs nativo; echo "saída: $?" → REGISTRO: 8 chamadas · ok 3 · erro 1 · recusado 2 · cancelado 1 · pediu-pessoa 1 · dado pessoal no registro: não y saída: 0.
E2 · Detectar la fuga
3 min
Corre el ensayo del log con la entrada completa.
Listo cuando: El bloque imprime dado pessoal no registro: SIM y saída: 1.
E3 · El registro de tu sitio
15 min
Para las herramientas de tu sitio, escribe qué campos entran en el log (solo el nombre), a dónde va la línea en producción y quién revisa el resumen cada semana.
Listo cuando: El archivo registro-[tu sitio].md tiene una línea por herramienta, el destino del log y la persona responsable, y ningún campo con valor de entrada.
07 · Prueba de la clase
La explicación aparece después de la respuesta.
Pregunta 1 de 4
La reserva por MCP con confirmación dejó dos líneas en el log. ¿Por qué?
Correcto
Es el MRTR de la revisión 2026-07-28: la herramienta devuelve input_required, el cliente pregunta y repite la llamada. No hay sesión en el protocolo.
No es esa
Es el MRTR de la revisión 2026-07-28: la herramienta devuelve input_required, el cliente pregunta y repite la llamada. No hay sesión en el protocolo.Repasar: Los desenlaces que importan
Pregunta 2 de 4
El log muestra muchas líneas "recusado" en reservar_vaga. ¿Qué miras primero?
Correcto
Recusado = la persona dijo que no. La protección funcionó; muchos rechazos sugieren que el agente está proponiendo lo incorrecto. La entrada inválida aparece como error.
No es esa
Recusado = la persona dijo que no. La protección funcionó; muchos rechazos sugieren que el agente está proponiendo lo incorrecto. La entrada inválida aparece como error.Repasar: Los desenlaces que importan
Pregunta 3 de 4
¿Por qué el registro guarda campos: ["id", "nome"] y no los valores?
Correcto
El nombre de quien reserva es un dato personal. Para operar basta saber que la llamada tenía id y nombre, el desenlace y el tiempo. El ensayo muestra el script atrapando la fuga.
No es esa
El nombre de quien reserva es un dato personal. Para operar basta saber que la llamada tenía id y nombre, el desenlace y el tiempo. El ensayo muestra el script atrapando la fuga.Repasar: El envoltorio
Pregunta 4 de 4
¿Dónde queda el envoltorio observado() en el kit?
Correcto
El registro queda en la frontera (formulario, herramienta WebMCP, herramienta MCP), alrededor de execute. La regla sigue pura y el mismo registro.mjs sirve a la página y al servidor.
No es esa
El registro queda en la frontera (formulario, herramienta WebMCP, herramienta MCP), alrededor de execute. La regla sigue pura y el mismo registro.mjs sirve a la página y al servidor.Repasar: Del pedido a la línea en el log
Prueba completada
Acertaste {a} de {n}. Si aciertas todas, la clase se marca como completada.
Elige una alternativa. La explicación aparece después de tu intento.
08 · En tres frases
LíneaSuperficie, herramienta, nombres de los campos, desenlace y tiempo: una por llamada.
DesenlaceError, rechazo, cancelamiento y pedido del MRTR cuentan historias diferentes.
PrivacidadEl valor de la entrada queda fuera del log; el script atrapa a quien se olvide.