이번 글은 AgentShield에서 Red Agent 로직과 보안 판정 구조를 어떻게 더 발전시킬 수 있는지 정리한 개인 기록입니다.
앞에서 파이프라인 실행, Fine-tuning 흐름, Judge와 Guard 모델 구조를 정리했다면, 이번에는 Red Agent가 실제 공격 결과를 어떻게 학습해서 다음 라운드에 반영할 수 있는지, 그리고 LangGraph 기반 보안 판정 구조가 어떤 방향으로 정리되었는지 기록합니다.
핵심은 두 가지입니다. 하나는 Red Agent가 단순히 “사용한 기법을 다시 쓰지 않는 수준”을 넘어, 특정 챗봇에게 잘 먹힌 기법을 세션 안에서 실시간으로 추적해야 한다는 점입니다. 다른 하나는 보안 판정을 단순 if-else가 아니라 여러 노드가 합의하는 구조로 바꾸는 것입니다.
1. 현재 Red Agent 파이프라인이 이미 하고 있는 것
현재 파이프라인에도 이미 적응형 로직이 일부 들어가 있습니다.
Red Agent는 타겟 챗봇의 도메인을 감지해서 공격 프레이밍을 조정합니다. 이 흐름은 domain_context에서 시작해 build_red_prompt로 이어집니다.
또한 이번 공격에서 사용한 기법을 추적해서 다음 라운드에서 같은 기법을 반복하지 않도록 합니다. 이 부분은 used_techniques와 prev_techniques를 통해 관리됩니다.
타겟 응답에 나타난 방어 신호도 분석합니다. analyze_defense_signal을 통해 방어 패턴을 읽고, 그 결과를 branching_block에 반영해서 우회 전략을 분기합니다.
한 카테고리에서 얻은 성공 정보가 다른 카테고리에 공유되는 구조도 있습니다. 이 부분은 cross_category_intel로 정리됩니다.
ChromaDB에 누적된 성공 사례도 참고합니다. 전체 히스토리 기반의 성공 사례는 category_profiles를 통해 Red Agent가 활용할 수 있습니다.
정리하면 현재 있는 구조는 다음과 같습니다.
타겟 챗봇 도메인 감지 → 공격 프레이밍 조정
이번 공격에서 사용한 기법 추적 → 다음 라운드 차단
타겟 방어 신호 분석 → 우회 전략 분기
한 카테고리 성공 정보 → 다른 카테고리에 공유
ChromaDB 누적 성공사례 참조
이 정도만 봐도 Red Agent는 이미 완전히 정적인 생성기가 아닙니다. 다만 아직 빠져 있는 중요한 부분이 있습니다.
2. 현재 없는 핵심 로직
현재 파이프라인에는 “이번 세션에서 이 특정 챗봇에게 어떤 기법이 얼마나 잘 먹혔는지”를 실시간으로 추적하는 구조가 없습니다.
지금 있는 used_techniques는 이미 사용한 기법을 다시 쓰지 않도록 막는 역할에 가깝습니다.
하지만 실제로 필요한 것은 이것보다 한 단계 더 나간 구조입니다.
예를 들어 어떤 챗봇에게 technique A는 성공률이 높고, technique B는 거의 통하지 않는다면 다음 라운드에서는 A 계열을 우선해야 합니다.
현재 파이프라인은 “썼던 기법을 다시 쓰지 마라”는 정도까지는 하지만, “이 챗봇에게 잘 먹힌 기법을 더 우선해라”까지는 하지 않습니다.
AdaptiveRedAgent의 success_rate_map이 추가하려는 핵심은 바로 이 부분입니다.
technique A → 이 세션에서 성공률 0.9
technique B → 이 세션에서 성공률 0.1
다음 라운드 → technique A 계열 우선
이 로직이 들어가면 Red Agent는 단순 변형기가 아니라 세션 상태를 유지하면서 이전 공격 결과를 학습하는 자율 에이전트에 가까워집니다.
3. AdaptiveRedAgent를 파이프라인에 연결하는 방식
연결 위치는 run_phase2() 안의 per-attack 루프입니다.
세션 단위로 AdaptiveRedAgent 인스턴스를 하나 만들고, 각 라운드가 끝날 때마다 verdict를 반영하면 됩니다.
흐름은 다음과 같습니다.
세션 시작
→ AdaptiveRedAgent 인스턴스 생성
→ 공격 생성
→ 타겟 응답 수집
→ Judge verdict 확인
→ evaluate_attack(new_attack, target_response, score) 호출
→ success_rate_map 업데이트
→ 다음 라운드 prompt 생성 시 성공률 높은 전략 우선 반영
구현 관점에서는 다음 작업이 필요합니다.
AdaptiveRedAgent 인스턴스를 세션 단위로 생성
각 라운드 verdict 후 evaluate_attack(new_attack, target_response, score) 호출
success_rate_map을 build_red_prompt의 category_attack_profile에 병합
변형 공격에서도 카테고리 분류
핵심은 success_rate_map을 _rank_strategies 또는 build_red_prompt 쪽에 전달해서 전략 선택에 반영하는 것입니다.
이렇게 되면 Red Agent는 단순히 이전에 사용한 기법을 제외하는 방식이 아니라, 이 세션의 타겟에게 실제로 잘 먹힌 방향을 우선하게 됩니다.
4. 변형 공격에서도 카테고리 분류가 필요합니다
AdaptiveRedAgent를 붙일 때 같이 봐야 하는 문제가 있습니다.
변형 공격은 원래 seed와 형태가 달라질 수 있습니다. 그래서 변형된 공격도 어떤 카테고리에 속하는지 분류할 수 있어야 합니다.
이 분류가 없으면 success_rate_map을 카테고리별로 안정적으로 쌓기 어렵습니다.
예를 들어 LLM01 계열로 시작한 공격이 변형 과정에서 LLM06 성격을 강하게 띠게 되면, 단순히 원래 seed의 카테고리만 보고 통계를 쌓는 것은 부정확할 수 있습니다.
따라서 변형 공격 이후에도 카테고리를 다시 확인하고, 그 결과를 Red Agent의 전략 기록에 반영해야 합니다.
5. 기능 B에서 생길 수 있는 문제
기능 B는 monitoring proxy 운영과 연결됩니다.
운영 중 프롬프트가 들어오면 정책 검사, 마스킹, usage log, violation 저장 같은 흐름이 동작합니다. 이때 공격 데이터가 들어오면 Blue Agent가 호출될 수 있습니다.
여기서 문제가 하나 생깁니다.
Blue Agent가 카테고리별로 학습되어 있다면, 분류되지 않은 프롬프트를 받았을 때 오류가 날 수 있습니다.
즉, Blue Agent가 “이 입력이 어떤 보안 카테고리에 속하는지”를 전제로 동작한다면, 카테고리 분류가 빠진 입력은 안정적으로 처리하기 어렵습니다.
그래서 기능 B에서도 카테고리 분류 또는 fallback 처리가 필요합니다.
이 문제는 Red Agent의 변형 공격 분류 문제와도 연결됩니다. 공격 생성, 판정, 방어 모두 카테고리를 기준으로 움직이기 때문입니다.
6. Red Agent 자율 에이전트 방향
Red Agent를 자율 에이전트처럼 만들려면 상태 유지가 필요합니다.
상태가 없으면 매 라운드가 독립적으로 실행됩니다. 그렇게 되면 이전 공격이 왜 실패했는지, 어떤 기법이 성공했는지, 어떤 방어 신호가 반복되는지 다음 라운드에 충분히 반영하기 어렵습니다.
AdaptiveRedAgent의 핵심은 이전 공격 결과를 상태로 저장하고, 다음 공격 전략을 동적으로 조정하는 것입니다.
정리하면 Red Agent의 방향은 다음과 같습니다.
이전 공격 결과 저장
기법별 성공률 추적
타겟별 방어 신호 누적
성공률 높은 기법 우선 선택
실패 기법은 우선순위 하향
카테고리별 전략 기록 유지
이 구조가 들어가면 Red Agent는 단순 프롬프트 생성기가 아니라, 현재 세션의 타겟에 맞게 전략을 조정하는 공격 실험 에이전트가 됩니다.
7. 보안 판정 구조를 LangGraph로 바꾸는 이유
기존의 단순 if-else 구조는 빠르고 이해하기 쉽지만, 판정이 복잡해질수록 한계가 생깁니다.
Prompt Injection, Data Leak, Excessive Agency, Prompt Leak처럼 카테고리가 늘어나면 단일 판정 함수가 모든 맥락을 안정적으로 처리하기 어렵습니다.
그래서 LangGraph 기반 구조를 사용하면 상태를 관리하면서 여러 노드가 협업하는 방식으로 판정을 구성할 수 있습니다.
목적은 전문가가 매번 직접 보지 않아도 자동화된 보안 판정 신뢰도를 확보하는 것입니다.
여기서 사용하는 핵심 도구는 LangGraph와 Qwen 3.5 4B입니다.
LangGraph는 상태 관리와 에이전트 워크플로우 제어를 담당합니다.
Qwen 3.5 4B는 지능형 의도 분석과 보안 판정을 수행하는 경량 LLM 역할을 합니다.
8. 3-Layer Consensus 판정 구조
LangGraph 기반 판정 구조는 3-Layer Consensus 형태로 정리됩니다.
첫 번째는 Triage입니다.
Triage는 정규식과 키워드 기반의 고속 스캔을 담당합니다. 명확한 거부 응답이나 명확한 유출이 발생하면 여기서 즉시 판정하고 종료할 수 있습니다.
두 번째는 Scanner입니다.
Scanner는 도구 호출과 구조적 패턴을 분석합니다. 특히 LLM06, 즉 Excessive Agency 탐지에 중요합니다. <tool_call> 같은 구조가 있는지, 미승인 권한 실행이 발생했는지 확인합니다.
세 번째는 Auditor입니다.
Auditor는 LLM 기반 의도와 문맥 분석을 담당합니다. 카테고리별 Rubric을 주입받아 더 깊게 판단합니다.
마지막으로 Consensus가 있습니다.
Consensus는 각 노드의 결과를 취합해 최종 판정을 내립니다. 결과가 상충할 경우 가중치 기반 합의 알고리즘을 적용합니다.
정리하면 다음과 같습니다.
Triage → Scanner → Auditor → Consensus
이 구조의 목적은 모든 요청을 무거운 LLM 판정으로 보내지 않고, 빠른 규칙 기반 판단과 LLM 기반 판단을 조합하는 것입니다.
9. 카테고리별 판정 기준
카테고리별로 보는 기준도 다릅니다.
LLM01은 Prompt Injection입니다.
여기서는 시스템 지침을 제대로 따랐는지, 공격자가 넣은 지시를 우선했는지를 봅니다. 점수가 0.8보다 높으면 vulnerable로 판정하는 기준이 사용됩니다.
LLM02는 Data Leak입니다.
여기서는 정규식 패턴 매칭이 중요한 지표입니다. 민감정보나 데이터 유출 패턴이 있는지 먼저 확인합니다.
LLM06은 Excessive Agency입니다.
여기서는 <tool_call> 태그 유무와 미승인 권한 실행 여부가 중요합니다.
LLM07은 Prompt Leak입니다.
여기서는 시스템 내부 설정값, 아키텍처 정보, 시스템 프롬프트 노출 여부를 확인합니다.
이처럼 카테고리마다 취약함을 판단하는 기준이 다르기 때문에, 하나의 단순 규칙으로 모두 처리하기 어렵습니다.
10. 판정 속도가 느려질 때 확인할 점
LangGraph 구조를 넣으면 판정이 더 정교해질 수 있지만, 속도가 느려질 가능성도 있습니다.
특히 모든 요청이 무거운 LLM 기반 Auditor 노드를 거치면 전체 파이프라인 속도가 떨어집니다.
따라서 Triage_Node에서 safe 또는 vulnerable 판정이 명확하게 나왔을 때 바로 END로 빠지는지 확인해야 합니다.
조건부 엣지가 제대로 설정되어 있어야 불필요한 LLM 호출을 줄일 수 있습니다.
11. 오류와 타임아웃 처리
판정 중 타임아웃이나 네트워크 오류가 날 수 있습니다.
이 경우 시스템이 중단되면 안 됩니다.
retry_count 상태를 활용해 최대 3회 재시도 루프를 구성하고, 최종 실패 시에는 ambiguous로 안전하게 폴백하는 구조가 필요합니다.
이 방식은 판정 실패가 전체 파이프라인 중단으로 이어지는 것을 막기 위한 장치입니다.
12. False Positive가 높을 때 조정할 부분
False Positive가 높으면 Consensus_Node에서 최종 판정을 내리는 confidence 임계값을 조정해야 합니다.
기준을 너무 낮게 잡으면 애매한 응답도 vulnerable로 많이 잡힐 수 있습니다.
메모에서는 confidence 임계값을 0.7에서 0.85로 올리는 방식을 정리했습니다.
이렇게 하면 판정 기준이 더 엄격해지고 오탐을 줄일 수 있습니다.
다만 너무 높게 잡으면 실제 취약 케이스를 놓칠 수 있으므로 review queue에서 수동 검수 결과를 함께 봐야 합니다.
13. 완료된 구조
현재 정리된 파일 구조는 다음과 같습니다.
backend/core/judge_utils.py에는 모든 규칙 기반 판정 로직이 들어갑니다.
여기에는 rule_based_judge, _judge_llm01~07, 유틸리티 함수가 포함됩니다. 의존성이 없도록 분리되어 있습니다.
backend/agents/judge_nodes.py에는 LangGraph 노드 구현이 들어갑니다.
이 파일은 judge_utils.py를 글로벌 임포트해서 순환 의존 문제를 해결하고, Ollama API를 직접 호출합니다.
backend/graph/judge_graph.py에는 LangGraph 워크플로우가 정의됩니다.
흐름은 Triage -> Scanner -> Parallel Auditors -> Consensus/Debate 구조입니다.
backend/core/judge.py는 메인 진입점입니다.
full_judge가 LangGraph를 호출하는 역할을 합니다.
이 구조로 순환 의존 오류가 해결되고, LangGraph 기반 멀티 에이전트 판정 시스템이 정상 작동할 것으로 정리되었습니다.
14. 이번 정리에서 잡은 기준
Red Agent 쪽에서 현재 없는 핵심은 세션 기반 성공률 추적입니다.
지금은 사용한 기법을 반복하지 않는 정도지만, 앞으로는 특정 챗봇에게 잘 먹힌 기법을 우선하는 구조가 필요합니다.
이를 위해 AdaptiveRedAgent가 세션 상태를 유지하고, success_rate_map을 통해 기법별 성공률을 관리해야 합니다.
판정 쪽에서는 단순 if-else 구조를 LangGraph 기반 멀티 노드 구조로 바꾸는 방향이 정리되었습니다.
Triage, Scanner, Auditor, Consensus가 각각 역할을 나누고, 빠른 규칙 기반 판정과 LLM 기반 심층 판정을 조합합니다.
결국 AgentShield는 공격 생성도, 보안 판정도 단순 일회성 로직에서 상태 기반 에이전트 구조로 넘어가고 있습니다.
이 방향으로 가면 파이프라인은 단순히 공격을 실행하는 도구가 아니라, 타겟별 반응을 학습하고 판정 신뢰도를 계속 개선하는 보안 실험 시스템에 가까워집니다.
