Skip to main content
SDK는 실패를 네 층으로 나눠, 어느 것이 예외를 던지고 어느 것이 결과로 돌아오는지 엄격히 분리합니다. .message 문자열 매칭이 아니라 타입 클래스로 분기하고, 구조화 로거로 재시도까지 겉으로 드러나게 두세요.

타입 에러

.message가 아니라 에러 클래스로 분기하세요. 모든 에러가 안정적 .code, (해당되면) 그 실행의 .traceId, 서버가 판정한 .retryable을 들고 옵니다.
계층:

실패 4층

이 규칙을 잘 읽어 두세요. Flow가 시작됐지만 도중에 실패하면 SDK는 예외를 던지지 않고, { status: "failed", traceId, outputs: <부분>, failure: {...}, notices: [...] }를 돌려줍니다. 예외만 잡는 조용한 try/catch는 이 실패를 놓칩니다. flows.run의 반환값 .status를 반드시 확인하세요.

왜 나뉘어 있나

“요청이 그래프에 도달하지도 못했다” 는 것은 예외로 던져 호출자가 크고 빠르게 실패하게 합니다. “그래프는 돌았는데 답이 깔끔하지 않다” 는 것은 결과로 돌려 다음을 다 챙깁니다.
  • 트레이스 UI와 feedback / signals.reporttraceId
  • 만들어진 부분 outputs
  • 재시도 · 다운그레이드 결정에 쓰는 기계 판독 가능 failure.code
  • 실행을 제약한 notices[] (관리자 UI에 노출하고, 최종 사용자에는 X)

로깅

기본이 구조화 · 레드액션입니다. 토큰 · 시크릿 · onBehalfOf 값 · 요청/응답 본문은 debug: true를 안 켜면 로그에 남지 않습니다.
재시도는 언제나 로깅됩니다. 각 시도마다 attempt, 실패 code, 결정이 남습니다. 조용한 재시도는 없습니다. 권장:
  • Nora 로그를 서비스 로거(pino / winston / bunyan)에 연결해 로그 레벨과 목적지를 맞추세요.
  • onLog를 메트릭에 연결하세요. 재시도율, 서킷 오픈율, 프로바이더 폴백 빈도는 상위 프로바이더가 삐걱대기 시작할 때 가장 먼저 움직이는 지표입니다.
  • 프로덕션에서는 debug를 끄고, 사고 재현할 때만 요청 단위 스코프드 클론으로 켜세요.

흔한 패턴

retryable일 때만 재시도

partial이면 다운그레이드

feedbacksignals.report 구분

섞으면 탐지기와 군집이 시끄러워집니다. 의도를 분리해서 담으세요.