AI 에이전트: 3가지 필수 패턴 마스터하기 (Reflexive). 3부 중 3
Source: Dev.to
이 패턴들의 코드는 GitHub에서 확인할 수 있습니다.
Repo
반사 패턴 – 생각할 시간이 없을 때
*Article 2 (ReAct)*에서 우리는 에이전트를 꼼꼼한 **“조사관”**으로 바꾸었습니다.
에이전트는 앉아서 분석하고, 계획하고, 구글 검색을 한 뒤 답변합니다.
복잡한 작업에는 아주 잘 맞지만, 현실 세계에서는 큰 버그가 있습니다: 느리다는 점.
이렇게 생각해 보세요: 뜨거운 스토브에 손을 대면 뇌가 토론을 시작하지 않습니다:
“음, 온도가 200 °C인 걸 감지했어, 이건 단백질 변성을 일으킬 거야, 이두근을 움직이는 게 좋겠어…”
하하, 그렇지 않죠. 척수신경이 명령을 내리고 통증을 느끼기 전에 손을 떼게 합니다.
Reflexive Pattern(때때로 Semantic Router라 불림)은 바로 그와 같습니다: 인공지능의 “반사 행동”.
사용 사례: 보안 센티넬
실시간으로 서버 로그를 읽는 시스템을 상상해 보세요. 수천 건의 정상 방문 중에 악의적인 요청이 나타납니다:
GET /search?q=' OR 1=1;--
여기에 ReAct 에이전트를 사용한다면, 당신은 곧바로 위험에 처합니다. 에이전트는 다음과 같이 생각할 것입니다:
“와, 이상한 패턴이네.
SQL Injection이 뭔지 검색 도구를 사용해 보겠어. 아, 위험하군. 차단 진행.”
에이전트가 “생각”을 마치는 데(10‑15 초) 걸리는 동안, 데이터베이스는 이미 다크웹에 유출되어 있습니다.
여기서 Reflexive Agent가 빛을 발합니다
| 자극 | 반사 행동 | 시간 |
|---|---|---|
| 악의적인 문자열을 감지 | block_ip() 실행 | 1초 미만 |
예시 Reflex 행동 (Python)
def block_ip(ip: str, reason: str) -> str:
"""악의적인 IP 주소를 즉시 차단합니다."""
msg = f"⛔ BLOCKING IP [{ip}]: {reason}"
logger.warning(msg)
return msg
def escalate_to_admin(log_id: str, severity: str) -> str:
"""중대한 문제를 인간 관리자에게 에스컬레이션합니다."""
msg = f"⚠️ ADMIN ALERT: Log [{log_id}] - Severity [{severity}]"
logger.critical(msg)
return msg
def log_normal_traffic(source: str) -> str:
"""정상적이고 안전한 트래픽을 기록합니다."""
msg = f"✅ Normal traffic from [{source}]"
logger.info(msg)
return msg
# ----------------------------------------------------------------------
# 4. Agno Agent Configuration (Reflexive Pattern)
# ----------------------------------------------------------------------
model_id = os.getenv("BASE_MODEL", "gpt-4o-mini")
agent = Agent(
model=OpenAIChat(id=model_id),
tools=[block_ip, escalate_to_admin, log_normal_traffic],
instructions=[
"당신은 자동화된 보안 시스템(Reflexive Pattern)입니다.",
"당신의 작업은 들어오는 로그를 분류하고 해당 도구를 **즉시** 실행하는 것입니다.",
"행동 규칙:",
"- SQL Injection, XSS, 알려진 공격을 감지하면 → `block_ip` 사용.",
"- 서버 오류(500), 서비스 다운, 타임아웃을 감지하면 → `escalate_to_admin` 사용.",
"- 트래픽이 정상적이거나 로그인 성공, 일반 탐색이라면 → `log_normal_traffic` 사용.",
"결정을 설명하지 마세요. 인사하지 마세요. 자극에 바로 도구를 실행하세요.",
"로그를 처리하고 실행을 종료하세요."
]
)
# ----------------------------------------------------------------------
# 5. Flow Simulation (The Stream)
# ----------------------------------------------------------------------
def main():
logger.info("Starting Security Sentinel Agent (Reflexive)...")
print("--- Security Sentinel - Reflexive Pattern ---")
# 시뮬레이션 로그
logs = [
"User 'admin' logged in successfully from 192.168.1.10",
"GET /search?q=' OR 1=1;-- (SQL Injection attempt from 203.0.113.5)",
"Service 'PaymentGateway' timed out after 3000ms (Error 500)",
"User 'jdoe' updated profile picture",
"alert('hacked') sent via form from 88.22.11.44",
"DB_ERROR: Connection pool exhausted (LogID: 4452)",
"Bot crawler identified: Googlebot/2.1 from 66.249.66.1",
"Multiple failed login attempts for user 'sys'..."
# ... 추가 로그를 여기서 더 넣을 수 있습니다
]
for entry in logs:
# 에이전트는 각 로그 항목을 자극으로 받아 즉시 반응합니다.
response = agent.run(entry)
print(response)
if __name__ == "__main__":
main()
위 코드는 순수 Reflexive 워크플로우를 보여줍니다: 에이전트가 로그 라인을 받으면 하드코딩된 규칙과 매칭하고 즉시 적절한 도구를 트리거합니다—사고 과정 없이, 루프 없이, 1초 미만의 응답 시간으로.
def main():
logs = [
"admin' from 45.33.22.11",
"HealthCheck: All systems operational - latency 12ms",
"Unauthorized access attempt to /etc/passwd from 172.16.0.50"
]
print(f"\nProcessing {len(lo")
Source:
gs)} logs in the 'stream'...\n")
for i, log_entry in enumerate(logs, 1):
try:
print(f"[{i}] Stimulus: {log_entry}")
logger.info(f"Processing log {i}: {log_entry}")
# In reflexive mode, we expect the agent to execute the tool immediately.
# We use show_tool_calls=True to demonstrate the action.
agent.print_response(log_entry, show_tool_calls=True)
print("-" * 50)
except Exception as e:
logger.error(f"Error processing log {i}: {str(e)}")
print(f"An error occurred in event {i}: {e}")
if __name__ == "__main__":
main()
제한적인 지시 (부정적 제약)
시스템 프롬프트(instructions)에서 에이전트가 생각하거나 대화하는 것을 명시적으로 금지합니다:
- 설명하지 마세요
- 그냥 실행하세요
에이전트는 도구를 실행하는 것만 하도록 프로그래밍되었습니다.
직접 매핑
피드백 루프가 없습니다. 흐름은 선형입니다:
Incoming Log → Classification → Tool Execution
모델 선택
gpt-4o-mini가 구성되었습니다.- 더 작고 빠른 모델을 사용하면 지연 시간과 처리량을 우선시합니다.
이 패턴이 멋진 이유 (장점)
- 터무니없는 속도 (최소 지연): “생각” 텍스트를 생성하지 않음으로써 응답이 거의 즉시 이루어집니다.
- 높은 처리량: 분당 수천 개의 이메일, 실시간 채팅, 혹은 모니터링 알림을 처리하는 데 완벽합니다.
- 예측 가능 (결정론): “창의성”을 제거하면 에이전트가 고전 스크립트처럼 동작합니다—X가 주어지면 항상 Y를 수행합니다.
- 비용 효율적: 출력 토큰이 적고 모델이 작아지면 API 비용이 낮아집니다.
Where It Fails (Cons)
- Goldfish Memory (Contextual Blindness): 에이전트는 현재 입력에만 반응합니다. 공격이 10분에 걸쳐 세 단계로 나뉘어 진행되면, 연결점을 찾지 못합니다.
- Stubborn (Rigidity): 규칙에 포함되지 않은 모호한 입력은 실패하거나 잘못된 분류를 초래할 수 있습니다.
- Black Box: ReAct와 달리, 행동이 왜 수행됐는지 설명하는 “Thought” 로그가 없습니다.
개발자를 위한 비교
| 특징 | ReAct (레벨 2) | Reflexive (레벨 3) |
|---|---|---|
| 비유 | 셜록 홈즈 | 클럽 보안 요원 |
| 우선순위 | 품질 및 추론 | 속도 및 양 |
| 루프 | 예 (생각‑행동‑관찰) | 아니오 (발사 후 잊음) |
| 이상적인 모델 | 최고 모델 (GPT‑4o, Claude) | 경량 모델 (Mini, Haiku) |
Source: …
현장 팁
1. “금지 망치”를 조심하라
이 에이전트는 먼저 행동하고 나중에 질문하기 때문에 오탐이 흔합니다.
조언: 100 % 확신이 없으면 delete_account() 대신 flag_for_review() 액션을 사용하세요.
2. 프롬프트를 엄격하게 (부정적 제약)
- 잘못된 프롬프트: “이 텍스트를 분류하세요.”
- 올바른 프롬프트: “이 텍스트를 분류하세요. DO NOT 이유를 설명하세요. DO NOT 서론을 생성하세요. JSON만 반환하세요.”
3. 하이브리드 아키텍처
Reflexive 패턴은 **“보병”**에 해당합니다. 전선에 배치해 약 80 %의 쉬운 잡음을 걸러냅니다.
만약 이해하지 못하거나 모호한 상황을 만나면, 에스컬레이션하여 더 똑똑하고 비용이 많이 드는 ReAct 에이전트에게 티켓을 넘겨 심층 조사를 진행합니다. 이렇게 하면 양쪽 장점을 모두 활용할 수 있습니다.
행복한 코딩 되세요! 🤖
