SigNoz의 MCP Server를 사용하여 스스로 디버깅하는 AI Agent를 만들었습니다
요약
SigNoz의 MCP Server를 활용하여 관측 가능성(Observability) 데이터를 직접 쿼리하고 스스로 디버깅하는 AI Agent 구축 사례를 소개합니다. 하드코딩된 쿼리 없이 LLM이 적절한 도구를 선택하여 실제 수치 기반의 진단을 수행하는 과정을 다룹니다.
핵심 포인트
- MCP Server를 통해 AI Agent가 관측 가능성 데이터에 직접 접근 가능
- 하드코딩 없이 LLM이 스스로 적절한 쿼리 도구를 선택하여 추론
- OpenTelemetry 트레이스를 활용한 에이전트 동작의 가시성 확보
- 실제 실패 모드(지연, 에러)를 포함한 실전적인 디버깅 환경 구축
저는 터미널 명령어에 질문을 던졌습니다 — "왜 check_inventory 호출이 실패하고 있나요? 구체적인 수치를 알려주세요." — 그리고 다음과 같은 답변을 받았습니다:
sre-agent 서비스의 지난 6시간 동안:
- execute_tool check_inventory로 명명된 총 Span: 11
- Error Span: 0 (0%)
- 에러 비율: 0 / 11 (0%)
sre-agent 서비스 필터를 통해 signoz_aggregate_traces를 사용하여 직접 쿼리한 결과입니다. 이것은 제가 대시보드를 읽은 것이 아닙니다. 제 시스템에 대한 사전 지식이 전혀 없는 두 번째 AI Agent가 SigNoz의 MCP Server에 연결하여, 스스로 적절한 쿼리 도구를 선택하고, 추측 대신 실제 수치로 답변한 것입니다. 이 포스트는 이것을 구축하는 방법과, 제대로 작동하기 전까지 네 가지 방식으로 실패했던 과정에 관한 것입니다.
제가 실제로 해결하려고 했던 문제
AI Agent는 조용히 실패합니다. 도구 호출(Tool call)이 타임아웃되거나, LLM 호출이 느려지거나, 재시도 루프(Retry loop)가 토큰 소모를 세 배로 늘려도, 이 중 어느 것도 충돌(Crash)처럼 보이지 않습니다. 사용자가 불평하기 전까지는 아무 일도 일어나지 않는 것처럼 보입니다. SigNoz의 Agents 해커톤(Track 01: AI & Agent Observability)을 위해, 저는 단순히 Agent를 SigNoz에 연결하고 Trace 스크린샷을 찍는 것에 그치고 싶지 않았습니다. 저는 더 날카로운 질문에 답하고 싶었습니다: 관측 가능성(Observability) 데이터 자체가 두 번째 Agent가 무엇이 잘못되었는지 설명하는 데 사용하는 도구가 될 수 있을까?
제가 만든 것
두 가지 구성 요소입니다. 첫째는 sre-agent입니다. 이는 FastAPI + Gemini 기반의 도구 호출(Tool-calling) 지원 봇으로, 세 가지 도구를 가지고 있습니다 — 날씨 조회, 문서 검색, 그리고 제가 의도적으로 신뢰할 수 없게 만든 재고 확인(Inventory check) 도구입니다:
def check_inventory(sku: str) -> str:
with tracer.start_as_current_span("execute_tool check_inventory") as span:
span.set_attribute("gen_ai.tool.name", "check_inventory")
try:
latency = random.choice([0.05, 0.08, 0.1, 0.1, 2.4]) # 간헐적인 느린 경로 (occasional slow path)
time.sleep(latency)
if random.random() < 0.25:
raise RuntimeError(f"inventory-service timeout for sku={sku}")
...
except Exception as exc:
span.record_exception(exc)
span.set_status(Status(StatusCode.ERROR, str(exc)))
tool_call_errors.add(1, {"tool.name": "check_inventory"})
25% 실패율과 간헐적인 2.4초 지연이 있습니다. 실제적이고 보기 싫은 실패 모드가 없다면, "보세요, 관측 가능하잖아요!"라는 데모는 그저 연극일 뿐입니다.
둘째, SRE Sidekick: SigNoz의 MCP 서버에 연결하여 실행 시간에 사용 가능한 도구 목록을 나열하고, LLM이 진단 질문에 답하기 위해 어떤 도구를 호출할지 결정하도록 하는 완전히 분리된 스크립트입니다. 하드코딩된 쿼리는 없습니다. SigNoz에게 무엇을 물어봐야 할지 실제로 추론해야 합니다.
첫 번째 에이전트에 대한 모든 요청은 GenAI 시맨틱 컨벤션(semantic conventions)을 따르는 실제 OpenTelemetry 트레이스를 생성합니다:
invoke_agent support-agent
chat gemini-flash-lite-latest (LLM 호출이 도구 사용을 결정함)
execute_tool check_inventory (불안정한 도구)
chat gemini-flash-lite-latest (LLM이 최종 답변 생성)
모든 LLM 스팬에는 gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, 그리고 추정된 gen_ai.usage.cost_usd가 포함됩니다. 사용자 지정 메트릭은 도구 지연 시간과 오류 횟수를 추적합니다. 로그는 OTel SDK의 로깅 핸들러를 통해 trace_id와 자동으로 상관관계가 설정됩니다. 대시보드와 두 가지 경고 규칙(도구 오류율, P95 지연 시간)이 이 모든 것을 감시하며 — 저는 이를 SigNoz UI를 클릭해서 만든 것이 아니라 MCP 서버를 통해 직접 구축했습니다.
작동하지 않았던 네 가지 경우 (순서대로)
- Vercel에서 로컬 환경에서는 otel_setup에서 ...을 가져오는 sibling import가 조용히 깨졌습니다. agent/app.py에서는 작동했지만, Vercel에 배포하자 모든 요청이 다음으로 500 에러를 반환했습니다:
File "/var/task/agent/app.py", line 29, in
from otel_setup import (
ModuleNotFoundError: No module named 'otel_setup'
Vercel의 Python 런타임은 엔트리 파일(entry file)을 경로를 통해 직접 임포트합니다. 즉, 모든 로컬 스크립트가 암묵적으로 얻게 되는 '해당 파일의 디렉토리를 sys.path에 추가하는 기능'을 제공하지 않습니다. 해결 방법은 다음과 같습니다:
_HERE = Path(file).resolve().parent
if str(_HERE) not in sys.path:
sys.path.insert(0, str(_HERE))
단 세 줄의 코드지만, 이는 "로컬에서 작동함"과 "서버리스 함수(serverless function)로 작동함"이 서로 다른 주장이라는 사실 때문에 필요했습니다.
- 개발 환경에서는 멀쩡해 보이지만 운영 환경(production)에서 텔레메트리(Telemetry)가 사라질 수 있음
OpenTelemetry의 BatchSpanProcessor는 스팬(span)을 버퍼에 저장했다가 백그라운드 타이머(보통 몇 초마다 실행)에 맞춰 플러시(flush)합니다. 하지만 서버리스 플랫폼에서는 HTTP 응답이 전송되는 즉시 프로세스가 정지될 수 있으며, 이 경우 타이머가 실행되기도 전에 종료됩니다. 이로 인해 uvicorn --reload 환경에서는 트레이스(trace)가 잘 작동하다가, Vercel에서는 아무런 에러 없이 트레이스만 사라지는 현상이 발생했습니다. 저는 모든 요청의 끝에 명시적인 플러시(flush)를 추가했습니다:
@app.post("/chat")
def chat(req: ChatRequest):
try:
return ChatResponse(reply=run_agent(req.message), session_id=req.session_id)
finally:
flush_telemetry() # tracer/meter/logger 프로바이더의 force_flush() 호출
- 계정 이름에 포함된 "Admin"이 내가 만든 역할(role)로서의 Admin을 의미하지는 않음
SigNoz 서비스 계정(service account)을 생성하고 이름을 admin으로 지정했지만, 여전히 다음과 같은 MCP 호출 결과가 돌아왔습니다:
SigNoz API error: unexpected status 403: only editors/admins can access this resource
SigNoz의 최신 RBAC(역할 기반 액세스 제어) 모델은 서비스 계정을 생성하는 것과 해당 계정에 역할을 부여하는 것을 분리하여 처리합니다. 명시적으로 연결하지 않는 한 두 작업은 서로 무관합니다. 즉, 계정 이름은 권한 시스템에 아무런 영향을 주지 않았습니다. Settings → Service Accounts 메뉴에서 signoz-admin 역할을 연결하자마자, 코드 변경 없이 모든 읽기 및 쓰기 호출이 즉시 작동하기 시작했습니다. 기억해 둘 점: 설정을 잘못했다고 가정하기 전에 실제 에러 메시지를 먼저 읽으십시오.
- 에이전트의 자체 도구 목록이 토큰 예산(token budget)을 초과할 수 있습니다. SRE Sidekick의 첫 번째 실제 실행은 다섯 번의 합리적인 MCP 도구 호출을 수행한 후 답변 도중에 중단되었습니다:
openai.RateLimitError: Error code: 429 - Quota exceeded for metric:
generativelanguage.googleapis.com/generate_content_free_tier_input_token_count,
limit: 250000, model: gemini-3.5-flash-lite
원인은 대화 기록(conversation history)이 아니었습니다. 매 턴마다 SigNoz의 MCP 도구 41개 전체를 JSON 스키마 (JSON schema)를 포함하여 모델에게 전달했기 때문이었습니다. 그중 일부 스키마(특히 대시보드 및 알림 작성 관련)는 수백 줄에 달합니다. 다단계 추론 루프 (multi-step reasoning loop)의 매 단계마다 이를 다시 전송하는 것은 무료 티어 (free-tier) 할당량을 빠르게 소진시킵니다. 해결책 또한 더 나은 에이전트 설계였습니다. 도구 목록을 실제 작업에 필요한 범위로 제한하는 것입니다.
READ_TOOLS = {
"signoz_search_traces", "signoz_aggregate_traces", "signoz_search_logs",
"signoz_aggregate_logs", "signoz_list_services", "signoz_get_service_top_operations",
"signoz_query_metrics", "signoz_list_metrics", "signoz_list_alerts",
}
tool_specs = [spec(t) for t in tools if t.name in READ_TOOLS]
41개가 아닌 11개의 도구입니다. Sidekick의 다음 실행은 깔끔하게 완료되었으며 이 포스트 상단에 있는 답변을 생성했습니다.
과거의 나에게 해주고 싶은 말
초기에 배포하세요, 설령 거친 버전일지라도. 이 네 가지 버그 중 세 가지는 프로덕션 (Production) 환경에서만 발생하며, 저는 남은 시간이 0인 상태보다는 2시간이라도 남아있을 때 이 버그들을 마주하고 싶습니다.
MCP 서버의 도구 (Tool) 목록은 공짜가 아닙니다. 만약 방대한 도구 표면 (Tool surface)을 대상으로 에이전트 (Agent)를 구축하고 있다면, 모델이 "혼란스러워한다"고 가정하기 전에 범위를 좁히세요. 모델이 단순히 자신의 도구 정의 (Tool definitions)로 인해 컨텍스트 예산 (Context budget)을 소진해버린 것일 수도 있습니다.
권한 오류 (Permission errors)는 거의 항상 말 그대로의 의미를 가집니다. 403: 권한 없음 (not authorized)은 권한이 없다는 뜻이었지, 제 요청의 버그가 아니었습니다.
의도적으로 망가뜨린 코드 경로 (저의 불안정한 check_inventory)는 여러분의 관측성 (Observability) 설정이 실제로 작동하는지 테스트하는 데 있어 백 개의 깨끗한 코드 경로보다 더 가치 있습니다.
직접 시도해보세요
레포지토리 (Repo): https://github.com/23f2001033/agents-of-signoz
라이브 (Live): https://agents-of-signoz.vercel.app — {
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기