도메인 에러 매핑 (도메인 카탈로그 → ApplicationError)
이게 왜 필요한가
섹션 제목: “이게 왜 필요한가”내 프로젝트에는 DOC_005, CTX_001 같은 자체 에러 코드가 있는데,
SDK의 관측성(trace 이벤트 · Langfuse)은 표준 ErrorCode 8종(INVALID_INPUT, NOT_FOUND, …)만 이해합니다.
이 둘을 에러를 던질 때마다 손으로 이으면 코드가 흩어지고 trace 필드도 빠지기 쉽습니다.
make_domain_error_raiser는 매핑 표(카탈로그) 하나로 전용 raise 함수를 만들어 이 연결을 한곳에 모읍니다.
이후 그 함수를 한 줄 호출하면 ApplicationError 생성과 trace 필드 노출이 자동입니다.
따라하기 (2단계)
섹션 제목: “따라하기 (2단계)”① 한 번만 — 카탈로그 + raise 함수 정의
섹션 제목: “① 한 번만 — 카탈로그 + raise 함수 정의”from llamon_agent.core.errors import ( DomainErrorSpec, ErrorCode, make_domain_error_raiser,)
_CATALOG: dict[str, DomainErrorSpec] = { "CTX_001": {"sdk_code": ErrorCode.INVALID_INPUT, "reason": "context_invalid", "title": "요청 컨텍스트 오류", "retriable": False}, "DOC_005": {"sdk_code": ErrorCode.NOT_FOUND, "reason": "doc_name_unrecognized", "title": "서류명 미식별", "retriable": False},}
raise_app_error = make_domain_error_raiser(_CATALOG)카탈로그는 도메인코드 → {sdk_code, reason, title, retriable} 매핑입니다.
| 필드 | 뜻 |
|---|---|
sdk_code | 표준 ErrorCode 8종 중 하나 |
reason | 기계용 사유 (snake_case 권장) |
title | 사용자에게 보일 기본 메시지 |
retriable | 클라이언트 재시도 가능 여부 |
② 매번 — 노드에서 호출
섹션 제목: “② 매번 — 노드에서 호출”from app.internals.errors import raise_app_error
raise_app_error("DOC_005", detail="documents 빈 배열")raise_app_error("DOC_005", detail="...") 한 줄이면 끝입니다.
(카탈로그에 없는 코드를 넣으면 즉시 ValueError로 알려줍니다. 메시지를 그때그때 바꾸려면 message="..."를 추가하세요.)
자동으로 채워지는 trace 필드
섹션 제목: “자동으로 채워지는 trace 필드”위 호출이 노드에서 일어나면 NODE_ERROR · TOOL_ERROR · INVOKE_ERROR · A2A_ERROR 이벤트 최상위에 다음 필드가 별도 코드 없이 등장합니다.
| 필드 | 출처 |
|---|---|
errorCode · errorReason · retriable | 카탈로그의 sdk_code · reason · retriable |
domainCode · domainTitle | 함수가 자동 추가 |
detail + 호출 시 넘긴 **extra | 호출 시점 |
덕분에 Langfuse에서 domainCode = "DOC_005" 기준으로 바로 묶어 보거나 거를 수 있습니다.
더 알아두면 좋은 것
섹션 제목: “더 알아두면 좋은 것”추가 정보 붙이기 — 호출할 때 아무 키나 더 넘기면 trace에 같이 실립니다.
raise_app_error("UPS_001", bankErrorCode="0042", retryAfterMs=1500)키 이름 바꾸기 — domainCode 대신 사내 컨벤션(bizCode 등)을 쓰려면:
raise_app_error = make_domain_error_raiser( _CATALOG, domain_code_key="bizCode", domain_title_key="bizTitle",)안전장치 2가지
- 호출할 때
errorCode·errorReason·retriable을**extra로 덮어쓰려 해도 카탈로그 값이 항상 우선합니다. - 카탈로그의
sdk_code가ErrorCode가 아니면, 운영 중이 아니라 함수를 만드는 순간 바로TypeError로 잡힙니다(fail-fast).
꼭 factory를 써야 하나?
섹션 제목: “꼭 factory를 써야 하나?”| 상황 | 권장 |
|---|---|
| 도메인 코드 3개 이상 + 일관성 필요 | make_domain_error_raiser (factory) |
| 코드 0~2개 / 일회성 | raise_application_error 직접 호출 |
직접 호출도 trace 노출 효과는 동일합니다. factory는 카탈로그 일관성과 “만드는 즉시 검증”을 더해 줄 뿐입니다.
from llamon_agent.core.errors import ErrorCode, raise_application_error
raise_application_error( ErrorCode.NOT_FOUND, "doc_name_unrecognized", domainCode="DOC_005",)관련 문서
섹션 제목: “관련 문서”- A2A 에러 처리 spec
- 플로우 상태와 헬퍼 —
require_state_*와 함께 사용