AI 에이전트 연결 (Tools & Guardrails)
목표
- Chatbot에 로그 파일을 업로드하면 Agent가 적절한 분석기 Tool을 골라 호출하고 유의미한 답변을 반환하도록 연결
- 민감정보가 LLM으로 흘러가지 않도록 Guardrail(가드레일) 계층 추가
핵심 흐름:
사용자 요청 → Agent 판단 → 적절한 로그 분석기 Tool 호출 → 분석 결과 반환 → LLM이 설명 생성
LLM은 직접 로그를 분석하지 않는다. 정량 분석은 Tool이, 설명/요약은 LLM이 담당.
1. Tool
LLM이 사용하는 Function이다. LLM에게 명시적으로 외부 코드나 API에 맡겨야 하는 작업을 호출할 수 있게 만들어 준다. 해당 프로젝트에선 로그 분석기 호출 기능을 담당하고 있다.
적절한 분석기 Tool 호출
왜 Tool 기반 구조인가
일반 Chatbot(사용자 입력 → LLM → 답변) 구조의 한계:
| 문제점 | 내용 |
|---|---|
| 계산 정확도 부족 | Full GC 횟수, 평균 Pause Time, Heap retained size 등 정량 계산은 LLM이 부정확 |
| Hallucination | 실제 분석 없이 그럴듯한 설명을 만들어낼 수 있음 |
| 비용/속도 | 로그 전체를 LLM에 넘기면 토큰 비용 증가, Context 초과, 응답 지연 |
목표 동작 흐름
[사용자] "이 로그 분석해줘" + 파일
↓
[Chatbot UI] 파일 업로드 → file_id 발급
↓
[Agent] file_id로 파일 일부 읽기
↓
[로그 타입 판별] Full GC / nid= / HTTP 500 / OOM ...
↓
[Tool 선택] gc / thread / apache / heap analyzer
↓
[Tool.run(content)] 구조화 결과(JSON) 반환
↓
[LLM] 결과를 자연어로 설명
↓
[Chatbot] 최종 응답 출력
로그 타입 판별 규칙(예시)
| 패턴 | 로그 타입 |
|---|---|
Full GC | GC Log |
nid= / prio= | Thread Dump |
HTTP Status 500 | Apache/Tomcat |
java.lang.OutOfMemoryError | JVM |
MAT Leak Suspect | Heap Dump Result |
초기에는 Rule-based로 시작.
TOOLS = {
"gc": gc_log_analyzer,
"thread": thread_dump_analyzer,
"apache": apache_log_analyzer,
"heap": heap_dump_analyzer,
}
if "Full GC" in content:
tool = TOOLS["gc"]
elif "nid=" in content:
tool = TOOLS["thread"]Tool 결과 형식 (예시)
{
"tool_name": "gc_log_analyzer",
"full_gc_count": 15,
"avg_pause_ms": 3200,
"risk_level": "HIGH"
}→ LLM에는 이 구조화 데이터만 넘겨서 “Full GC가 비정상적으로 많이 발생, 메모리 압박 가능성” 같은 설명을 생성.
작업 규칙 (반드시 준수)
routers/는 수정하지 않는다.models/schemas.py,upload_schemas.py의 공통 응답 구조를 임의 변경하지 않는다.- 로그 타입 식별 규칙은 각 분석기 디렉터리의
signatures.py에만 추가한다. - 분석기 호출 연결은
services/tool_router.py에서만 관리한다. - 개별 분석 로직은
services/{본인분석기}_analyzer/내부에만 작성한다. - 분석 결과는 반드시
AnalyzeLogResponse또는ToolResult로 반환한다. - 원본 로그 전문은 응답에 포함하지 않는다.
- 150MB 초과 파일은 분석 전에 거부한다.
설계 원칙
| 원칙 | 내용 |
|---|---|
| 1 | LLM이 직접 로그를 계산하지 않는다 |
| 2 | Tool은 구조화 데이터(JSON)를 반환한다 |
| 3 | Agent의 핵심 책임은 Tool 선택이다 |
| 4 | LLM은 설명·요약 역할만 담당한다 |
Tool
현재 등록된 Tool은 다음과 같으며 프로세스는 아래와 같다.
- analyze_gc_log
- analyze_tomcat_log
- analyze_apache_log
- analyze_java_application_log
- analyze_thread_dump_log

이후, 실제 로그 분석 요청 시 Log Type에 따라 도구를 선택하는 것을 확인할 수 있다.

2. Guardrail / 보안정보 차단
GuardRail을 이용하여 LLM에게 제공 및 반환되는 정보들을 제한할 수 있다. 아래의 아키텍처와 같이 가드레일을 세 곳에서 진행한다.

문맥 관련해서 LLM이 적용되어야 한다고 생각했는데 내가 생각했던 가드레일의 내용과는 달랐다.
- 내가 생각한 가드레일 > LLM에게 이거는 하지마 라고 제약 걸기
- 실제 가드레일 > 검증, 검증, 검증
현재는 문맥 관련 내용에 대해서 검증할 수 없음. 즉, regex 기반으로만 가능함. 문맥 관련 검증을 하기 위해서는 RAG와 마찬가지로 전용 LLM을 추가하여 설정할 수 있음.
왜 필요한가
운영 환경 로그에는 다음 같은 민감정보가 섞일 수 있음:
- 비밀번호, JWT Token, Session ID, API Key
- DB Connection URL, 인증 Header, Cookie
- 이메일, 전화번호, 주민번호, 내부 IP
이걸 그대로 LLM에 넘기면 민감정보 유출 / 보안 정책 위반 / 개인정보 노출.
추가로 lena-ts-log-analysis 특성상 다음 위험도 함께 고려:
| 특징 | 위험 |
|---|---|
| 대용량 로그 처리 | OOM, 디스크 고갈 |
| Agent 기반 Tool 호출 | 무한 루프, 중복 호출 |
| 파일 업로드 | 악성 파일, zip bomb |
| AI 응답 생성 | Hallucination |
| 외부 시스템 접근 | SSRF, 내부망 접근 |
| 자동 분석 | 오탐/과탐 |
핵심 원칙
LLM은 보안 장비가 아니다. “민감정보는 무시하세요” 같은 프롬프트만으로는 절대 안 됨.
| 잘못된 방식 | 올바른 방식 |
|---|---|
| 로그 전체 → LLM → “민감정보는 무시” | 로그 전체 → Guardrail로 마스킹 → 안전한 데이터만 LLM 전달 |
권장 Guardrail 위치 (7단계)
[1] 입력 가드레일
↓
[2] 파일 가드레일
↓
[3] Agent 가드레일
↓
[4] Tool 실행 가드레일
↓
[5] AI 응답 가드레일
↓
[6] 운영/리소스 가드레일
↓
[7] 감사(Audit) 가드레일
마스킹 대상 & 예시
| 대상 | 입력 | 출력 |
|---|---|---|
| Password | password=admin123 | password=[REDACTED] |
| JWT | Authorization: Bearer eyJhbGc... | Authorization: Bearer [REDACTED_JWT] |
| Session ID | JSESSIONID=ABCD1234 | JSESSIONID=[REDACTED] |
| API Key | api_key=sk-xxxx | api_key=[REDACTED] |
| DB URL | jdbc:mysql://admin:pass@10.0.0.5/prod | jdbc:mysql://[REDACTED]/prod |
| 이메일 | test@example.com | [REDACTED_EMAIL] |
| 전화번호 | 010-1234-5678 | [REDACTED_PHONE] |
| 주민번호 | 900101-1234567 | [REDACTED_RRN] |
초기 구현은 정규식 기반(Rule-based) 으로 충분.
가장 안전한 구조
로그 원문
→ Tool 분석
→ 구조화 결과(JSON)
→ Guardrail
→ LLM
원본 로그를 LLM에 넘기지 말고, Tool 결과(JSON)만 전달.
raw_text = load_log()
masked = apply_guardrail(raw_text)
llm_input = {
"summary": analysis_summary, # Tool 결과
"masked_preview": masked[:1000], # 꼭 필요한 경우만 일부
}LLM 입력 예시:
{
"risk_level": "HIGH",
"patterns": ["FULL_GC"]
}자주 하는 실수
| 실수 | 내용 |
|---|---|
| 1 | 로그 전체를 그대로 LLM에 전달 |
| 2 | 프롬프트만으로 보안 해결 시도 (“민감정보는 저장하지 마세요”) |
| 3 | Guardrail을 응답 단계에서만 적용 (입력 단계 차단이 더 중요) |
2-1. 적용 정책
2-1. Input
사용자 입력을 LLM 호출 전에 검사한다.
현재는 정규식 기반으로 다음 항목을 확인한다.
- 로그 분석과 무관한 일반 대화인지
- 지원하지 않는 로그 도메인인지
- 지원 로그 타입에 대한 분석 요청인지
- 분석에 필요한 file_id, log_content, 분석 결과 context가 있는지
차단 예시는 다음과 같다. 아래 요청은 LLM 호출 전에 차단된다.
안녕?
오늘 날씨 어때?
쿠버네티스 로그 분석해줘
Docker 로그 분석해줘
반대로 아래 요청은 로그 분석 범위로 판단한다.
GC 로그 분석해줘
Tomcat 로그 원인 알려줘
Apache access 로그에서 500 에러 원인 분석해줘
방금 분석 결과에서 가장 위험한 신호가 뭐야?
단, 지원 로그 타입 요청이라도 분석할 파일이나 로그 본문이 없으면 LLM을 호출하지 않고 파일 첨부 안내를 반환한다.
한 줄 요약
- AI Agent 시스템에서 LLM은 만능 분석기가 아니라, Tool 결과를 설명하는 보조 계층이다.
- 실제 로그 분석은 Tool이, 민감정보 차단은 Guardrail이, LLM은 최소 정보만 받아 설명을 생성한다.