Agent Executor 동작 원리 이해하기

📌 3줄 요약
· Agent Executor는 LLM이 "어떤 도구를 어떤 입력으로 쓸지" 스스로 정하고, 그 결과를 다시 받아 다음 행동을 이어 가도록 반복을 돌려 주는 LangChain의 실행 엔진입니다.
· 핵심은 생각 → 행동 → 관찰을 한 바퀴로 묶어, 최종 답이 나올 때까지 이 루프를 자동으로 반복한다는 점입니다.
· 도구 호출·결과 수집·종료 판단을 사람이 손으로 짜지 않아도, Executor가 LLM의 결정을 실제 실행으로 연결해 줍니다.
🧠 LLM이 다음 행동 결정 → 🔧 도구 실행 → 👀 결과 관찰 → 🔁 끝날 때까지 반복

앞선 편들에서는 프롬프트를 만들고, 체인을 잇고, 대화를 기억하게 하는 방법을 살펴봤습니다. 그런데 "검색해서 찾아보고, 계산까지 한 다음 답해 줘" 같은 요청은 한 번의 LLM 호출로는 끝나지 않습니다. 모델이 필요한 도구를 직접 골라 쓰고, 그 결과를 보고 다음 행동을 다시 정해야 하기 때문입니다. 이 반복을 대신 돌려 주는 것이 바로 Agent Executor입니다. 오늘은 이 실행 엔진이 안에서 무엇을 하는지 차근차근 따라가 보겠습니다.


🧩 Agent와 Agent Executor는 다릅니다

먼저 헷갈리기 쉬운 두 개념을 구분해야 합니다. Agent는 "지금 상황에서 무엇을 할지 결정하는 두뇌"입니다. 질문과 지금까지의 진행 상황을 받아, 다음에 어떤 도구를 어떤 입력으로 쓸지, 아니면 이제 최종 답을 낼지를 한 번 판단해 돌려줄 뿐입니다. 즉 Agent 자체는 결정만 하고, 실제로 도구를 실행하지는 않습니다.

반면 Agent Executor는 그 결정을 받아 실제로 실행에 옮기고, 결과를 다시 Agent에게 돌려주며, 최종 답이 나올 때까지 이 과정을 반복으로 묶어 주는 실행 담당입니다. 다시 말해 Agent가 "다음 수"를 고르는 사람이라면, Executor는 그 수를 실제 판 위에 두고 다음 차례를 계속 돌려 주는 진행자인 셈입니다.

Agent는 무엇을 할지 결정하고, Agent Executor는 그 결정을 실제 실행과 반복으로 연결합니다 — 둘이 짝을 이뤄야 비로소 "스스로 도구를 쓰는 AI"가 됩니다.

🔁 생각-행동-관찰 루프

Agent Executor의 동작은 흔히 생각(Reason) → 행동(Act) → 관찰(Observe)이라는 한 바퀴로 설명됩니다. 모델이 먼저 지금 무엇을 해야 할지 생각하고, 그 생각에 따라 도구를 실행한 뒤, 돌아온 결과를 관찰해 다음 생각의 재료로 삼는 흐름입니다.

중요한 점은 이 한 바퀴가 한 번으로 끝나지 않는다는 것입니다. 관찰한 결과만으로 답하기에 부족하면 Executor는 그 결과를 다시 프롬프트에 담아 다음 바퀴를 돌립니다. 모델이 "이제 충분하다"고 판단해 최종 답을 내놓을 때까지, 이 루프가 계속 이어집니다.


🔍 한 바퀴 안에서 벌어지는 일

Executor가 루프 한 바퀴에서 내부적으로 하는 일을 단계로 나눠 보면 구조가 한눈에 들어옵니다.

🧠 결정 단계
질문과 지금까지의 기록을 Agent에게 넘기면, Agent가 다음에 쓸 도구와 입력을 골라 돌려줍니다.
🔧 실행 단계
Executor가 그 도구를 실제로 호출하고, 돌아온 결과(관찰값)를 받아 둡니다.
📎 기록 단계
방금의 행동과 관찰값을 진행 기록에 덧붙여, 다음 결정의 재료로 삼습니다.
🏁 판단 단계
Agent가 최종 답을 내놓았는지 확인해, 끝났으면 멈추고 아니면 다시 결정 단계로 돌아갑니다.

정리하면 흐름은 이렇게 이어집니다. 사용자의 질문이 들어오면 Executor가 Agent에게 다음 행동을 묻고, 돌아온 결정대로 도구를 실행합니다. 결과를 진행 기록에 덧붙인 뒤 다시 Agent에게 물어, 이번에도 도구를 쓰라고 하면 반복하고 최종 답을 주면 그것을 돌려주며 끝냅니다. 이렇게 매 바퀴마다 기록이 쌓이므로, Agent는 이전에 무엇을 해 봤는지를 알고 다음 수를 고를 수 있습니다.


⚙️ 코드로 살펴보기

가장 기본적인 형태는 도구 목록과 Agent를 만들어 AgentExecutor에 넘기는 것입니다. 여기서는 간단한 계산 도구 하나를 정의해, 모델이 필요할 때 이 도구를 쓰도록 구성해 보겠습니다.

from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.tools import tool
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

# 1) 도구 정의 — 모델이 필요할 때 호출한다
@tool
def add(a: int, b: int) -> int:
    """두 정수를 더한다."""
    return a + b

tools = [add]

llm = ChatOpenAI(temperature=0)

prompt = ChatPromptTemplate.from_messages([
    ("system", "너는 도구를 활용해 답하는 assistant다."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),  # 진행 기록이 쌓이는 자리
])

# 2) 결정만 담당하는 Agent
agent = create_tool_calling_agent(llm, tools, prompt)

여기까지는 결정 두뇌만 만든 상태입니다. 이제 이 Agent를 AgentExecutor로 감싸면, 도구 실행과 반복까지 Executor가 알아서 처리해 줍니다.

# 3) 실행과 반복을 담당하는 Executor
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

result = executor.invoke({"input": "17 더하기 25는 얼마야?"})
print(result["output"])
# 모델이 add 도구를 호출 → 결과 42 관찰 → 최종 답 생성

위에서 agent_scratchpad가 바로 진행 기록이 쌓이는 자리입니다. Executor는 매 바퀴마다 방금의 행동과 관찰값을 이 자리에 채워 넣어, 다음 결정 때 모델이 지금까지의 흐름을 보고 판단하게 합니다. verbose=True로 두면 어떤 도구를 어떤 입력으로 썼고 무엇을 관찰했는지 중간 과정이 로그로 보이므로, 디버깅할 때 유용합니다.


🪜 루프를 멈추는 기준

스스로 반복한다는 말은 잘못하면 끝없이 돌 수도 있다는 뜻이기도 합니다. 그래서 Agent Executor에는 루프를 안전하게 끊는 멈춤 장치가 마련돼 있습니다. 대표적인 기준을 표로 정리했습니다.

멈춤 기준 언제 멈추나
최종 답 도달Agent가 도구 대신 최종 답을 내놓으면 그 즉시 루프를 끝내고 결과를 돌려줍니다.
max_iterations정해 둔 최대 반복 횟수를 넘으면, 답이 안 났더라도 더 돌지 않고 멈춥니다.
max_execution_time전체 실행이 정해 둔 시간 한도를 넘으면 중단합니다.

예를 들어 반복 횟수를 제한하고 싶다면, 아래처럼 max_iterations를 지정하면 됩니다.

executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=5,        # 최대 5바퀴까지만 반복
    # max_execution_time=30, # 필요하면 시간 한도도 함께
)

이렇게 상한을 걸어 두면 모델이 같은 도구를 계속 맴돌거나 답을 못 내는 상황에서도, 루프가 무한정 이어지지 않고 안전하게 끊깁니다. 즉 스스로 판단하는 자유와, 폭주하지 않는 안전장치를 함께 갖춘 구조입니다.


🔧 실무 팁

  • 반복은 곧 비용 — 한 바퀴를 돌 때마다 LLM을 다시 호출하므로, 루프가 길어질수록 토큰 비용과 지연이 함께 늘어납니다. 꼭 필요한 도구만 쥐여 주는 것이 좋습니다.
  • 도구 설명은 또 하나의 프롬프트 — 모델은 도구의 이름과 설명(docstring)을 보고 쓸지 말지 정합니다. 설명이 모호하면 엉뚱한 선택을 하므로, 무엇을 하는 도구인지 분명히 적어야 합니다.
  • 상한은 되도록 설정 — 운영 환경이라면 max_iterations나 시간 한도를 걸어, 예상 밖의 무한 루프와 비용 폭주를 막는 편이 안전합니다.
  • 중간 과정을 확인 — 기대와 다른 답이 나오면 verbose 로그로 어느 바퀴에서 어떤 도구를 잘못 썼는지 되짚으면 원인을 빨리 찾을 수 있습니다.

❓ 자주 묻는 질문 (FAQ)

Q. Agent만 있으면 되지, Executor가 왜 따로 필요한가요?
A. Agent는 "다음에 무엇을 할지" 결정만 하고 멈춥니다. 그 결정을 실제 도구 호출로 옮기고, 결과를 다시 넣어 반복을 돌려 주는 역할이 Executor입니다. 둘이 짝을 이뤄야 실제로 동작합니다.

Q. 모델이 도구를 안 쓰고 바로 답해 버리면요?
A. 그래도 괜찮습니다. Agent가 처음부터 최종 답을 내놓으면 Executor는 도구를 거치지 않고 그 답을 바로 돌려줍니다. 도구 사용은 필요할 때만 일어납니다.

Q. 루프가 멈추지 않으면 어떻게 되나요?
A. max_iterations나 max_execution_time 같은 상한에 걸리면 강제로 중단됩니다. 상한을 걸지 않았다면 비정상적으로 오래 돌 수 있으므로, 운영 시에는 설정해 두는 것이 안전합니다.


마무리

정리하면, Agent Executor는 "무엇을 할지 결정하는" Agent와 짝을 이뤄, 그 결정을 실제 도구 실행과 반복으로 연결해 주는 실행 엔진입니다. 핵심은 생각 → 행동 → 관찰을 한 바퀴로 묶어, 매 바퀴의 결과를 진행 기록에 쌓아 가며 최종 답이 나올 때까지 돌린다는 점이었습니다. 그리고 이 자유로운 반복이 폭주하지 않도록 최대 반복 횟수와 시간 한도 같은 멈춤 장치가 함께 준비돼 있다는 것도 살펴봤습니다. 다음 편에서는 이 Agent가 고를 수 있는 재료인 Tools를 직접 정의하고 다루는 방법으로 이야기를 이어가 보겠습니다.

댓글

이 블로그의 인기 게시물

LCEL — LangChain 표현식으로 체인 깔끔하게 잇기

Streaming — 답변을 실시간으로 흘려보내기

Callback와 로깅 — LangChain 내부 들여다보기