운영과 실패 복구
오케스트레이터의 실패는 결과 상태와 호출 예외로 나눠 처리합니다. 둘을 한 retry 분기에 묶으면 설정 오류를 반복하거나, 응답만 잃은 side effect를 다시 실행할 수 있습니다.
결과와 예외 구분
섹션 제목: “결과와 예외 구분”| 신호 | 의미 | 권장 처리 |
|---|---|---|
is_input_required | 자식이 사용자 입력을 더 기다림 | 관리형 workflow는 checkpoint 후 재개, code-first는 대기 단계 기록 |
is_error | 자식이 errorCode를 담은 도메인 오류를 반환 | 결과로 분기하고 남은 성공 단계를 실행하지 않음 |
is_unavailable | upstream _pending_agent sentinel을 준비 중 결과로 정규화 | 잠시 사용할 수 없는 자식으로 처리 |
ChildUnresolvedError | Registry target을 해석하지 못함 | 설정·발견 문제로 분류 |
ChildCallError | alias, 전송, 네트워크, 프로토콜 문제 | 원인에 맞는 공개 오류로 정규화 |
is_unavailable은 네트워크 장애의 포괄 표현이 아닙니다. 네트워크·프로토콜 장애는 예외입니다. 이 구분은 code-first와 Agentic 문서 전체에서 같습니다.
직접 run_turn을 작성했다면 결과 상태를 합성보다 먼저 확인하세요.
work = await ctx.call( "verification", text=ctx.user_text, data=ctx.data, files=ctx.files,)
# 제어 상태를 정상 업무 결과와 합치지 않습니다.if work.is_input_required or work.is_error or work.is_unavailable: return work
return workcombine_results()는 모든 DataPart를 합치지만 text·files·raw·task state는 마지막 결과에서 가져옵니다. 앞 결과의 제어 상태를 잃지 않도록 완료 결과만 합치세요.
예외는 안정된 오류로 공개합니다
섹션 제목: “예외는 안정된 오류로 공개합니다”원 예외 문자열은 로그와 trace에 남기고, 사용자에게는 고정된 오류 계약만 보냅니다.
import logging
from llamon_agent.core.errors import ErrorCode, raise_application_errorfrom llamon_agent.orchestrator import ChildCallError, ChildUnresolvedError
logger = logging.getLogger(__name__)
async def call_verification(ctx): try: return await ctx.call("verification", data=ctx.data, files=ctx.files) except ChildUnresolvedError: # target 설정 오류는 같은 요청을 반복해도 해결되지 않습니다. logger.exception("verification target resolution failed") raise_application_error( ErrorCode.NOT_FOUND, "child_target_unresolved", message="요청한 처리 서비스를 찾을 수 없습니다.", retriable=False, ) except ChildCallError: # 전송 장애는 원문 대신 안정된 공개 문구로 변환합니다. logger.exception("verification call failed") raise_application_error( ErrorCode.UPSTREAM_UNAVAILABLE, "child_call_failed", message="요청을 처리하지 못했습니다. 잠시 후 다시 시도해 주세요.", retriable=True, )str(exc)를 공개 DataPart나 WorkflowState에 넣지 마세요. 공급자 URL, 인증 정보, 프롬프트나 사용자 입력이 섞일 수 있습니다. 내부 분류는 errorReason·domainCode에 두고 외부 errorCode에는 SDK 표준 enum을 사용합니다.
자동 checkpoint와 재개
섹션 제목: “자동 checkpoint와 재개”Agentic과 내장 TurnWorkflow는 다음 정보를 durable store에 저장합니다.
- 실행 단계와 완료 여부
- 실제로 해석한 child target snapshot
- 완료 결과의 relay artifact
- 도구 승인과 담당자 검수 대기 정보
- 재개 시 정책 변경을 확인할 digest
결과 검증을 켠 workflow는 provisional Agentic 후보와 별도의 verification state version, policy_id, evaluator target snapshot, policy digest, candidate digest, 평가·수정 횟수도 저장합니다. evaluator timeout이나 일시 unavailable로 멈춘 경우 같은 후보부터 재개합니다. 재개 시 정책·evaluator target·후보 digest가 바뀌면 과거 후보를 새 기준으로 몰래 재평가하지 않고 VERIFICATION_RESUME_DRIFT로 안전하게 실패합니다. 자세한 수명주기는 결과 검증 루프에 있습니다.
같은 conversation으로 새 입력이 오면 완료한 단계는 건너뛰고 기다리던 단계부터 이어 갑니다. OKF then.sequence도 완료 step의 artifact를 복구하고 대기 중인 child의 exact 입력과 target snapshot만 재개합니다. result_transitions나 고정 첫 호출의 result_gate 정책이 대기 중 바뀌면 과거 결과를 새 정책으로 자동 완료하지 않습니다. 저장한 결과는 재사용하되 controller 판단이나 안전한 종료 경계로 되돌립니다. 결과 정책의 세부 규칙은 Agentic 결과 정책에 있습니다.
WorkflowState의 save·commit 실패 때는 이번 턴의 메시지, WorkMemory 공개 상태와 workflow checkpoint를 턴 시작 상태로 함께 복원합니다. 반쪽짜리 기억이나 checkpoint가 남지 않게 하려는 경계입니다. 다만 raw code-first에서 예외 전에 저장을 마친 state와 외부 side effect까지 자동 롤백되는 것은 아닙니다.
retry와 멱등성
섹션 제목: “retry와 멱등성”일반 ctx.call()은 모든 예외를 자동 재시도하지 않습니다.
- alias 누락과 Registry 설정 오류는 재시도로 고쳐지지 않습니다.
- timeout은 자식이 작업을 끝냈지만 응답만 잃은 상황일 수 있습니다.
- 결제·발송·삭제를 같은 입력으로 다시 호출하면 중복 처리될 수 있습니다.
관리형 workflow는 안정된 orchestrationInvocationId와 orchestrationStepId, target snapshot, 완료 결과 복구를 제공합니다. 그러나 네트워크 전체의 정확히 한 번 실행(exactly-once)을 보장하지는 않습니다. side-effect 자식은 이 ID를 멱등성 키로 받아 중복 요청을 제거해야 합니다.
고정 첫 호출의 계약 위반을 재시도하려면 result_gate의 bounded retry를 사용하고, 실패 경로는 고정 respond 문구를 우선 검토하세요. controller 합성으로 실패를 감추지 않게 설계하는 편이 안전합니다.
PostgreSQL 운영
섹션 제목: “PostgreSQL 운영”로컬 개발은 state_backend = "in_memory"로 충분합니다. 재시작 복구나 multi-worker 처리가 필요하면 PostgreSQL을 사용하세요.
[orchestrator]# WorkflowState와 durable 실행 저장소를 PostgreSQL 계열로 조립합니다.state_backend = "postgres"DSN은 POSTGRES_ORCH_DSN 환경변수로 주입하며, 없으면 POSTGRES_MEMORY_DSN을 사용합니다. 비밀값을 TOML이나 문서 예제에 넣지 않습니다. 운영 전에는 다음을 확인하세요.
- 같은 conversation을 두 worker가 동시에 처리해도 실행이 직렬화되는가?
- DB 연결이 끊긴 뒤 완료한 child를 중복 호출하지 않는가?
- checkpoint와 relay artifact의 보존·정리 주기가 업무 재개 시간보다 긴가?
- 저장소와 backup에 원본 artifact가 남는 기간과 접근 권한이 적절한가?
배포 전 실패 시나리오
섹션 제목: “배포 전 실패 시나리오”input_required, 도메인 오류, pending unavailable, target 해석 실패, timeout을 각각 테스트합니다.- 병렬 일부 실패를 “문제없음”으로 표시하지 않고 누락 항목을 응답에 남깁니다.
- output guardrail이나 reviewer가 실패할 때 검수 전 초안이 공개되지 않는지 확인합니다.
- 승인 뒤 side effect의 상태가 불명확하면 자동 retry하지 않습니다.
- 공개 오류와 trace에 원문 데이터·credential·예외 문자열이 들어가지 않는지 검사합니다.
llamon doctor와 재시작·multi-worker 통합 테스트를 배포 gate에 둡니다.