도구가 달린 챗봇에서 AI 에이전트로: 빠진 제어 계층

실용적인 제어 계층을 통해 AI 에이전트가 권한, 상태, 복구, 중대한 결과를 낳는 작업을 안전하게 관리할 수 있습니다.

핵심 요약

  • 더 나은 에이전트 성능을 추구하는 대부분의 AI 팀은 더 큰 컨텍스트 윈도우, 더 많은 문서, 더 정교한 프롬프트라는 똑같은 수단을 택한다. 이 글은 그런 접근 자체가 잘못된 본능이라고 주장한다. 부족한 것은 더 많은 정보가 아니다. 제어다. 잘 설계된 제어 계층이 데모에서만 작동하는 에이전트와 프로덕션에서도 작동하는 에이전트를 가른다.

  • AI 에이전트에 더 큰 메모리, 더 많은 문서, 더 긴 컨텍스트 윈도우를 제공해도 더 똑똑해지지 않는다. 속도가 느려지고 비용만 늘어날 뿐이다. 진정한 개선은 모든 것을 한꺼번에 소비하는 대신, 에이전트가 필요한 순간에 필요한 것을 선택하도록 가르칠 때 이루어진다.

  • 신뢰성은 모델이 아니라 루프에서 나온다. 데모에서는 인상적이지만 프로덕션에서는 무너지는 에이전트와 실제로 견고하게 작동하는 에이전트의 차이는 AI의 품질이 아니라 시스템이 스스로 작업을 검사하는지에 있다. 매 단계에서 계획하고, 실행하고, 관찰하고, 검증하는 에이전트는 틀린 답을 확신에 차서 내놓는 대신 스스로 오류를 찾아낸다.

  • 오늘날 대부분의 AI 에이전트는 사실상 단계만 더해진 챗봇이다. 제대로 진행 중인지, 언제 멈춰야 하는지, 언제 다른 방법을 시도해야 하는지 판단할 장치가 없다. 명확한 성공 기준, 구조화된 상태, 검증 검사로 구성된 적절한 제어 계층을 추가해야 에이전트 모양의 물체가 실제로 신뢰할 수 있는 시스템으로 바뀐다.


어제 점심으로 무엇을 먹었나요?

아마 ‘어제+점심’에 해당하는 기억이 나올 때까지 평생의 기억을 전부 재생하지는 않았을 것이다. 그 개념들이 저장된 경험의 한 부분으로 곧장 이동했을 것이다. 에이전트를 구축할 때 유용한 사고 모델이다.

  • 거대한 컨텍스트 윈도우가 곧 메모리는 아니다.

  • 검색한 문서를 쌓아 둔다고 이해가 되는 것은 아니다.

  • 긴 추론 과정이 곧 신뢰성은 아니다.

이것들은 재료일 뿐이다. 에이전트를 진정한 에이전트처럼 느끼게 하는 것은 뇌가 인생의 모든 기억을 무차별 대입하지 않게 해주는 것과 같다. 바로 제어다.

최근 발표된 조사 논문 대규모 언어 모델을 위한 에이전트형 추론은 많은 개발자가 체감해 온 변화를 훌륭하게 요약하고 이름 붙였다. 모델 내부의 추론에서 상호작용을 통한 추론으로의 전환이다. 이 글은 해당 논문을 요약한 것이 아니다. 그 변화를 실용적인 시스템 설계로 옮기려는 시도다.

도구가 달린 챗봇처럼 에이전트를 구축하면 챗봇과 똑같은 방식으로 실패하면서 비용만 더 큰 실수를 반복하게 된다.

기존 방식과 새로운 방식

한동안 ‘모델을 더 똑똑하게 만드는’ 기본 전략은 더 나은 프롬프트, 추론 과정, 자기 일관성 및 샘플링 기반 개선에 검색을 약간 더하는 것이었다.

ReAct는 ‘사고 → 행동 → 관찰’이라는 흐름을 자연스럽게 만든 전환점이었다. 하지만 암묵적인 제약에 주목해야 한다. 많은 경우 여전히 ‘토큰만 더 많이 쓰는 원샷 추론’으로 끝난다. 이 조사는 더 명확한 관점을 제시한다. 에이전트형 추론은 테스트 시점 상호작용의 확장을 강조하며, 모델과 메모리, 환경이 모두 루프에 참여하는 반복적 과정으로 추론을 바꾼다.

데모에서는 인상적이지만 실제 워크플로에서는 쉽게 무너지는 에이전트를 만들거나 사용해 본 사람을 위한 글이다.

의도치 않게 만든 에이전트와 오늘날 수많은 ‘에이전트’의 모습

자주 보았고 필자도 여러 형태로 직접 만들어 본 패턴을 설명해 보겠다.

  1. 좋은 채팅 모델을 가져온다

  2. 검색, DB 쿼리, 코드 실행 같은 도구 몇 개를 추가한다

  3. RAG를 추가한다

  4. “you are an autonomous agent”라는 시스템 프롬프트를 추가한다

  5. 중단되거나 시간 초과가 될 때까지 모든 것을 while 루프로 감싼다

축하한다. 에이전트 모양의 물체가 완성됐다. 하지만 대개 예측 가능한 방식으로 실패한다.

  • 컨텍스트 비대화: 모든 관찰 결과가 추가되면서 프롬프트가 고고학적 지층처럼 쌓인다.

  • 도구 오용: ‘잘못된 도구를 확신에 차서 사용하기’가 기본적인 실패 유형이 된다.

  • 중단 조건 부재: 계속해야 해서가 아니라 계속할 수 있다는 이유로 작업을 이어 간다.

  • 그라운딩 원칙 부재: 강제로 확인하게 하지 않으면 자신의 오류를 알아차리지 못한다.

  • 메모리=채팅 기록: 사실상 로그를 작성하면서 이를 학습이라고 부르는 셈이다.

이 때문에 ‘에이전트’는 데모에서는 마법처럼 보이지만 프로덕션에서는 엉망이 되기 쉽다. 에이전트형 시스템을 프로덕션에 도입한 경험도 이를 뒷받침한다. 모델이 아닌 시스템을 평가하기 시작하면 실패 유형에는 ‘모델이 정답을 냈는가’뿐 아니라 탐색, 올바른 도구 사용, 컨텍스트 정리, 평가 설계까지 포함된다.

그렇다면 의도한 에이전트란 무엇일까?

현실에서 의도대로 작동하는 에이전트: 항공편 예약

덜 추상적으로 설명하기 위해 누구나 쉽게 떠올릴 수 있는 간단한 워크플로를 살펴보자. “Book me a flight from London to New York next Tuesday. Arrive before 6pm. Keep it under £900. Aisle seat.”

기존 패턴: 도구가 달린 챗봇

흔히 볼 수 있는 ‘에이전트 모양’ 구현은 다음과 같다.

  • 아직 필요하지 않더라도 항공사 및 여행 정책 문서를 대량으로 즉시 검색한다.

  • 검색 도구를 호출해 긴 결과 목록을 프롬프트에 붙여 넣고 그중 ‘하나를 고른다’.

  • 도착 시간, 수하물, 좌석, 정책 등의 제약 조건을 검증하지 않고 성급하게 예약한다.

  • 실패하면 약간 다른 방식으로 재시도하지만, 무엇이 바뀌었고 무엇을 배웠는지는 명확하지 않다.

실패 원인은 모델이 추론하지 못해서가 아니라 시스템이 워크플로를 제어하지 않기 때문이다.

개선된 패턴: 에이전트형 루프

좀 더 에이전트다운 방식은 이 작업을 명시적인 상태와 검사를 갖춘 상호작용 과정으로 다룬다.

  • 계획: 제약 조건을 다시 정리하고 누락된 정보를 나열한다(예: “선호하는 공항이 있나요?”/“경유 1회도 괜찮나요?”).

  • 실행: 날짜 범위, 도착 시간 제약, 예산을 담은 구조화된 쿼리로 항공편 검색을 호출한다.

  • 관찰: 결과를 그대로 대량으로 붙여 넣지 않고 가격·도착 시간·경유 횟수가 포함된 상위 후보 5개를 간결한 상태 객체에 저장한다.

  • 업데이트: 제약 조건을 충족하지 못하면 쿼리를 조정한다(예: “오후 6시 이전 도착은 너무 엄격합니다. 시간 범위를 넓히거나 예산을 올릴까요?”).

  • 검증: 검증기를 실행한다(“도착 < 18:00”, “가격 ≤ £900”, “정책 준수”, “좌석 선택 가능”).

  • 중단: 예약 API가 확인 정보를 반환하고 모든 검증기를 통과한 경우에만 중단한다.

달라진 점은 미묘하지만 결정적이다. 검색은 반사적으로 수행하지 않고 필요할 때만 하며, 컨텍스트는 누적하지 않고 구조화된 상태로 관리하고, 검증은 사용자에게 맡기지 않고 루프 안에서 수행한다. ‘항공편 예약’을 ‘구매 주문서 작성’, ‘환불 처리’, ‘프로덕션 설정 변경’, ‘PR 배포’로 바꿔도 마찬가지다. 에이전트가 행동할 수 있게 되면 프롬프트보다 루프가 중요해진다.

의도한 에이전트: 명시적 컨텍스트, 명시적 상태, 명시적 검증

앞서 언급한 조사는 에이전트형 추론을 기반 계층(계획·도구 사용·검색), 자기 진화 계층(피드백+메모리), 집단 계층(다중 에이전트 조율)의 세 계층으로 분류한다.

하지만 더 근본적인 발상은 추론이 그럴듯한 추론 과정을 생성하는 데 그치지 않고 계획, 의사 결정, 검증을 구성하는 원칙이 된다는 것이다. 아키텍처에서 무엇이 달라지는지 연결해 보기 전까지는 추상적으로 들릴 수 있다. 기억해야 할 핵심은 세 가지다.

1) 컨텍스트는 자원이지, 아무거나 쌓아 두는 곳이 아니다

좋은 에이전트는 검색을 ‘항상 해야 하는 일’로 취급하지 않는다. 검색은 반사 행동이 아니라 결정이다.

실용적인 판단 기준은 다음과 같다.

시스템이 매 차례 검색한다면 검색 기능을 구축한 것이 아니라 컨텍스트 비용을 만든 것이다.

실제 업무에서도 늘 볼 수 있는 문제다. 프로덕션 장애를 디버깅할 때 모든 로그를 컨텍스트에 쏟아붓지는 않는다. 현재 가설을 바탕으로 다음에 가져올 메트릭과 로그를 결정한다. 이것이 ‘에이전트형 검색’이다. 더 구체적인 패턴은 다음과 같다.

  1. 검색이 필요한지 판단한다

  2. 필요하다면 쿼리를 작성하고, 가져오고, 훑어보고, 추출한다

  3. 증거가 충돌하면 다시 가져온다

  4. 그런 다음에만 종합한다

‘에이전트형 RAG’가 기존 RAG와 달라지는 지점도 여기다. 검색은 기본 파이프라인 단계가 아니라 의도적인 추론 단계가 된다.

2) 상태가 명시적이고 검사 가능하다

평가 대상을 ‘모델’에서 ‘시스템’으로 바꾸는 순간, 상태 추적과 트레이싱이 중요해진다.

이제 업계에서 한층 명확하게 다루기 시작한 것 중 하나는 에이전트 워크플로의 관측 가능성이다. 예를 들어 OpenAI의 Agents SDK에는 기본 트레이싱 기능과 Traces 대시보드가 포함되어 있다. 에이전트 실행 과정(생성, 도구 호출, 핸드오프, 가드레일, 사용자 지정 이벤트)을 기록해 단계별로 무슨 일이 있었는지 디버깅하고 감사할 수 있게 해준다.

이는 있으면 좋은 기능이 아니다. 디버깅할 수 있는 시스템과 감으로만 점검할 수 있는 시스템을 가르는 차이다.

3) 검증은 선택 사항이 아니다

이 조사에서 가장 실용적인 부분은 피드백의 중요성을 매우 직접적으로 설명한다는 점이다. 피드백을 성찰적 피드백(생성 → 비평 → 수정), 매개변수 적응(파인 튜닝/RL로 학습), 검증기 기반 피드백(검증을 통과할 때까지 재시도)의 세 가지 체계로 나눈다.

대부분의 팀은 단순하지만 효과적인 검증기 기반 피드백부터 시작해야 한다. 단위 테스트를 실행하거나 스키마를 검사하고, 비즈니스 규칙과 제약 조건(“상위 단계의 승인 없이 X를 초과하는 금액은 환불 금지”)을 적용하거나 사실성을 확인하는(“인용 필수”) 검증기를 하나라도 만들 수 있다면, 비결정적인 모델 출력을 실제로 신뢰할 수 있는 결과로 바꿀 수 있다.

여기서 쉽게 예상하지 못하는 변화 중 하나는 간단하다. 에이전트 영역에서는 신뢰성이 모델보다 루프에서 나오는 경우가 많다.

구체적인 패턴: 계획 → 실행 → 관찰 → 업데이트

훈련 없이도 동작을 안정적으로 개선해 주는 가장 간단한 루프 원칙은 다음과 같다.

  • 계획 → 실행 → 관찰 → 업데이트의 단계로 작업한다.

  • 각 실행 후 관찰 결과를 1~3개의 글머리 기호로 요약한다.

  • 성공 기준을 충족하거나 예산 한도에 도달하면 중단하고, 현재까지 파악한 최선의 결과와 남은 불확실성을 반환한다.

모델의 답변을 장황하게 만들자는 이야기가 아니다. 시스템을 이해하기 쉽게 만들고, 각 단계에서 현실과 맞닿도록 강제하자는 것이다. 엔지니어에게 익숙한 예로 CI 방식의 폐쇄 루프 그라운딩이 있다.

  • 계획: 변경 목록 제안

  • 실행: 테스트/린트 실행

  • 관찰: 실패 결과 파싱

  • 업데이트: 패치 후 재시도

에이전트가 어딘가 어색한지 알아보는 법

의도치 않게 만들어진 에이전트 설계를 드러내는 몇 가지 질문이 있다.

“에이전트가 검색할 대상을 직접 선택하는가, 아니면 언제나 검색부터 하는가?”

무조건 검색하면 지연 시간과 비용이 늘고, 컨텍스트가 희석되며, 잘못된 입력이 잘못된 출력으로 이어질 위험도 커진다.

“에이전트가 자신의 오류를 알아차릴 수 있는가?”

에이전트가 받는 유일한 피드백 신호가 “사용자가 짜증을 낸다”라면, 인간의 고통을 이용해 RL을 하는 셈이다. 검증기 기반 재시도 루프는 에이전트가 현실을 점검하게 하는 가장 깔끔한 방법이다.

“메모리에 기록할 수 있으며, 시간이 지날수록 개선되는가?”

‘메모리’가 채팅 기록을 이어 붙이는 데 불과하다면 사실상 로그를 작성하는 것이다. 이 조사가 제시한 메모리의 관점은 중요하다. 메모리는 단순한 대화 기록이 아니라, 에이전트가 시간이 지나며 다듬어 가는 동적이고 확장 가능한 컨텍스트가 된다.

실제로 도움이 되는 메모리

로그는 무슨 일이 있었는지 알려주고, 메모리는 다음에 무엇을 해야 하는지 알려준다. 채팅 기록은 대화 내용의 기록이다. 메모리는 앞으로 유지할 가치가 있는 정보를 판단하는, 계속 발전하는 정책이다.

실용적인 출발점은 ‘작업 유형·도구·실패 유형’을 키로, ‘효과가 있었던 방법과 피해야 할 것’을 값으로 정리한 작은 ‘교훈’ 표다. 완벽한 지식 그래프를 구축하는 것이 목적은 아니다. 목표는 복리처럼 개선되는 동작을 만드는 것이다. 메모리와 피드백을 결합하면 에이전트가 ‘상태 없는 도우미’에서 시간이 지날수록 발전하는 시스템으로 바뀐다.

다중 에이전트: 에이전트 증식이 아닌 최소 기능 팀

문제에 더 많은 에이전트를 투입하고 싶어지지만, 이는 조율 부담만 몇 배로 늘리는 경우가 많다. 효과적인 ‘최소 기능 팀’ 패턴은 다음과 같다.

  • 조정자: 작업 분해 및 할당

  • 실행자: 도구 호출 및 변경 수행

  • 비평자/평가자: 정확성과 위험 검사

  • 메모리 관리자: 교훈 기록 및 선별

각 에이전트의 책임을 설명할 수 없다면 아직 여러 에이전트가 필요하지 않을 가능성이 크다.

규범이 아닌 실용적인 교훈

이러한 패러다임 전환을 진정으로 받아들인다면 모든 것을 프롬프트에 밀어 넣고, 실패를 최종 출력으로 취급하고, 에이전트를 챗봇처럼 평가하는 일을 멈추게 될 것이다. 그리고 에이전트를 본래 모습 그대로 바라보기 시작할 것이다. 언어가 제어 평면 역할을 하고 신뢰성이 루프에서 나오는 소프트웨어 시스템으로 말이다.

모델을 하나 더 추가하기 전에 평가 루프를 하나 더 추가하라. 모든 것을 검색하기 전에 검색을 조건부로 만들어라. 열 개를 배포하기 전에 검증기 하나부터 배포하라. 메모리를 데이터베이스가 아니라 정책 결정처럼 다뤄라. 다중 에이전트로 전환할 때는 스무 개가 아니라 두 개부터 시작하라. 이는 규칙이 아니라 프로덕션 환경에서 살아남은 패턴이다.

작성자

Giorgos Lysandrou