.message 문자열 매칭이 아니라 타입 클래스로 분기하고, 구조화 로거로 재시도까지 겉으로 드러나게 두세요.
타입 에러
.message가 아니라 에러 클래스로 분기하세요. 모든 에러가 안정적 .code, (해당되면) 그 실행의 .traceId, 서버가 판정한 .retryable을 들고 옵니다.
실패 4층
이 규칙을 잘 읽어 두세요. Flow가 시작됐지만 도중에 실패하면 SDK는 예외를 던지지 않고,
{ status: "failed", traceId, outputs: <부분>, failure: {...}, notices: [...] }를 돌려줍니다. 예외만 잡는 조용한 try/catch는 이 실패를 놓칩니다. flows.run의 반환값 .status를 반드시 확인하세요.
왜 나뉘어 있나
“요청이 그래프에 도달하지도 못했다” 는 것은 예외로 던져 호출자가 크고 빠르게 실패하게 합니다. “그래프는 돌았는데 답이 깔끔하지 않다” 는 것은 결과로 돌려 다음을 다 챙깁니다.- 트레이스 UI와
feedback/signals.report용traceId - 만들어진 부분
outputs - 재시도 · 다운그레이드 결정에 쓰는 기계 판독 가능
failure.code - 실행을 제약한
notices[](관리자 UI에 노출하고, 최종 사용자에는 X)
로깅
기본이 구조화 · 레드액션입니다. 토큰 · 시크릿 ·onBehalfOf 값 · 요청/응답 본문은 debug: true를 안 켜면 로그에 남지 않습니다.
attempt, 실패 code, 결정이 남습니다. 조용한 재시도는 없습니다.
권장:
- Nora 로그를 서비스 로거(pino / winston / bunyan)에 연결해 로그 레벨과 목적지를 맞추세요.
onLog를 메트릭에 연결하세요. 재시도율, 서킷 오픈율, 프로바이더 폴백 빈도는 상위 프로바이더가 삐걱대기 시작할 때 가장 먼저 움직이는 지표입니다.- 프로덕션에서는
debug를 끄고, 사고 재현할 때만 요청 단위 스코프드 클론으로 켜세요.