GuidesOneMux

API 인시던트 진단을 위한 제한된 LangGraph 에이전트 구축

읽기 전용 진단 도구를 호출하고, 실행을 제한하며, 실패를 명확히 드러내고, 위험한 작업 전에 일시 중지하는 LangGraph 인시던트 진단 에이전트를 구축합니다.

AI

요약 · TL;DR

유용한 인시던트 에이전트는 통제되지 않은 조치를 취하는 대신 증거를 수집해야 합니다. 이 튜토리얼에서는 읽기 전용 진단 도구, 명시적인 실패 신호, 제한된 실행, 그리고 복구 조치 전 사람의 검토를 포함하는 LangGraph 워크플로를 설명합니다.

핵심 요점

  • 진단 도구는 읽기 전용으로 유지하고, 실패를 포함한 구조화된 증거를 반환하세요.
  • 실행 한도를 설정하되, 이를 인시던트 진단 결과가 아닌 안전 경계로 취급하세요.
  • 프로덕션 상태를 변경하는 도구를 실행하기 전에 사람의 승인을 받으세요.
  • 인터럽트를 사용할 때는 그래프 상태를 저장해 일시 중지된 실행을 재개할 수 있게 하세요.
  • 추측을 진단 결과처럼 제시하지 말고, 도구 실패와 불완전한 증거를 보고하세요.
목차 (8)

결정: 진단은 자동화하고, 복구 조치는 신중하게

API 인시던트 에이전트는 로그, 상태 점검, 최근 배포 메타데이터에서 증거를 수집해 시간을 절약할 수 있습니다. 하지만 서비스를 몰래 재시작하거나 릴리스를 롤백하거나 구성을 변경해서는 안 됩니다. 더 안전한 설계는 읽기 전용 진단과 부작용이 발생하는 복구 조치를 분리하고, 에이전트의 작업 범위를 제한하며, 실패했거나 누락된 증거를 운영자에게 명확히 보여줍니다.

이 내용은 실용적인 설계 예시이며, 테스트된 통합이나 프로덕션에서 바로 사용할 수 있는 서비스가 아닙니다. 아래 도구 본문은 설명을 위한 예시입니다. 자체 인증 및 권한 제한 관측 클라이언트로 대체하세요.

사전 준비 사항 및 워크플로

Python, 애플리케이션에 구성된 LangGraph 호환 채팅 모델, 그리고 현재 사용하는 진단 시스템용 클라이언트 함수가 필요합니다. 이 예시에서는 해당 클라이언트 함수가 데이터를 반환하거나 예외를 발생시킨다고 가정합니다. 특정 모델 공급자, 엔드포인트 또는 도구 통합을 전제로 하지 않습니다.

유용한 인시던트 실행은 다음과 같이 제한된 루프를 따릅니다.

  1. 영향을 받은 서비스와 시간 범위에 대해 미리 정한 소수의 신호를 수집합니다.
  2. 각 결과를 성공, 실패 또는 사용 불가로 표시합니다.
  3. 모델에 증거를 요약하고 아직 확인되지 않은 사항을 식별하도록 요청합니다.
  4. 정해진 그래프 단계 수가 지나면 중단하고, 상태를 변경하는 작업 전에 사람의 검토를 요청합니다.

상태 필드가 중요한 이유는 운영 측면에 있습니다. 로그 쿼리가 실패한 경우, 일치하는 이벤트가 없었던 정상적인 로그 검색처럼 보이면 안 됩니다.

실패 신호를 명시하는 진단 도구 정의

도구 계약의 범위를 좁게 유지하세요. 서비스 이름과 제한된 시간 범위를 필수로 지정하고, 고정된 쿼리로 충분한 경우 모델에 임의의 쿼리 접근 권한을 주지 마세요. 후속 노드와 인시던트 보고서가 증거가 비어 있는 경우와 도구 실패를 구분할 수 있도록 구조화된 결과를 반환하세요.

from typing import Literal, TypedDict
from langchain.tools import tool

class Signal(TypedDict):
    status: Literal["ok", "error", "unavailable"]
    source: str
    data: str
    error: str | None


def query_logs(service: str, minutes: int) -> Signal:
    if not 1 <= minutes <= 60:
        return {
            "status": "error", "source": "logs", "data": "",
            "error": "minutes must be between 1 and 60",
        }
    try:
        # Replace with a read-only, scoped observability client call.
        rows = logs_client.search(service=service, minutes=minutes)
        return {
            "status": "ok", "source": "logs",
            "data": str(rows), "error": None,
        }
    except TimeoutError as exc:
        return {
            "status": "unavailable", "source": "logs", "data": "",
            "error": f"timeout: {exc}",
        }

@tool
def inspect_api(service: str, minutes: int = 15) -> dict:
    """Collect scoped, read-only API incident signals."""
    return query_logs(service, minutes)

동일한 결과 형식을 사용해 상태 점검이나 배포 메타데이터를 위한 도구를 별도로 추가하세요. 모든 예외를 잡아 빈 문자열을 반환하지 마세요. 통합 문제를 진단할 수 있도록 충분한 오류 맥락은 보존하되, 로그와 모델 컨텍스트에 비밀 정보나 민감한 페이로드가 포함되지 않도록 하세요.

실행을 제한하고 불완전한 실행을 드러내기

LangGraph의 create_agent로 에이전트를 만들었다면 호출 시 그래프 재귀 한도를 설정하세요. 이 한도는 그래프 단계를 제한하지만, 유용한 답변을 보장하거나 도구 수준의 시간 제한을 대신하지는 않습니다. 한도에 도달한 경우를 주변 애플리케이션에서 처리하고, 실행이 진단을 완료한 것처럼 취급하지 말고 명확한 '불완전' 상태를 반환하세요.

from langchain.agents import create_agent

agent = create_agent(
    model=your_configured_chat_model,
    tools=[inspect_api],
    system_prompt=(
        "Diagnose API incidents using available evidence. "
        "Report each source as ok, error, or unavailable. "
        "Do not claim a cause without supporting evidence. "
        "Do not perform remediation."
    ),
)

try:
    result = agent.invoke(
        {"messages": [{"role": "user", "content":
            "Investigate elevated errors for payments-api over the last 15 minutes."}]},
        config={"recursion_limit": 12},
    )
except Exception as exc:
    # Map known graph-limit and provider/tool failures to your app's
    # incident-run status; do not expose credentials or raw secrets.
    result = {"status": "incomplete", "reason": type(exc).__name__}

한도 값은 예시일 뿐, 보편적인 권장값이 아닙니다. 허용할 도구 수와 모델 호출 횟수를 기준으로 값을 정하고, 도구 및 애플리케이션 계층에 시간 제한과 요청 크기 제한을 추가하세요. 실행 ID, 선택한 서비스와 시간 범위, 시도한 도구, 도구 상태, 종료 사유를 기록하세요. 이러한 신호를 바탕으로 운영자는 '오류를 찾지 못함'과 '로그 백엔드 시간 초과'를 구분할 수 있습니다.

복구 조치 전에 사람의 검토 추가

나중에 프로덕션 상태를 변경하는 도구를 추가한다면 LangChain의 휴먼 인 더 루프 미들웨어와 체크포인터를 사용해 해당 도구를 제어하세요. 문서에 설명된 미들웨어는 조건에 맞는 도구 호출을 승인, 수정, 거부 또는 직접 응답을 위해 일시 중지할 수 있습니다. 상태가 저장되므로 결정이 내려진 뒤 실행을 재개할 수 있습니다. 프로덕션에서는 프로토타이핑용으로 표시된 인메모리 옵션 대신 영구 체크포인터를 사용해야 합니다. LangChain 휴먼 인 더 루프 문서를 참고하세요.

실용적인 정책은 읽기 전용 진단은 중단 없이 허용하고, 재시작, 롤백 또는 구성 변경 도구에는 승인을 요구하는 것입니다. 제안된 작업을 거부할 때는 해당 작업을 거부하세요. 문서에서는 'respond'가 부작용이 있는 호출을 거부하는 것이 아니라 도구 역할을 수행하기 위한 것이라고 주의를 줍니다. 수정된 인수는 자체 도구 구현에서 검증하세요. 문서에 설명된 미들웨어는 수정 내용을 표시된 스키마에 맞춰 검증하지 않습니다.

설계 시 고려할 실패 사례

  • 결과가 비어 있음: '서비스가 정상입니다'가 아니라 '일치하는 이벤트가 반환되지 않았습니다'라고 보고합니다.
  • 도구 시간 초과 또는 권한 부여 실패: 실패한 소스와 오류 범주를 보존하고, 끝없이 자동 재시도하지 않습니다.
  • 도구 호출 반복: 그래프 실행을 제한하고 도구 입력 범위를 좁힙니다. 재시도를 추가한다면 명시적으로 적은 횟수의 재시도 정책을 설정하고 시도 횟수를 표시합니다.
  • 인터럽트 후 재개 불가: 체크포인터가 구성되어 있는지, 재개할 때 동일한 스레드 식별자를 사용하는지 확인합니다. 원본 문서에서는 사람의 검토를 위해 체크포인팅이 필요하다고 명시합니다.
  • 오해를 부르는 최종 요약: 보고서의 주장을 수집된 신호와 연결하고, 사용할 수 없는 소스와 해결되지 않은 질문을 나열하도록 합니다.

인시던트 실행 체크리스트

배포 전에 진단 도구가 읽기 전용이며 범위가 제한되어 있는지, 시간 범위와 쿼리 양이 제한되어 있는지, 도구 오류를 확인할 수 있는지, 그래프 실행에 한도가 있는지, 부작용이 있는 각 작업이 사람의 결정을 위해 일시 중지되는지 확인하세요. 시간 초과, 빈 결과, 거부된 작업, 인터럽트 후 재개 경로를 테스트하세요. 좋은 에이전트는 그럴듯한 근본 원인을 제시하는 데 그치지 않습니다. 실제로 어떤 증거를 얻었는지, 진단이 어디까지인지 보여줍니다.

출처

FAQ

LangGraph 에이전트의 실행을 어떻게 제한하나요?

호출 구성에서 재귀 한도를 설정하고, 주변 애플리케이션에서 한도 도달이나 런타임 오류를 처리하세요. 도구 수준의 시간 제한과 입력 범위 제한도 적용해야 합니다. 그래프 한도만으로 진단 완료가 보장되지는 않습니다.

인시던트 에이전트는 진단 도구 실패를 어떻게 보고해야 하나요?

안전한 오류 범주와 소스 이름을 포함해 error 또는 unavailable 같은 구조화된 상태를 반환하세요. 이를 일치하는 이벤트가 없었던 성공적인 쿼리와 구분해야 합니다.

LangGraph 도구가 프로덕션을 변경하기 전에 어떻게 승인을 요구하나요?

휴먼 인 더 루프 미들웨어로 선택한 도구 호출을 중단하고, 그래프를 일시 중지했다가 재개할 수 있도록 체크포인터를 구성하세요. 읽기 전용 도구는 그대로 허용하고 부작용이 있는 도구는 검토를 거치게 하세요.

휴먼 인 더 루프 미들웨어는 수정된 도구 인수를 검증하나요?

제공된 문서에 따르면 표시된 응답 스키마와 수정 내용을 대조해 확인하지 않습니다. 작업을 수행하기 전에 도구나 애플리케이션에서 인수를 검증하세요.

관련 글