Split View: 루프 설계 — 무한 루프와 조기 포기 사이
루프 설계 — 무한 루프와 조기 포기 사이
- 같은 호출을 마흔 번 반복한 에이전트
- 루프는 하네스의 심장입니다
- 재시도 상한: 0도 무한도 답이 아닙니다
- 정지 조건 세 가지: 고정 스텝, 목표 체크, 확신도
- 확신도 기반 정지의 함정
- 에스컬레이션: 막히면 그냥 끝이 아니라
- 직접 연습하기
- 참고 자료
같은 호출을 마흔 번 반복한 에이전트
재시도 상한이 없는 하네스에서 에이전트가 존재하지 않는 파일을 마흔 번 연속으로 읽으려 한 기록을 상상해 보겠습니다. 구성한 예시지만, 조립 방식은 현실적입니다. 실패가 예외 문자열 그대로 돌아오니 모델은 원인을 모르고, 원인을 모르니 같은 시도를 반복하고, 상한이 없으니 아무도 멈추지 않습니다. 반대편 실패도 있습니다. 재시도가 0인 하네스는 일시적인 네트워크 오류 한 번에 끝낼 수 있던 과제를 버립니다.
루프 설계의 목표는 이 두 절벽 사이에 길을 내는 것입니다. 얼마나 다시 시도할지, 무엇을 근거로 멈출지, 막히면 어디로 올릴지. 세 가지 모두 코드로 배포되는 하네스의 결정입니다.
루프는 하네스의 심장입니다
Anthropic의 에이전트 구축 가이드의 구분을 빌리면, 에이전트는 모델이 환경의 피드백을 근거로 다음 행동을 스스로 정하는 시스템입니다. 단계를 미리 예측할 수 없는 열린 문제에 쓰라고 권하는 이유도, 비용이 커지고 오류가 누적될 수 있다고 경고하는 이유도 루프에 있습니다. 도구 호출의 결과가 매 스텝 현실의 근거를 제공하지만, 그 근거를 어떻게 소비할지는 하네스가 정합니다.
같은 가이드는 정지 조건, 이를테면 최대 반복 횟수를 명시하라고 권합니다. 당연한 조언처럼 들리지만, 운영에서 무너지는 지점은 대체로 이 당연한 층입니다. 루프의 자유도가 클수록 멈추는 규칙이 시스템의 안전판이 됩니다.
재시도 상한: 0도 무한도 답이 아닙니다
재시도는 실패의 종류에 따라 값이 달라지는 구매입니다. 일시적 실패에는 몇 번의 재시도가 싸게 과제를 살리고, 구조적 실패에는 어떤 재시도도 돈 낭비입니다. 문제는 모델이 그 구분을 스스로 하지 못할 때입니다. 3편에서 다룬 실패 반환 형식이 여기서 다시 등장합니다. 원인과 대안이 돌아오는 하네스에서 재시도는 다른 경로의 탐색이 되고, 예외 문자열만 돌아오는 하네스에서 재시도는 같은 실패의 반복 구매가 됩니다.
그래서 순서가 중요합니다. 실패 반환을 고치기 전에 상한만 올리면, 더 비싸게 같은 곳을 도는 루프를 얻습니다. 상한 자체는 과제의 변동성에 맞춰 낮게 시작해 근거가 생길 때만 올리는 쪽이 안전합니다.
정지 조건 세 가지: 고정 스텝, 목표 체크, 확신도
멈추는 규칙은 크게 세 계열입니다. 고정 스텝은 정해진 횟수를 채우면 끝냅니다. 구현이 공짜고 예산이 예측 가능하지만, 다 된 과제를 붙잡고 있거나 덜 된 과제를 놓아 버립니다. 목표 체크는 멈출 조건을 코드로 씁니다. 테스트가 통과하면, 산출물이 스키마를 만족하면 끝. 루프가 새지 않는 대신, 목표를 검증 가능한 형태로 적을 수 있어야 한다는 선불 비용이 있습니다. 확신도 정지는 모델에게 얼마나 확신하는지 물어 그 값으로 멈춥니다.
MAX_STEPS = 20 # 과제 복잡도에 맞춰 조정
for step in range(MAX_STEPS):
action = model.next_action(context)
if action.kind == "finish":
if goal_check(workspace): # 정지 조건은 코드로 쓴다
break
context.add("goal_check 실패: 테스트 2개가 아직 빨갛습니다")
continue
context.add(run_tool(action, retries=3))
else:
escalate("스텝 상한 도달", summary=context.progress_note())
세 계열은 배타적이지 않습니다. 실무의 안전한 조합은 목표 체크를 주 정지 조건으로 쓰고, 고정 스텝을 바깥의 안전판으로 두는 것입니다.
확신도 기반 정지의 함정
확신도 정지는 매력적입니다. 목표를 코드로 쓸 필요가 없고, 빠르고, 쌉니다. 함정은 정확히 그 지점에 있습니다. 자기 보고 확신도는 검증이 아니라 발화이고, 모델은 자신 있게 틀릴 수 있습니다. 그 경우 루프는 오답을 들고 정상 종료합니다. 실패가 기록에 실패로 남지 않는, 가장 나쁜 종류의 실패입니다.
확신도를 쓰려면 역할을 바꾸는 것이 안전합니다. 정지 신호가 아니라 라우팅 신호로. 확신도가 낮으면 더 싼 검증을 한 번 더 돌리거나 사람에게 올리는 트리거로 쓰고, 멈춤 자체는 검증 가능한 목표 체크가 결정하게 합니다. 확신은 참고 자료이지 심판이 아닙니다.
에스컬레이션: 막히면 그냥 끝이 아니라
정지 조건이 발동했는데 과제가 덜 끝났다면, 다음 행선지가 필요합니다. 아무 데도 없으면 지금까지의 진행이 그대로 증발합니다. 행선지는 두 곳입니다. 하나는 사람입니다. 이때 가치는 질문의 구체성에서 나옵니다. "막혔습니다"가 아니라 "A와 B 중 어느 쪽 스키마가 맞습니까"처럼, 진행 요약과 선택지를 함께 올려야 사람의 한 번의 답이 루프를 다시 굴립니다. 다른 하나는 서브에이전트입니다. 오염된 컨텍스트를 버리고 깨끗한 창에서 하위 문제만 다시 풀게 하는 것인데, 2편에서 본 것처럼 토큰 비용이 큽니다.
Anthropic의 멀티 에이전트 시스템 회고는 이 층의 실패를 구체적으로 나열합니다. 단순한 질의에 과한 노력을 쏟는 에이전트, 끝없이 이어지는 검색, 중복 작업. 처방도 루프 쪽입니다. 과제의 복잡도에 노력을 비례시키고, 위임할 때 목표와 출력 형식과 과제 경계를 명시하는 것. 에스컬레이션은 예외 처리가 아니라 루프 설계의 정규 부품입니다.
직접 연습하기
하네스 엔지니어링 RPG의 3티어 "루프 설계"가 이 글의 실습입니다. 재시도 없음부터 상한 없음까지 네 단계의 재시도 정책과 세 가지 정지 조건, 세 가지 에스컬레이션을 조합해 보면, 확신도 정지가 싸게 이기는 시나리오와 자신 있게 틀리는 시나리오를 모두 만나게 됩니다.
참고 자료
- Building effective agents — Anthropic, 2024-12-19 — 에이전트는 환경 피드백으로 스스로 진행하는 시스템이라는 정의, 열린 문제에 쓰라는 권고, 비용과 오류 누적 경고, 최대 반복 횟수 같은 정지 조건을 두라는 조언이 이 글에 있습니다.
- How we built our multi-agent research system — Anthropic, 2025-06-13 — 단순 질의에 대한 과투자, 끝없는 검색, 중복 작업 같은 루프 실패 사례와 과제 경계 명시라는 처방이 이 글에 있습니다.
- 서두의 마흔 번 반복 사례와 본문의 루프 코드는 설명을 위해 구성한 것입니다.
Loop Design — Between Infinite Loops and Giving Up Early
- The agent that repeated the same call forty times
- The loop is the heart of the harness
- The retry cap: neither zero nor infinity
- Three stopping conditions: fixed steps, goal checks, confidence
- The trap in confidence-based stopping
- Escalation: stuck should not mean done
- Practice it yourself
- References
The agent that repeated the same call forty times
Imagine a transcript, from a harness with no retry cap, in which an agent tries to read a nonexistent file forty times in a row. It is a constructed example, but the assembly is realistic. The failure comes back as a raw exception string, so the model does not know the cause; not knowing the cause, it repeats the same attempt; with no cap, nothing stops it. The opposite failure exists too. A harness with zero retries throws away a task it could have finished over one transient network error.
The goal of loop design is to cut a path between these two cliffs. How much to retry, on what grounds to stop, and where to raise things when stuck. All three are harness decisions deployed as code.
The loop is the heart of the harness
Borrowing the distinction from Anthropic's agent-building guide, an agent is a system in which the model decides its own next action based on feedback from the environment. The loop is why the guide recommends agents for open-ended problems whose steps cannot be predicted, and why it warns that costs grow and errors can compound. Tool results provide ground truth at every step, but how that ground truth is consumed is up to the harness.
The same guide recommends explicit stopping conditions, such as a maximum number of iterations. It sounds like obvious advice, but operations usually break at exactly this obvious layer. The more freedom the loop has, the more the stopping rules become the safety valve of the system.
The retry cap: neither zero nor infinity
A retry is a purchase whose value depends on the kind of failure. For transient failures, a few retries buy the task back cheaply; for structural failures, every retry is wasted money. The problem is that the model often cannot make that distinction on its own. The failure return format from part 3 reappears here. In a harness that returns causes and alternatives, a retry becomes exploration of a different path; in a harness that returns only exception strings, a retry is a repeat purchase of the same failure.
So the order matters. Raise the cap before fixing the failure return, and what you get is a loop that circles the same spot at higher cost. As for the cap itself, the safe move is to start low, matched to the volatility of the task, and raise it only when evidence arrives.
Three stopping conditions: fixed steps, goal checks, confidence
Stopping rules come in three families. Fixed steps end the run after a set count. Free to implement and budget-predictable, but it holds on to finished tasks and lets go of unfinished ones. A goal check writes the stopping condition as code: stop when the tests pass, when the artifact satisfies the schema. The loop stops leaking, at the upfront cost of having to state the goal in verifiable form. Confidence-based stopping asks the model how sure it is and stops on that value.
MAX_STEPS = 20 # tune to task complexity
for step in range(MAX_STEPS):
action = model.next_action(context)
if action.kind == "finish":
if goal_check(workspace): # write the stopping condition as code
break
context.add("goal_check failed: 2 tests are still red")
continue
context.add(run_tool(action, retries=3))
else:
escalate("step cap reached", summary=context.progress_note())
The three families are not exclusive. The safe combination in practice is a goal check as the primary stopping condition with fixed steps as the outer safety valve.
The trap in confidence-based stopping
Confidence stopping is attractive. No goal has to be written as code, and it is fast and cheap. The trap sits exactly there. Self-reported confidence is an utterance, not a verification, and a model can be confidently wrong. In that case the loop terminates normally while holding a wrong answer — the worst kind of failure, the kind that never shows up in the record as a failure.
If you use confidence, the safe move is to change its role: a routing signal, not a stop signal. Low confidence becomes a trigger to run one more round of cheap verification or to raise the case to a human, while the stopping itself is decided by a verifiable goal check. Confidence is a reference input, not the judge.
Escalation: stuck should not mean done
When a stopping condition fires and the task is unfinished, you need a next destination. If there is none, the progress so far simply evaporates. There are two destinations. One is a human — and the value there comes from the specificity of the question. Not "I am stuck" but "which schema is correct, A or B", with a progress summary and options attached, so that one human answer restarts the loop. The other is a subagent: throw away the polluted context and have the subproblem solved again in a clean window — which, as part 2 showed, carries a serious token cost.
Anthropic's multi-agent system retrospective lists the failures of this layer concretely: agents over-investing effort in simple queries, endless searches, duplicated work. The prescriptions are also loop-side: scale effort to the complexity of the query, and when delegating, state the objective, output format, and task boundaries. Escalation is not exception handling; it is a standard part of loop design.
Practice it yourself
Tier 3 of the harness engineering RPG, "Loop design", is the exercise for this post. Combine the four retry policies from none to unbounded, the three stopping conditions, and the three escalation paths, and you will meet both the scenario where confidence stopping wins cheaply and the one where it ends confidently wrong.
- Previous in the series: Tool surface design — one schema line moves the success rate
- Next in the series: The evaluator bottleneck — a weak grader caps the whole system
References
- Building effective agents — Anthropic, 2024-12-19 — the definition of agents as systems that proceed on environmental feedback, the advice to use them for open-ended problems, the cost and compounding-error warnings, and the recommendation of stopping conditions such as a maximum number of iterations are in this post.
- How we built our multi-agent research system — Anthropic, 2025-06-13 — loop failures such as over-investment in simple queries, endless searches, and duplicated work, and the prescription of explicit task boundaries, are in this post.
- The forty-repeats story at the top and the loop code in the body are constructed for explanation.