2026년 4월 29일 작성

Agent Loop - LLM이 Tool을 반복 호출하며 작업을 완수하는 제어 구조

agent loop는 stateless한 LLM이 tool 호출과 결과 관찰을 반복하며 작업을 진행하도록 만드는 while loop 기반 제어 구조입니다.

Agent Loop

  • agent loop는 LLM이 tool 호출과 결과 관찰을 반복하면서 하나의 작업을 완수하도록 만드는 제어 구조입니다.
    • 한 번의 LLM 호출로 끝나는 단발성 응답이 아니라, “생각 -> 행동 -> 관찰 -> 다시 생각”이 자동으로 이어집니다.
    • 이 반복 구조 덕분에 LLM은 처음부터 모든 정보를 알지 못해도, 환경에서 ground truth를 가져오며 점진적으로 작업을 완성합니다.
  • agent loop는 모든 LLM agent의 가장 근본적인 골격입니다.
    • “chatting”이라는 단순한 UX조차 이전 message를 추적하고 이어붙이는 while loop의 산물입니다.
    • workflow pattern, sub-agent, state machine 같은 더 복잡한 구조도 결국 agent loop의 변형이거나 그것을 감싸는 layer입니다.
  • agent loop는 harness engineering의 출발점입니다.
    • LLM 자체는 stateless하므로, 상태와 반복은 LLM 바깥의 code가 책임집니다.
    • 이 바깥 code 전체를 harness라고 부르며, agent loop는 harness의 가장 원초적인 형태입니다.
flowchart TB
    user[User] -->|작업 지시| app[Application]
    app -->|messages + tool schema| llm[LLM]
    llm -->|응답 생성| decision{tool 호출 요청?}
    decision -->|예| tool_exec[Tool 실행]
    tool_exec -->|결과를 messages에 누적| app
    decision -->|아니오, 종료 신호| final[최종 응답]
    final --> user
    safeguard[Max Iteration / Token Budget / Timeout] -.->|폭주 방지| app

LLM이 Stateless하다는 것의 의미

  • LLM은 이전 호출의 어떤 정보도 기억하지 않는 함수입니다.
    • 입력으로 받은 message 배열만 보고 다음 token을 생성합니다.
    • 같은 입력에 같은 model로 호출하면 sampling을 제외하면 같은 출력이 나옵니다.
  • “대화”가 가능한 이유는 application code가 message를 누적하기 때문입니다.
    • 사용자가 새 message를 보낼 때마다, application은 이전 모든 message에 새 message를 덧붙여 LLM에 다시 전달합니다.
    • LLM은 매 호출마다 전체 대화를 처음 보는 듯이 처리하며, 기억은 application의 message 배열에만 존재합니다.
  • agent loop는 message 누적을 application code가 책임지는 동일한 방식으로 작동합니다.
    • LLM이 tool을 호출하면, application이 tool을 실행하고 결과를 message 배열에 추가한 뒤 LLM을 다시 부릅니다.
    • LLM은 이전 호출과 현재 호출 사이의 연결을 직접 알지 못하며, message 배열에 누적된 history만 보고 다음 행동을 결정합니다.

Agent Loop의 기본 구조

  • 가장 단순한 agent loop는 LLM 호출과 tool 실행을 번갈아 수행하는 while loop입니다.
    • LLM이 tool을 더 이상 호출하지 않을 때까지 반복하며, 종료 조건은 LLM의 응답 자체가 알려줍니다.
    • 한 turn 안에서 application은 message 배열을 LLM에 전달하고, LLM은 다음 행동(tool 호출 또는 최종 답변)을 결정하여 반환합니다.
messages = [user의 첫 message]

loop:
    response = LLM 호출 (messages, tools)
    messages에 LLM 응답 추가

    if 응답이 tool 호출 요청이면:
        각 tool을 application이 실행
        실행 결과를 messages에 추가
        loop 계속
    else:
        loop 종료
  • agent loop를 상태 전이로 보면, Thinking, ToolCall, Observing 세 상태가 순환하다가 종료 신호로 Done에 도달하는 state machine으로 표현됩니다.
stateDiagram-v2
    [*] --> Thinking: User 작업 지시
    Thinking --> ToolCall: tool 호출 요청
    Thinking --> Done: 종료 신호
    ToolCall --> Observing: Application이 tool 실행
    Observing --> Thinking: 결과를 messages에 누적
    Done --> [*]: 최종 응답
  • 매 turn마다 LLM은 전체 message 배열을 처음부터 다시 받으며, 누적된 history만이 LLM이 참조할 수 있는 유일한 정보원입니다.

  • LLM은 tool을 직접 실행하지 않고 “이 tool을 이 인자로 부르고 싶다”고 선언만 하며, 실제 호출은 application code가 수행합니다.

  • application은 tool 실행 결과를 다시 message로 감싸 다음 호출에 포함시키며, 누적된 message가 LLM의 다음 판단 근거가 됩니다.

  • loop 종료는 LLM이 “더 이상 tool을 부를 필요 없다”는 신호를 응답에 담을 때 일어나며, application은 그 신호를 만날 때까지 호출을 이어갑니다.

Tool Use Contract

  • tool use는 application과 model 사이의 계약입니다.
    • application은 tool의 schema(이름, 설명, parameter 형식)를 정의합니다.
    • model은 schema를 보고 언제 어떤 인자로 tool을 부를지 결정하지만, 실제 실행은 절대 하지 않습니다.
  • schema 기반 호출 계약 덕분에 LLM은 자유 형식 text 생성기가 아니라, 호출 가능한 함수처럼 동작합니다.
    • 일반적인 typed interface처럼 schema 정의, callback 처리, 결과 반환의 흐름으로 통합할 수 있습니다.
    • 다만 호출 주체가 결정론적 code가 아니라, 대화 맥락을 보고 판단하는 LLM이라는 점이 다릅니다.
sequenceDiagram
    participant app as Application
    participant llm as LLM
    participant env as Environment

    app->>llm: messages + tools schema
    llm-->>app: tool 호출 의도
    app->>env: tool 실행
    env-->>app: 실행 결과
    app->>llm: 실행 결과를 추가하여 재호출
    llm-->>app: 다음 tool 호출 또는 작업 완료

Agent Loop가 안전하게 끝나기 위한 조건

  • agent loop는 종료 조건 없이 작동하면 무한 호출에 빠질 수 있으므로, application이 명시적인 안전 장치를 둬야 합니다.
    • LLM이 종료 신호를 반환하지 않고 tool 호출을 끊임없이 시도할 수 있습니다.
    • tool 실행 결과가 비어 있거나 오류일 때, LLM이 같은 호출을 반복할 수도 있습니다.
  • max iteration은 loop 횟수 상한을 두어, 일정 turn 이상 진행되면 강제 종료시킵니다.
    • LLM이 종료 신호 없이 tool 호출만 반복하더라도, 정해진 turn 수에 도달하면 application이 loop를 끊습니다.
  • token budget은 누적 token 사용량 상한을 두어, 비용 폭주를 막습니다.
    • context가 길어질수록 한 호출당 비용이 누적 message 길이에 비례해 커지므로, 누적 사용량을 측정해 한도를 넘으면 종료합니다.
  • timeout은 tool 실행과 전체 loop에 시간 제한을 두어, 무응답 상황에서 빠져나옵니다.
    • tool이 외부 system을 부르다 hang되거나 LLM 호출이 지연될 때, 시간 제한이 없으면 agent가 영원히 멈춰 있을 수 있습니다.
MAX_ITERATIONS = 50

for iteration in range(MAX_ITERATIONS):
    response = LLM 호출 (messages, tools)
    messages에 LLM 응답 추가

    if 응답이 tool 호출 요청이 아니면:
        loop 종료
    
    각 tool을 application이 실행
    실행 결과를 messages에 추가

# 한도 초과 시
raise "agent가 max iteration에 도달했습니다."

Agentic System에서 Agent Loop의 위치

  • Anthropic은 LLM과 tool로 구성된 system 전체를 agentic system이라 부르며, 이를 다시 workflow와 agent로 구분합니다.
    • workflow는 사전 정의된 code 경로를 따라 LLM과 tool이 orchestration되는 system입니다.
    • agent는 LLM이 자신의 process와 tool 사용을 동적으로 결정하는 system이며, 그 핵심 mechanism이 바로 agent loop입니다.
  • agent loop는 agent를 정의하는 핵심 mechanism이며, workflow에서는 evaluator-optimizer 같은 일부 pattern에서만 제한적으로 등장합니다.
    • workflow의 대부분은 정해진 단계와 분기를 따라 흐르므로 loop가 필요 없습니다.
    • evaluator-optimizer처럼 평가-재생성을 반복하는 workflow는 loop를 갖지만, 종료 조건과 반복 경로가 code에 사전 정의되어 있다는 점에서 agent loop와 다릅니다.
    • agent는 어떤 tool을 몇 번 부를지 미리 정해지지 않으며, LLM이 매 turn 환경에서 ground truth를 받아 다음 행동을 정합니다.
flowchart TB
    agentic_system[Agentic System] --> workflow[Workflow]
    agentic_system --> agent[Agent]
    workflow --> prompt_chain[Prompt Chaining]
    workflow --> routing[Routing]
    workflow --> parallel[Parallelization]
    workflow --> orchestrator[Orchestrator-Workers]
    workflow --> evaluator[Evaluator-Optimizer]
    agent --> agent_loop[Agent Loop]
    agent_loop --> tool_call[Tool Call]
    tool_call --> observe[Environmental Feedback]
    observe --> agent_loop

Agent Loop와 Workflow의 차이

  • agent loop는 반복 횟수와 경로가 LLM에 의해 결정됩니다.
    • 사용자가 “bug를 찾아 고쳐줘”라고 지시하면, 어떤 file을 몇 번 읽고 어떤 명령을 실행할지는 LLM이 매 turn 결정합니다.
    • 결과적으로 동일 입력이 동일 경로로 처리되지 않으며, 자율성과 비용 및 오류 누적 위험이 함께 커집니다.
  • workflow는 반복 횟수와 경로가 code에 의해 결정됩니다.
    • “문서를 요약하고 번역해줘”라는 작업을 두 단계 LLM 호출로 미리 정의합니다.
    • prompt chaining, routing, parallelization, orchestrator-workers, evaluator-optimizer 같은 정형화된 pattern으로 구성됩니다.
    • 자율성은 낮지만 latency와 비용이 예측 가능하며, 결과의 일관성이 높습니다.

Agent Loop가 풀어야 하는 본질적 문제

  • agent loop는 동작 원리는 단순하지만, 실제로 안정적인 agent를 만들려면 여러 본질적 문제를 해결해야 합니다.
    • 단순 loop만으로는 장시간 작업, 대규모 tool 출력, 복합 sub task 등에서 한계를 드러냅니다.
    • 장시간 작업, 대규모 출력, 복합 sub task에서 드러나는 한계가 곧 harness engineering이 다루는 문제 영역입니다.

Context 부패

  • LLM은 context 길이가 늘어날수록 추론 능력이 떨어집니다.
    • 이를 context 부패(context rot)라고 부르며, agent loop가 길어질수록 응답 품질이 저하됩니다.
    • tool 결과가 누적되어 context가 가득 차면, agent가 이전 정보를 잘못 참조하거나 작업을 절반만 마치고 종료합니다.
  • compaction과 tool call offloading으로 대응합니다.
    • compaction은 일정 길이를 넘으면 이전 history를 요약하여 일부 message를 덜어냅니다.
    • tool call offloading은 큰 tool 출력을 file로 빼고 요약만 context에 남깁니다.

조기 종료와 폭주

  • LLM은 작업이 끝나지 않았는데 종료 신호를 반환하기도 하고, 끝났는데도 tool 호출을 계속 시도하기도 합니다.
    • 조기 종료는 system prompt와 tool description으로 작업 완료 기준을 명확히 명시하여 줄입니다.
    • 폭주는 max iteration, token budget, hook 기반 검증으로 막습니다.

Sub Task의 Context 오염

  • 한 agent loop 안에서 조사, 탐색, 구현을 모두 처리하면 중간 noise가 쌓여 핵심 context를 흐립니다.
    • sub-agent는 별도 loop를 spawn하여 sub task를 격리 처리하고, 상위 agent에게는 요약된 결과만 전달합니다.
    • 이를 context 방화벽이라고 부르며, sub-agent의 진짜 가치는 역할 분담이 아니라 context 격리에 있습니다.

검증 불가능성

  • LLM 내부에서 일어나는 world modeling, planning, reflection은 hidden state로 처리되어 검증할 수 없습니다.
    • 동일 input이 동일 output을 보장하지 않으며, audit과 재현이 어렵습니다.
    • state machine agent는 결정론적인 부분을 LLM loop 밖 state machine에 두고, LLM은 잔여 판단에만 호출하는 방식으로 검증 불가능성을 완화합니다.

Agent Loop 설계 원칙

  • Anthropic이 제시한 agent 구현의 핵심 원칙은 단순성, 투명성, ACI(Agent-Computer Interface) 품질입니다.
    • 복잡성은 측정 가능한 개선이 있을 때만 추가합니다.
    • agent의 planning 단계를 명시적으로 노출하여 동작을 추적 가능하게 합니다.
    • tool documentation과 testing을 prompt만큼 정성껏 다듬습니다.

단순성

  • 가장 단순한 해결책을 먼저 시도하고, 부족할 때만 복잡성을 추가합니다.
    • agent loop가 필요 없으면 단발 호출로 끝냅니다.
    • workflow로 충분하면 agent를 쓰지 않습니다.
    • sub-agent가 필요 없으면 단일 loop로 처리합니다.
  • framework는 시작에는 도움이 되지만, production에서는 추상화 layer를 줄이는 방향이 권장됩니다.
    • LangChain, LlamaIndex 같은 framework는 표준 작업을 단순화하지만, debug를 어렵게 만들 수 있습니다.
    • basic component로 직접 구축하면 동작을 정확히 통제할 수 있습니다.

투명성

  • agent의 planning 단계를 명시적으로 노출하면 동작을 추적할 수 있습니다.
    • thinking을 활용하여 model이 다음 행동을 결정하기 전에 reasoning을 출력하도록 합니다.
    • tool 호출 전후의 상태 변화를 log로 남겨 audit이 가능하도록 합니다.

ACI 품질

  • ACI(Agent-Computer Interface)는 agent와 환경 사이의 interface, 즉 tool의 schema와 description입니다.
    • tool 이름과 parameter 이름은 model 입장에서 분명해야 합니다.
    • description에는 사용 예시, edge case, 입력 형식, 다른 tool과의 경계가 포함되어야 합니다.
    • SWE-bench agent를 만들 때 Anthropic은 prompt보다 tool 설계에 더 많은 시간을 들였습니다.
  • poka-yoke(실수 방지) 원칙을 적용합니다.
    • relative path가 혼란을 일으키면 absolute path만 받도록 schema를 바꿉니다.
    • 잘못된 인자가 들어올 수 없는 형태로 parameter를 설계합니다.

Agent Loop와 Harness의 관계

  • agent loop는 harness의 가장 안쪽 골격이며, harness의 다른 구성 요소들은 모두 agent loop를 감싸거나 보강하는 layer입니다.
    • file system은 loop가 session을 넘어 상태를 유지하게 합니다.
    • sandbox는 loop 안에서 실행되는 code를 격리합니다.
    • context 관리(compaction, offloading, skill)는 loop가 길어질 때 추론 품질을 유지합니다.
    • sub-agent는 loop 안에서 새 loop를 spawn하여 context를 격리합니다.
    • hook과 back-pressure는 loop의 특정 시점에 자동 검증을 끼워 넣습니다.
flowchart TB
    subgraph harness[Harness]
        subgraph loop[Agent Loop]
            llm[LLM] --> tool_call_node[Tool Call]
            tool_call_node --> observe_node[Observation]
            observe_node --> llm
        end
        loop --- filesystem[File System]
        loop --- sandbox[Sandbox]
        loop --- context_mgmt[Context 관리]
        loop --- subagent[Sub-Agent]
        loop --- hook[Hook과 Back-Pressure]
    end
  • agent loop를 먼저 깊이 이해해야 harness 전체의 설계 의도가 이해됩니다.
    • file system, sandbox, context 관리, sub-agent, hook은 각각 agent loop의 어떤 한계를 보완하는지를 기준으로 도출된 결과물입니다.
    • 즉 harness engineering은 “agent loop를 어떻게 안정적으로 운영할 것인가”에 대한 응답입니다.

Reference


목차