콘텐츠로 이동

에이전트 오케스트레이션

분류: Layer 12 - AI 시스템 & LLM 애플리케이션 | 선수지식: L12-20 (Prompt), L12-40 (RAG), L12-50 (Tool calling)

에이전트 오케스트레이션 — Workflow vs Agent, Multi-Agent, Memory, Planning

섹션 제목: “에이전트 오케스트레이션 — Workflow vs Agent, Multi-Agent, Memory, Planning”

LLM 에이전트는 LLM + tools + memory + 자율적 결정 루프의 조합이며, 워크플로우(고정 흐름)와 에이전트(LLM 자율 결정)의 스펙트럼에서 운영 요구에 맞는 패턴을 선택한다.

  • 2024-2026 LLM 운영의 핵심: 단순 chat·RAG에서 multi-step·tool-using agent로 이동
  • Workflow vs Agent 결정: Anthropic “Building effective agents” — 대부분 workflow로 충분, agent는 신중히
  • 비용·latency 폭증 위험: agent loop는 LLM 호출 N회 누적 → 비용·실패 모두 ↑
  • 운영 패턴: state machine·event-driven·observability·error recovery
  • 평가: SWE-Bench Verified·τ-bench·BFCL이 표준

3.0 Lineage — 단일 LLM·도구 호출만으로 부족했던 이유

섹션 제목: “3.0 Lineage — 단일 LLM·도구 호출만으로 부족했던 이유”

L12-20(Prompt), L12-40(RAG), L12-50(Tool calling)까지의 패턴은 모두 단일 LLM 호출의 입출력 보강에 머물렀다. 한계가 드러난 지점:

  • 단계 수가 사전에 정해지지 않는 작업에서 깨졌다. 예: “버그 리포트 → 관련 파일 탐색 → 수정 → 테스트 재실행”. Tool calling은 1회 호출만 모델링하므로, 다음 step을 결정할 주체가 없다 (Anthropic 표현: “open-ended problems where it’s difficult or impossible to predict the required number of steps”).
  • 중간 결과에 따른 분기가 외부 코드로 hardcode되어야 했다. RAG는 retrieve → answer 2-step 고정이고, retrieve가 빈 결과를 반환하면 “다시 다른 query로 retry” 같은 적응 동작이 불가능.
  • 상태가 호출 사이를 건너 살아남지 못함 — context window 안에서만 유효. 사용자 프로필·과거 결정 등 세션 간 정보를 다루려면 외부 store + retrieval 정책이 별도로 필요했다.

Agent orchestration이 푸는 메커니즘:

  • 자율 결정 loop (while not done: thought → action → observation → state update)으로 단계 수를 LLM이 동적으로 결정 (§3.3).
  • State machine 명시화 (LangGraph 등)로 중간 분기·재시도·checkpoint를 코드 경로 밖에서 표현 (§3.8).
  • Short/Long-term memory 분리로 세션 간 정보를 외부 store(Mem0, Letta, Zep)에 위임 (§3.4).

단, 이 자율성이 단계 수 = 비용으로 직결되므로 §3.9·§3.14의 cost runaway가 등장한다. Anthropic 권고가 “workflow가 default, agent는 신중히”인 이유. 출처: Anthropic, Building effective agents (2024-12).

3.1 Workflow vs Agent — Anthropic 분류 (2024-12)

섹션 제목: “3.1 Workflow vs Agent — Anthropic 분류 (2024-12)”

Anthropic의 “Building effective agents”가 정착시킨 분류.

LLM과 tools를 사전 정의된 코드 경로로 오케스트레이션.

  • 결정성·재현성·디버깅 좋음
  • 대부분의 production 작업에 충분
  • 패턴: prompt chaining, routing, parallelization, orchestrator-workers, evaluator-optimizer

여기서 말하는 workflow는 “LLM application pattern”이다. Temporal, Step Functions 같은 일반 workflow engine은 결제·승인·배치처럼 긴 비즈니스 절차를 실행하고 복구하는 인프라 계층이고, durable execution은 그 engine이 장애 후에도 이어 달릴 수 있게 만드는 실행 의미론이다. Agent orchestration은 그 위나 옆에서 LLM이 어떤 step·tool·worker를 선택할지를 다룬다. 즉 같은 “오케스트레이션”이라도 관심사가 다르다.

주 질문대표 도구/패턴
일반 workflow engine오래 걸리는 업무 절차를 어떻게 실행할까?Temporal, Step Functions, Airflow
Durable executionworker crash 후 어디서 어떻게 재개할까?Temporal history/replay, checkpoint
LLM workflow pattern정해진 LLM/tool 단계를 어떻게 조합할까?chaining, routing, evaluator loop
Agent orchestration다음 행동을 LLM이 언제 자율 결정하게 할까?ReAct loop, planner, multi-agent

분산 시스템 관점에서는 이 구분이 중요하다. workflow engine은 queue, retry, timer, idempotency, consistency 같은 L6~L9 문제를 숨기지 않고 실행 모델로 묶어준다. agent orchestration은 그 실행 모델 위에서 모델의 자율성을 얼마나 허용할지 정한다. CAP·일관성·네트워크 장애 직관은 L9 분산 시스템 기초를 참조하면 된다.

LLM이 자율적으로 다음 행동 결정, 자기 작업 흐름·도구 사용 제어.

  • 동적·유연하나 비용·실패 ↑
  • 도구·환경 피드백을 받아 동작 조정 (loop)
  • production은 신중하게 (Anthropic: “agents shine for ill-defined, open-ended problems”)
Workflow가 적합:
- 작업이 잘 정의됨 (명확한 입력·출력)
- 결정성·디버깅 중요
- 비용·latency 예측 필요
Agent가 적합:
- 사전에 단계 수를 알 수 없음
- 복잡한 multi-step + tool 사용
- 모델의 자율 판단이 가치
- production에서는 sandboxing·휴먼 휴먼 검토 결합

3.2 Workflow 5대 패턴 (Anthropic 분류)

섹션 제목: “3.2 Workflow 5대 패턴 (Anthropic 분류)”

작업을 N개 step으로 분해, 각 step LLM 호출 결과를 다음 step 입력으로.

Step 1: 마케팅 카피 작성
Step 2: 톤 검사 (gate) → 통과 못하면 Step 1로
Step 3: 다국어 번역

입력 분류 후 적절한 핸들러로.

사용자 질문 → Router (작은 LLM)
├─ 일반 → cheap model
├─ 코드 → code-specialized
└─ 의료 → expert workflow

여러 LLM 호출을 동시에 → 결과 합산.

  • Sectioning: 작업을 독립 sub-task로 분할
  • Voting: 같은 작업 N번 후 majority

중앙 LLM(orchestrator)이 sub-task 동적 결정·worker LLM에 위임.

사용자 요청 → Orchestrator
├─ Plan: "검색 + 분석 + 글쓰기 필요"
├─ Worker A: 검색
├─ Worker B: 분석
└─ Worker C: 글쓰기 → Orchestrator 통합

한 LLM이 응답 생성, 다른 LLM이 평가·피드백 → 반복.

  • 번역·코드 리뷰·창작에서 효과적
  • 명확한 평가 기준이 있을 때

Evaluator-Optimizer는 넓게 보면 critic loop다. 초안 생성자(generator)가 산출물을 만들고, 비평자(critic/evaluator)가 기준에 맞춰 결함을 찾은 뒤, 수정자(optimizer/reviser)가 다시 고친다.

draft = Generator(input)
for i in range(max_rounds):
critique = Critic(draft, rubric)
if critique.pass:
break
draft = Reviser(draft, critique)
return draft

대표 변형:

  • Evaluator-Optimizer: 하나의 산출물을 rubric으로 평가하고 반복 개선. 코드 리뷰·번역·요약 품질 개선에 적합
  • Debate → Review → Revise: 서로 다른 관점의 agent가 찬반·대안을 만든 뒤, judge가 쟁점을 정리하고 reviser가 최종안 작성
  • Self-Refine: 같은 모델이 자기 산출물을 비판·수정. 저렴하지만 같은 편향을 반복할 위험
  • Cross-Model Critic: generator와 critic을 다른 모델로 분리. 비용은 늘지만 blind spot이 줄어듦

적용 전제는 “비평 기준이 코드나 체크리스트로 표현 가능해야 한다”는 점이다. 기준이 모호하면 critic은 실제 품질보다 말투·길이·자신감 같은 표면 신호에 끌린다.

while not done:
thought = LLM(state) # 다음 행동 결정
action = parse_action(thought) # tool call
obs = execute(action) # tool 실행
state = update(state, action, obs)
if termination_condition(state):
break
  • LLM: 사고·결정 엔진
  • Tools (L12-50): 외부 세계 액션
  • Memory: 단·장기 정보 저장
  • Planning: 작업 분해
  • Termination: 종료 조건 (max_iter, success signal)

현재 conversation·tool 호출 history. context window 안.

  • 너무 길어지면 비용·lost-in-middle
  • summarization으로 압축
  • relevant 부분만 retrieve해 prompt에 (selective)

여러 session 사이에 유지되는 정보. 외부 store (vector DB, key-value store).

  • 사용자 프로필·선호 (예: “사용자는 한국어 답변 선호”)
  • 과거 대화 요약
  • 학습한 도메인 지식
  • 표준 도구: Mem0, Letta (formerly MemGPT), Zep
  • Episodic: 특정 사건 (when/where/who/what)
  • Semantic: 추상화된 지식 (“Python은 동적 타입”)
1. LLM이 전체 plan 생성 (high-level steps)
2. 각 step을 sequential로 실행
3. 실패 시 replanning

생각·행동·관찰 명시 루프.

여러 경로 동시 탐색·평가.

작업 후 자기 비판 → 개선 (Reflexion).

[Supervisor agent]
├─ [Researcher] (검색)
├─ [Coder] (코드 작성)
└─ [Reviewer] (검토)
  • supervisor가 작업 분배·통합
  • 가장 일반적인 패턴

여러 agent가 동등 관계로 자유 통신. 복잡·비용 ↑.

agent A → agent B → agent C 단방향. workflow에 가깝지만 각 agent가 자율 결정.

Anthropic·OpenAI 모두 “먼저 single agent 시도, 부족하면 multi-agent”. multi-agent는 communication overhead·debugging difficulty 多.

다음 조건이 여러 개 동시에 맞을 때만 multi-agent를 고려한다.

  • 작업 분해가 자연스럽다: researcher, planner, coder, reviewer처럼 역할별 산출물이 분리된다.
  • 병렬 탐색 이득이 크다: 서로 다른 검색 경로·가설·설계안을 동시에 비교해야 한다.
  • 컨텍스트가 너무 넓다: 단일 agent context window에 모든 근거·파일·대화가 안정적으로 들어가지 않는다.
  • 검토 관점이 독립적이다: 보안 리뷰, UX 리뷰, 테스트 리뷰처럼 failure mode가 다르다.
  • 추가 비용을 정당화할 task value가 있다: 10분 줄이는 자동화보다, 고가치 리서치·장기 작업에 적합하다.

반대로 다음 조건이면 쓰지 않는다.

  • 작업이 선형적이다: 한 파일 수정, 짧은 요약, 단순 분류는 workflow 또는 single agent가 낫다.
  • 공유 컨텍스트 의존이 크다: 모든 참여자가 같은 세부 상태를 알아야 하면 message passing 비용이 폭증한다.
  • 통합 기준이 모호하다: 여러 agent 산출물을 합칠 judge 기준이 없으면 최종 품질이 운에 가까워진다.
  • latency·비용 SLA가 빡빡하다: agent 간 대화 turn 수가 예측 불가능해진다.
  • 권한 있는 action이 많다: 여러 agent가 파일·DB·외부 API를 동시에 만지면 audit·rollback이 어려워진다.

Anthropic 자체 research system 운영 보고 (Claude Opus 4 lead + Sonnet 4 subagents):

  • 토큰 사용: agent는 chat 대비 약 , multi-agent는 약 15×. 비용이 task value를 정당화할 때만 손익이 맞는다.
  • 성능: 같은 multi-agent 구성이 single-agent Opus 4 대비 +90.2% (breadth-first 연구 query에서).
  • 적합한 작업: 병렬화 가능·single context window 초과·서로 독립 방향 탐색.
  • 부적합한 작업: 모든 agent가 같은 컨텍스트를 공유해야 하거나 의존 관계가 많은 경우 — 대표적으로 코딩 작업. 출처: Anthropic, Multi-Agent Research System (2025).

깨지는 시나리오 — Flappy Bird 사례 (Cognition)

섹션 제목: “깨지는 시나리오 — Flappy Bird 사례 (Cognition)”

“Flappy Bird clone 만들기”를 두 subagent로 분할했을 때 실제로 관찰된 실패:

  • Subagent 1은 작업을 오해해 Super Mario Bros 풍 배경을 만들었고, Subagent 2가 만든 새 asset과 시각적 스타일이 충돌.
  • 최종 통합 agent가 incompatible output을 합치지 못해 작업 실패.

원인: subagent들이 서로의 결정·암묵적 가정을 보지 못함. Cognition은 “현재 agents가 신뢰성 있는 multi-agent 협업을 못한다”고 결론짓고 single-threaded linear agent + 대화 압축 모델을 default로 권고. 다단계 작업이라도 multi-agent는 question-answering처럼 좁고 잘 정의된 sub-task에만 사용. 출처: Cognition, Don’t Build Multi-Agents (2025).

이 두 보고가 §3.13·§3.14의 “Multi-agent: 통신 overhead 多 — single agent 우선” 권고의 정량적·사례적 근거다.

프레임워크 생태계는 빠르게 바뀐다. 교과서적으로 외울 대상은 이름 목록보다 선택 기준이다.

선택 기준확인할 질문
명시적 상태·전이agent loop를 graph/state machine으로 볼 수 있는가
Tool 권한·격리allowlist, confirmation, audit log를 넣기 쉬운가
관측성step trace, token, latency, retry를 남기는가
UI·런타임 통합streaming, cancellation, human approval과 맞는가
모델·벤더 독립성provider 교체와 fallback이 가능한가

예시는 LangGraph, CrewAI, AutoGen, OpenAI/Claude SDK, Pydantic AI, Mastra, Vercel AI SDK, DSPy 등이지만 특정 이름은 참고일 뿐이다.

agent loop를 명시적 finite state machine으로 (LangGraph가 표준 구현).

States: [planning] → [tool_calling] → [observing] → [reflecting] → [done]
Transitions: 명시적 조건
Error: error state로 분기, retry/escalate
  • 디버깅·재현·복구 표준화

각 agent step을 이벤트(Kafka, NATS, AWS EventBridge)로 발행. 비동기·confirmable.

비가역 action(이메일·결제) 전 사용자 승인.

agent 권한은 “무엇을 할 수 있는가”보다 “실패했을 때 어디까지 피해가 번지는가”로 설계한다.

정책 영역기본값운영 기준
Tool allowlist작업별 최소 tool만 노출read/write/delete·외부 발송 tool을 분리
Confirmation비가역 action 전 승인결제, 이메일, 배포, DB write는 human gate
Sandbox파일·네트워크·secret 범위 제한repo/path allowlist, 임시 credential, egress 제한
Prompt/tool 방어untrusted input을 명령과 분리검색 결과·웹 페이지·사용자 첨부는 tool 지시로 불인정
Audit logstep·tool·argument·결과 기록rollback과 책임 추적이 필요한 action은 trace 필수

매 step state 저장. 실패 시 마지막 checkpoint부터 재개.

agent loop의 가장 큰 함정.

Total cost ≈ Σ (LLM 호출 비용) + Σ (tool 비용)
Total latency ≈ Σ (LLM latency) + Σ (tool latency) + 통신 overhead
  • Loop 무한 반복: max_iter 누락 → context 폭증
  • 동일 tool 반복: stuck → memory에 history 명시
  • 불필요한 sub-agent: workflow로 충분한데 agent 사용
  • Reasoning 모델 + Multi-agent: 비용 자릿수 폭증
  • Long context: 매 step prompt가 누적되어 비싸짐
  • Workflow 우선: 가능하면 workflow로
  • Smaller model 라우팅: 단순 단계는 작은 모델 (L12-70)
  • Prompt caching: 시스템 prompt·tool definition은 caching
  • Tool result 압축: 큰 tool output을 summarize
  • Termination 명시: 명확한 종료 조건
  • Parallel tool calling (L12-50 §3.4)
  • SWE-Bench Verified (500): GitHub 이슈 해결 — 코드 agent 표준
  • τ-bench / tau-bench: multi-turn tool agent (retail·airline)
  • BFCL v3: tool calling 정확도
  • WebArena, OSWorld, GAIA: web/OS 자동화
  • AgentBench: 다양 도메인
  • Trajectory eval: agent의 step-by-step trace 검토
  • Trace observability: LangSmith, Langfuse, Arize, OpenLLMetry, Weights & Biases
  • Cost·latency dashboard: 평균 step 수, 평균 비용/요청
  • Success rate: 작업 완료 여부
  • Recovery rate: 오류 후 복구 성공

critic loop는 “평가자가 있으니 안전하다”가 아니라, 평가자 자체도 eval 대상이다.

  • Rubric anchoring: critic prompt에 평가 기준·반례·통과/실패 예시를 고정한다.
  • Judge bias 측정: 길고 자신감 있는 답변, 자기 모델이 만든 답변, 먼저 제시된 답변을 과대평가하는지 샘플링한다.
  • Golden set: 사람이 이미 판정한 20~100개 사례로 critic의 precision/recall을 본다.
  • Disagreement log: generator pass, critic fail, human pass 같은 불일치를 따로 모아 rubric을 고친다.
  • Final human gate: 법무·보안·비용 집행처럼 고위험 action은 critic loop 후에도 사람이 승인한다.
  • Stuck loop: 같은 tool 반복 → max_iter, scratchpad
  • Wrong tool 선택: tool description 부족 → schema 강화
  • Memory contamination: long-term memory에 잘못된 정보 → memory 검증·삭제 정책
  • Goal drift: 처음 목표에서 멀어짐 → 주기적으로 원본 query 재확인
  • Cost runaway: budget alert 누락 → 호출당·요청당 한도 설정
  • Observation overflow: tool output이 매우 길 → summarization
  • Permission abuse: agent가 의도하지 않은 작업 수행 → allowlist + confirmation

Memory Contamination 진단·복구 절차

섹션 제목: “Memory Contamination 진단·복구 절차”

Memory contamination의 주요 증상과 구체적인 디버깅·복구 절차:

증상 식별

증상 1 (cross-thread 오염):
- agent가 다른 사용자/세션의 정보를 반복해서 인용
- thread_id를 공유하거나 session 간 MemorySaver를 재사용했을 때 발생
- 로그에서 "Retrieved memory from thread_id=shared" 같은 공유 thread 흔적 확인
증상 2 (상태 누적으로 인한 잘못된 기억):
- agent가 이전 turn의 잘못된 tool 결과를 계속 사실로 사용
- 메시지 리스트가 무한 증가하면서 오래된 오류 정보가 남아 있음
- 로그: state["messages"] 길이가 매 호출마다 N씩 증가

디버깅 단계 (LangGraph)

# 1. 현재 thread 상태 전체 열람
config = {"configurable": {"thread_id": "my-thread"}}
state = graph.get_state(config)
print(state.values) # 전체 state 덤프
print(len(state.values["messages"])) # 메시지 누적량 확인
# 2. checkpoint 이력 검토 (어느 단계부터 오염됐는지 확인)
history = list(graph.get_state_history(config))
for checkpoint in history:
print(checkpoint.created_at, checkpoint.values.get("messages", [])[-1])
# 3. 오염된 checkpoint 이전 시점으로 state 수정
# history[-N] = 오염 이전 시점
clean_checkpoint = history[-3] # 예: 3단계 이전
corrected_config = graph.update_state(
clean_checkpoint.config,
values={"messages": clean_checkpoint.values["messages"]}
)
# 수정된 state에서 재실행
result = graph.invoke(None, corrected_config)

예방 코드 (상태 크기 제한)

# messages reducer에서 최근 N개만 유지
def trim_messages(state):
MAX_MESSAGES = 20
if len(state["messages"]) > MAX_MESSAGES:
# 시스템 메시지는 유지, 나머지 오래된 것 제거
state["messages"] = state["messages"][:1] + state["messages"][-MAX_MESSAGES:]
return state

출처: LangGraph Memory Leakage Causes and Solutions, LangGraph Time Travel Debugging

증상 식별

증상:
- agent의 최종 답변이 원본 사용자 질문과 무관한 주제로 수렴
- 특히 step 10+ 이후에 자주 발생 (컨텍스트 누적으로 최초 목표가 희석)
- 로그에서 tool call argument가 초기 query와 무관한 키워드를 포함
- Trace에서 "현재 작업" 노드의 input이 원본 query와 의미적으로 다름
원인:
- long context에서 시스템 프롬프트가 후반부 대화에 묻힘 (lost-in-middle)
- intermediate tool output이 새로운 "목표"처럼 인식됨

디버깅 단계

# LangSmith / Langfuse trace에서 확인할 항목
# 1. 매 step의 LLM input 첫 번째 user message가 원본 query인지 확인
# 2. tool call arguments가 원본 query 키워드를 포함하는지 확인
# Goal anchor 패턴: 매 N step마다 원본 query를 state에서 재주입
GOAL_ANCHOR_INTERVAL = 5 # 5 step마다
def goal_anchor_node(state):
step = state.get("step_count", 0)
if step % GOAL_ANCHOR_INTERVAL == 0 and step > 0:
original_goal = state["original_query"]
anchor_msg = f"[Goal Reminder] 원래 목표: {original_goal}"
state["messages"].append({"role": "system", "content": anchor_msg})
state["step_count"] = step + 1
return state

복구

# goal drift 감지 시: checkpoint rollback + 원본 query 재주입
states = list(graph.get_state_history(config))
# drift 이전 checkpoint 식별 (수동 검토 or trajectory eval 결과 기반)
pre_drift = states[-5] # 예: 5단계 이전
graph.update_state(
pre_drift.config,
values={"messages": pre_drift.values["messages"] +
[{"role": "system", "content": f"원래 목표로 돌아갑니다: {original_query}"}]}
)

출처: LangGraph Time Travel Debugging (DEV Community)

o1·DeepSeek-R1·Claude 4 thinking 같은 reasoning 모델은 자체 CoT 내장 → agent의 planning에 강함.

  • 동일 작업에 일반 모델 multi-step vs reasoning 모델 single-step 비용 비교
  • reasoning 모델은 token 비용 5~20× 비싸지만 step 수 적음 → 합산이 더 싼 경우 多 (경험적 추정; 작업 복잡도에 따라 다름)
  • L11-90 §3.13의 RLVR로 reasoning 모델은 verifiable rewards에 최적화 — 코드·수학 agent에서 강함

3.13 깨지는 조건 정량 표 (운영 결정용)

섹션 제목: “3.13 깨지는 조건 정량 표 (운영 결정용)”
기법효과 발휘 범위깨지는 조건
Workflow명확한 입력·출력step 수 사전에 알 수 없으면 → agent
Agent (single)ill-defined·multi-stepstep 30+ → cost runaway 위험
Multi-agent명확히 다른 역할 (3+) + 독립 병렬 탐색토큰 ~15× (Anthropic 보고). 공유 컨텍스트·의존 多·코딩 작업에서 깨짐 (Flappy Bird 사례, Cognition)
ReActtool 자주 호출단발 답변엔 오버헤드
Plan-and-Execute사전 계획 가능계획 변경 잦으면 replanning 비용
Tree-of-Thoughts복잡 puzzle단순 작업 비용 5~20× (경험적 추정)
LangGraphstate machine 명시화빠른 prototype엔 CrewAI가 더 단순
Reasoning model 단발복잡 reasoningtoken 비용 5~20× — 단순 작업엔 일반 모델 (경험적 추정)
Max_iter=10표준 agent loop매우 복잡 multi-step엔 부족

정량 수치 주석: “cost 520ד는 특정 단일 벤치마크 기반이 아닌 경험적 추정 범위다. 실측 참고: AI Agent Token Cost Benchmark (WisGate)에 따르면 agentic 시스템은 단순 chat 대비 530× 토큰을 소모하며, multi-agent는 단일 agent 대비 2~5× 추가 소모. Multi-Agent vs Single-Agent Coding (vibecoding.app)에 따르면 multi-agent 방식이 SWE-bench Verified에서 약 72.2% vs 65% 성능을 보이나 토큰 비용은 더 높다.

3.14 Cost·Latency 정량 비교 (운영 결정 표)

섹션 제목: “3.14 Cost·Latency 정량 비교 (운영 결정 표)”

절대 금액은 모델 버전·가격표·컨텍스트 길이에 따라 쉽게 낡는다. 운영 판단은 아래 식과 실측 dashboard로 한다.

total_cost ~= Σ(model_input_tokens + model_output_tokens)
+ Σ(tool/API cost)
+ retry_count × 평균 step cost
total_latency ~= critical_path(LLM calls + tool calls + human wait)
  • single agent: step 수와 retry가 비용을 지배한다.
  • multi-agent: 병렬 탐색 이득이 있어도 agent 간 message·merge 비용이 추가된다. Anthropic 자체 research system 보고처럼 chat 대비 agent는 약 4×, multi-agent는 약 15× 토큰을 쓸 수 있다.
  • reasoning model 단발: 호출 수는 줄지만 호출당 token 단가와 출력 길이가 커질 수 있다.
  • 반복 작업: 빈도가 높고 입력·출력이 안정되면 workflow, 캐시, smaller model routing, fine-tune을 먼저 검토한다.

결정: 빈번 작업 → fine-tune·workflow. 비정형 작업 → reasoning model 또는 agent.

증상정량 신호원인복구
Stuck loopiter > 20LLM stuckmax_iter, scratchpad history 명시
Goal drift답이 원본 query와 무관컨텍스트 누적매 N step마다 원본 query 재확인
Memory contamination잘못된 정보 반복long-term memory 오염memory 검증·삭제 정책, fact-check
Cost runaway호출당 비용 10×↑budget 미설정per-request budget, alert
Observation overflowtool output 매우 김summarization 누락tool output cap·summarize
Permission abuseagent가 의도 외 작업allowlist 미적용tool allowlist + confirmation
Multi-agent stuck둘 사이 무한 대화termination 부재turn 한도, supervisor가 종료 결정
Judge biascritic이 그럴듯한 답만 통과rubric·golden set 부재blind eval, human spot check

critic loop는 품질을 올리지만 종료 조건이 없으면 “더 비판 → 더 수정”만 반복한다. production에서는 아래 guardrail을 함께 둔다.

  • max_rounds: 보통 1~3회. 3회 이후 개선 폭이 작으면 중단
  • quality threshold: rubric 점수 ≥ 0.85 또는 모든 must-have 항목 통과 시 종료
  • delta threshold: 이전 round 대비 점수 개선이 0.02 미만이면 수렴으로 판단
  • budget cap: 요청당 최대 토큰·달러·wall-clock time을 선차감 방식으로 관리
  • no-new-issues rule: 수정 후 새 critical issue가 생기면 rollback 또는 human escalation
  • judge disagreement: 두 critic이 충돌하거나 critic confidence가 낮으면 반복 대신 사람에게 넘김

간단한 정책 예:

max_rounds = 2
max_cost_per_request = $0.20
stop if score >= 0.85 and critical_issues == 0
stop if score_delta < 0.02
escalate if security_or_payment_action == true

3.16 Agent의 일반 매핑 (Transferable Pattern)

섹션 제목: “3.16 Agent의 일반 매핑 (Transferable Pattern)”

LLM agent = “state + tool + LLM 결정 loop”. 다른 시스템과 같은 패턴.

Agent 구성요소일반 시스템 매핑
State machine (LangGraph)workflow engine (Temporal, Step Functions)
Agent loopevent-driven processing, control loop (PID)
Tool callservice mesh, RPC
Memory (short/long)session cache + persistent store
Multi-agent supervisororchestrator pattern, coordinator
CheckpointDB transaction snapshot, save point
Trajectory evaldistributed trace replay (Jaeger, Datadog)
Self-Refineiterative refinement (gradient descent, A/B loop)

일반 공식: “결정 → 행동 → 관찰 → 갱신”의 control loop가 agent·로봇·제어 시스템·feedback loop 전반에 공통이다. LLM agent는 결정자가 LLM이라는 점만 다르다.

본문 적용 — Stuck loop 진단을 distributed trace로 푸는 시나리오:

§3.11에서 본 “stuck loop” 증상은 분산 시스템의 “재시도 폭주(retry storm)“와 같은 패턴이다. Datadog/Jaeger에서 같은 service가 동일 downstream을 N회 호출하는 trace를 발견하면, 회로 차단(circuit breaker) + jitter backoff로 대응한다. Agent에 동일하게 매핑하면:

  • trace replay: LangSmith에서 동일 tool이 같은 argument로 N회 호출되는 span을 grep (예: tool_name=search_docs AND arg.query="...")
  • circuit breaker 등가물: scratchpad에 “이 tool을 X argument로 이미 호출했다” 기록 후, LLM prompt에 history 명시 — RPC 회로 차단의 “open state”에 해당
  • 결정 결과: §3.6의 사내 코드 리뷰 agent에서 search_docs가 동일 query로 3회 반복되면 termination 트리거 (turn budget = circuit breaker threshold)

즉 §3.13·§3.15의 silent failure 표를 그냥 외우는 게 아니라, 분산 시스템 엔지니어가 이미 가진 “재시도 폭주 → 회로 차단” 직관을 그대로 옮겨 쓸 수 있다.

운영 시나리오 — 사내 코드 리뷰 agent 도입 결정 (예시)

섹션 제목: “운영 시나리오 — 사내 코드 리뷰 agent 도입 결정 (예시)”
상황: GitHub PR 자동 리뷰 도입 검토. 평균 PR 5개/일, 한국어 PR 60%.
선택지:
A. Workflow (prompt chaining): PR diff → review prompt → comment
- 결정성·재현성·debug 좋음
- 작업 복잡도 낮음, 충분
B. Single agent + tools (read_file, run_test, search_docs):
- 자율 결정 (tool loop)
- 비용 5~20× ↑
C. Multi-agent (reviewer + tester + security):
- 통신 overhead 多
- 사내 작업엔 과함
D. Reasoning model (o3, single shot):
- 자체 사고, 단순
- 토큰 비용 5~20× ↑
선택: A (Workflow). PR review는 잘 정의된 작업.
대안 비선택:
- B는 tool loop 비용 폭증, 결정성 약함
- C는 communication overhead, 단일 agent로 충분
- D는 비용 자릿수 ↑
silent failure (§3.15):
- stuck loop, goal drift, cost runaway, multi-agent stuck

§3.1 Workflow vs Agent + §3.13 깨지는 조건 + §3.14 cost 비교 + §3.15 silent failure 모두 적용.

  • 코드 어시스턴트 (Cline·Cursor·Devin·Claude Code)
  • 데이터 분석 agent
  • 고객 지원 자동화 (Tier 1)
  • 사내 자동화 (Slack 봇이 다단계 작업)
  • web·OS 자동화 (Operator·Computer Use)
  • research agent (논문 검색·요약)

플랫폼 엔지니어가 agent를 운영할 때 다음에 도움된다.

  • Workflow vs Agent 결정: 잘 정의된 작업은 workflow. agent는 ill-defined·open-ended에만
  • State machine 패턴: LangGraph 또는 자체 FSM으로 agent loop 명시화 — 디버깅·재현·복구
  • Observability: 매 step trace를 LangSmith/Langfuse로. cost·latency·success rate dashboard
  • Cost runaway 방어: max_iter, budget per request, alert
  • Single agent 우선: Anthropic 권고대로 multi-agent는 마지막
  • Reasoning 모델 도입 결정: token 비용 5~20× 증가 vs step 수 절감의 비교
  • Human-in-the-loop: 비가역 action 사용자 승인
개념 A개념 B차이점
WorkflowAgent코드 경로 결정 vs LLM 자율 결정. workflow가 default
Workflow engineAgent frameworkengine은 실행·복구 인프라, framework는 LLM step·tool 선택 구조
Durable executionAgent checkpointdurable execution은 history/replay 의미론, checkpoint는 agent state 저장 수단
Prompt chainingRouting순차 vs 분기
Orchestrator-WMulti-agent단일 LLM이 worker 호출 vs 동등 agent 다수
Single agentMulti-agent1개 LLM 자율 vs N개 협업. multi는 비용·debug ↑
Short-term memLong-term memcontext 안 vs 외부 store (Mem0, Letta, Zep)
EpisodicSemantic memory사건·시간 vs 추상화된 지식
ReActPlan-and-Executestep별 thought·action·obs vs plan 후 실행
State machineFree agent loop명시 transitions vs LLM 매번 결정
LangGraphCrewAIgraph state machine vs role-based multi-agent
Reasoning model일반 + CoT자체 사고 내장 vs prompt trigger
Critic loopAgent eval산출물 반복 개선 루프 vs 시스템 품질 측정 체계
CriticJudge결함 피드백 생성 vs 후보 간 판정·점수화
  • Workflow와 Agent의 차이를 결정성·비용·debug 관점에서 설명할 수 있다 (Anthropic 분류)
  • Workflow 5대 패턴(chaining/routing/parallelization/orchestrator-workers/evaluator-optimizer)을 작업에 매핑할 수 있다
  • Critic loop / evaluator-optimizer / debate-review-revise의 공통 구조(generator → critic → reviser)를 설명할 수 있다
  • ReAct·Plan-and-Execute·Tree-of-Thoughts·Self-Reflect 4가지 planning 전략의 차이를 말할 수 있다
  • Multi-agent를 써야 하는 조건(독립 병렬 탐색·역할 분리·컨텍스트 초과)과 쓰면 안 되는 조건(선형 작업·공유 컨텍스트 의존·SLA 제약)을 구분할 수 있다
  • State machine 패턴(LangGraph)이 production agent에서 가치 있는 이유를 설명할 수 있다
  • Agent의 cost·latency 폭증 원인 5종(loop·동일 tool·sub-agent·reasoning·long-context)을 식별할 수 있다
  • SWE-Bench Verified·τ-bench·BFCL의 측정 영역 차이를 구분할 수 있다
  • Stuck loop·goal drift·memory contamination·cost runaway 등 silent failure를 대응할 수 있다
  • Critic loop의 종료 조건(max_rounds·quality threshold·delta threshold)과 비용 상한을 설계할 수 있다
  • Judge bias를 golden set·blind eval·human spot check로 점검할 수 있다
  • Workflow 패턴: prompt chaining, routing, parallelization, orchestrator-workers, evaluator-optimizer
  • Critic loop: evaluator-optimizer, debate-review-revise, self-refine, Reflexion, LLM-as-a-judge, rubric anchoring, judge bias, golden set
  • Agent 패턴: ReAct, Plan-and-Execute, Tree-of-Thoughts, Reflexion, Self-Refine, Voyager
  • Memory: short-term, long-term, episodic, semantic, Mem0, Letta (MemGPT), Zep
  • Multi-agent: supervisor, swarm, sequential, hierarchical, role specialization, handoff, message passing, AutoGen, MetaGPT
  • Framework: LangGraph, CrewAI, AutoGen, OpenAI Agents SDK, Claude Agent SDK, Pydantic AI, Mastra, Vercel AI SDK
  • Observability: LangSmith, Langfuse, Arize Phoenix, OpenLLMetry, OpenAI tracing, Helicone, W&B Traces
  • Eval: SWE-Bench Verified, τ-bench, BFCL v3, WebArena, OSWorld, GAIA, AgentBench
  • Coding agents: Devin, Claude Code, Cline, Cursor, Aider, OpenHands
  • LangChain RunnableSequence로 prompt chaining 3-step pipeline 구현
  • Router pattern: 사용자 질문을 작은 LLM이 분류 → 해당 핸들러 호출

목표: get_weather, get_news tool을 가진 ReAct agent를 LangGraph state machine으로 구현하고 실행 trace를 확인한다.

# 설치: pip install langgraph langchain-openai
from typing import Annotated
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition
from langgraph.checkpoint.memory import MemorySaver
from typing_extensions import TypedDict
# 1. State 정의
class State(TypedDict):
messages: Annotated[list, add_messages]
# 2. Tool 정의
@tool
def get_weather(city: str) -> str:
"""Get current weather for a city."""
# 실제 구현에서는 OpenWeatherMap API 등 사용
return f"{city}: 맑음, 23°C"
@tool
def get_news(topic: str) -> str:
"""Get latest news about a topic."""
return f"{topic} 관련 최신 뉴스: [뉴스 항목 1], [뉴스 항목 2]"
tools = [get_weather, get_news]
# 3. LLM 설정
llm = ChatOpenAI(model="gpt-4o-mini").bind_tools(tools)
# 4. Graph 노드 정의
def agent_node(state: State):
return {"messages": [llm.invoke(state["messages"])]}
# 5. Graph 구성 (state machine)
graph_builder = StateGraph(State)
graph_builder.add_node("agent", agent_node)
graph_builder.add_node("tools", ToolNode(tools=tools))
graph_builder.add_edge(START, "agent")
graph_builder.add_conditional_edges("agent", tools_condition) # tool call이면 tools, 아니면 END
graph_builder.add_edge("tools", "agent")
# 6. Checkpointer 포함 컴파일
checkpointer = MemorySaver()
graph = graph_builder.compile(checkpointer=checkpointer)
# 7. 실행
config = {"configurable": {"thread_id": "session-001"}}
result = graph.invoke(
{"messages": [{"role": "user", "content": "서울 날씨와 AI 관련 뉴스를 알려줘"}]},
config=config
)
print(result["messages"][-1].content)

예상 출력 (정상 동작)

# 실행 trace (LangSmith 또는 print로 확인)
[agent] → tool_call: get_weather(city="서울")
[tools] → observation: "서울: 맑음, 23°C"
[agent] → tool_call: get_news(topic="AI")
[tools] → observation: "AI 관련 최신 뉴스: ..."
[agent] → final_answer: "서울 날씨는 맑고 23°C입니다. AI 관련 뉴스로는 ..."
# 최종 메시지 출력
서울 날씨는 맑고 23°C입니다. AI 관련 뉴스로는 [뉴스 항목 1], [뉴스 항목 2]가 있습니다.

검증 절차

# "이것이 나오면 정상" 기준:
# 1. messages 리스트에 AIMessage → ToolMessage → AIMessage 순서가 있어야 함
assert any(m.type == "tool" for m in result["messages"]), "tool 호출이 없음"
# 2. 마지막 메시지가 AI의 최종 답변이어야 함
assert result["messages"][-1].type == "ai", "agent가 tool에서 멈춤"
# 3. Checkpoint 저장 확인
state = graph.get_state(config)
assert len(state.values["messages"]) > 0, "state가 저장되지 않음"
print("검증 통과: ReAct agent 정상 동작")

출처: LangGraph create_react_agent docs, LangGraph Tutorial (Medium)

  • LangGraph로 ReAct agent 구현 (get_weather + get_news tools). 위 코드 실행 후 예상 출력과 비교
  • CrewAI로 supervisor + 3 worker agent (researcher/writer/editor) 구현 — 같은 작업의 latency·비용 비교
  • Mem0 또는 Letta로 long-term memory 통합 — 같은 사용자에게 두 번째 대화 시 이전 정보 기억하는지

Checkpoint state 검증 방법

# 두 번째 대화 후 메모리 유지 확인
config = {"configurable": {"thread_id": "session-001"}} # 동일 thread_id 재사용
result2 = graph.invoke(
{"messages": [{"role": "user", "content": "아까 말한 날씨 다시 알려줘"}]},
config=config
)
# 이전 대화를 참조한 답변이 나오면 memory 정상 동작
# MemorySaver → 프로세스 재시작 시 초기화됨 (in-memory)
# PostgresSaver → 프로세스 재시작 후에도 유지 (production 권장)
  • 동일 작업(예: “이메일 답장 작성”)을 single agent vs supervisor + 3 worker로 비교 — latency·비용·품질

비용 측정 방법

# LangSmith 없이 토큰 수 직접 측정
from langchain_community.callbacks import get_openai_callback
with get_openai_callback() as cb:
result = graph.invoke({"messages": [...]}, config=config)
print(f"총 토큰: {cb.total_tokens}, 비용: ${cb.total_cost:.4f}")
print(f"입력 토큰: {cb.prompt_tokens}, 출력 토큰: {cb.completion_tokens}")
  • LangSmith 또는 Langfuse 통합 — agent trace dashboard 확인
  • cost·latency 분포 시각화

LangSmith 빠른 연동

Terminal window
export LANGSMITH_API_KEY="ls__..."
export LANGSMITH_TRACING=true
export LANGSMITH_PROJECT="agent-test"
# 이후 graph.invoke() 호출 시 자동으로 trace가 LangSmith에 저장됨
  • 같은 SWE-Bench-스타일 작업에 GPT-4o + multi-step vs o3 single-step 비교 — token 비용·step 수·정확도

Critic Loop — 문서 품질 개선 루프

섹션 제목: “Critic Loop — 문서 품질 개선 루프”
  • 같은 짧은 기술 설명을 대상으로 Generator → Critic → Reviser 2회 반복 구현
  • rubric을 5개 항목(정확성·누락·구체성·톤·위험한 주장)으로 고정
  • max_rounds=2, max_cost_per_request, score_delta < 0.02 종료 조건을 코드에 넣기
  • critic 모델을 같은 모델/다른 모델로 바꿔 judge bias 차이를 비교
  • 사람이 만든 golden set 10개로 critic 판정이 실제 품질과 맞는지 확인

간단한 상태 전이

[drafting] → [criticizing] → [revising]
↑ │ │
└── fail ------┘ │
pass or budget exhausted → [done]

관찰할 지표

round_count
score_before / score_after
score_delta
tokens_per_round
critic_disagreement_rate
human_override_rate
증상확인 항목조치
agent loop 멈추지 않음tools_condition이 END로 가지 않음max_iter 추가, 시스템 프롬프트에 종료 조건 명시
tool이 호출되지 않음llm.bind_tools(tools) 누락 확인bind_tools 추가
두 번째 대화에서 기억 없음thread_id가 다르거나 MemorySaver가 재생성됨동일 thread_id 재사용, saver 인스턴스 재사용
multi-agent가 single보다 나쁨communication overhead → LangSmith trace에서 agent 간 메시지 수 확인workflow로 단순화
cost runawayget_openai_callback() 으로 호출당 토큰 확인budget per request, alert, smaller model 라우팅
  1. Workflow(코드 경로) vs Agent(LLM 자율) 분류 (Anthropic) — 대부분 workflow로 충분, agent는 신중히.
  2. Workflow 5대 패턴은 LLM 단계 조합이고, workflow engine/durable execution은 실행·복구 계층이다.
  3. State machine·observability·human-in-the-loop가 production agent의 표준 패턴 (LangGraph 대표).
  4. Single agent 우선, multi-agent는 독립 병렬 탐색·역할 분리 이득이 비용·debug 난이도를 넘을 때만 쓴다.
  5. SWE-Bench Verified·τ-bench·BFCL이 평가 표준이고, cost runaway·goal drift·stuck loop·judge bias가 흔한 silent failure.

최종 수정: 2026-04-27