장기 실행 에이전트를 위한 하네스 — 컨텍스트 윈도우를 넘는 인수인계 설계
에이전트는 컨텍스트 윈도우가 끝날 때마다 기억이 리셋되는 교대 근무 엔지니어다. compaction만으로는 부족하다 — 한 번에 다 만들려다 중간에 끊기거나, 남이 만든 진척을 보고 섣불리 완료를 선언한다. 환경을 깔아두는 initializer agent와 한 번에 한 기능씩 진행하는 coding agent의 2단 구조, 그리고 피처 리스트 JSON·git 커밋·진행 로그·인간 사용자처럼 하는 엔드투엔드 테스트로 이를 잡는다.
Effective harnesses for long-running agents
생각 덩어리
기억 없는 교대 근무 — 장기 실행 에이전트 문제의 본질
As AI agents become more capable, developers are increasingly asking them to take on complex tasks requiring work that spans hours, or even days. However, getting agents to make consistent progress across multiple context windows remains an open problem.
The core challenge of long-running agents is that they must work in discrete sessions, and each new session begins with no memory of what came before. Imagine a software project staffed by engineers working in shifts, where each new engineer arrives with no memory of what happened on the previous shift.
Compaction만으로는 부족하다 — Opus 4.5도 원샷은 실패
Theoretically, given this setup, it should be possible for an agent to continue to do useful work for an arbitrarily long time.
However, compaction isn’t sufficient. Out of the box, even a frontier coding model like Opus 4.5 running on the Claude Agent SDK in a loop across multiple context windows will fall short of building a production-quality web app if it’s only given a high-level prompt, such as “build a clone of claude.ai.”
두 가지 실패 패턴 — 과욕, 그리고 섣부른 완료 선언
First, the agent tended to try to do too much at once—essentially to attempt to one-shot the app. Often, this led to the model running out of context in the middle of its implementation, leaving the next session to start with a feature half-implemented and undocumented.
A second failure mode would often occur later in a project. After some features had already been built, a later agent instance would look around, see that progress had been made, and declare the job done.
2단 해법 — initializer agent와 coding agent
Initializer agent: The very first agent session uses a specialized prompt that asks the model to set up the initial environment: an init.sh script, a claude-progress.txt file that keeps a log of what agents have done, and an initial git commit that shows what files were added.
Coding agent: Every subsequent session asks the model to make incremental progress, then leave structured updates.
The key insight here was finding a way for agents to quickly understand the state of work when starting with a fresh context window, which is accomplished with the claude-progress.txt file alongside the git history. Inspiration for these practices came from knowing what effective software engineers do every day.
(두 에이전트는 초기 유저 프롬프트만 다를 뿐, 시스템 프롬프트·툴셋·하네스는 동일하다고 각주에 명시.)
피처 리스트 — 200개 이상의 요구사항 전부 'failing'에서 출발, 포맷은 JSON
we prompted the initializer agent to write a comprehensive file of feature requirements expanding on the user’s initial prompt. In the claude.ai clone example, this meant over 200 features, such as “a user can open a new chat, type in a query, press enter, and see an AI response.” These features were all initially marked as “failing” so that later coding agents would have a clear outline of what full functionality looked like.
{
"category": "functional",
"description": "New chat button creates a fresh conversation",
"steps": [
"Navigate to main interface",
"Click the 'New Chat' button",
"Verify a new conversation is created",
"Check that chat area shows welcome state",
"Verify conversation appears in sidebar"
],
"passes": false
}
We prompt coding agents to edit this file only by changing the status of a passes field, and we use strongly-worded instructions like “It is unacceptable to remove or edit tests because this could lead to missing or buggy functionality.” After some experimentation, we landed on using JSON for this, as the model is less likely to inappropriately change or overwrite JSON files compared to Markdown files.
한 번에 한 기능 — git 커밋과 진행 로그로 클린 스테이트 마감
the next iteration of the coding agent was then asked to work on only one feature at a time. This incremental approach turned out to be critical to addressing the agent’s tendency to do too much at once.
we found that the best way to elicit this behavior was to ask the model to commit its progress to git with descriptive commit messages and to write summaries of its progress in a progress file. This allowed the model to use git to revert bad code changes and recover working states of the code base.
By “clean state” we mean the kind of code that would be appropriate for merging to a main branch: there are no major bugs, the code is orderly and well-documented, and in general, a developer could easily begin work on a new feature without first having to clean up an unrelated mess.
테스트 — 인간 사용자처럼 엔드투엔드로
Absent explicit prompting, Claude tended to make code changes, and even do testing with unit tests or curl commands against a development server, but would fail recognize that the feature didn’t work end-to-end.
Claude mostly did well at verifying features end-to-end once explicitly prompted to use browser automation tools and do all testing as a human user would.
For example, Claude can’t see browser-native alert modals through the Puppeteer MCP, and features relying on these modals tended to be buggier as a result.
세션 시작 루틴 — pwd, git log, 진행 파일, 그리고 init.sh
매 세션 시작 시 거치는 절차:
- Run pwd to see the directory you’re working in. You’ll only be able to edit files in this directory.
- Read the git logs and progress files to get up to speed on what was recently worked on.
- Read the features list file and choose the highest-priority feature that’s not yet done to work on.
새 기능에 들어가기 전 init.sh로 개발 서버를 띄우고 기본 엔드투엔드 테스트부터 통과시킨다.
This ensured that Claude could quickly identify if the app had been left in a broken state, and immediately fix any existing bugs. If the agent had instead started implementing a new feature, it would likely make the problem worse.
남은 질문 — 단일 범용 에이전트 vs 멀티 에이전트
it’s still unclear whether a single, general-purpose coding agent performs best across contexts, or if better performance can be achieved through a multi-agent architecture. It seems reasonable that specialized agents like a testing agent, a quality assurance agent, or a code cleanup agent, could do an even better job at sub-tasks across the software development lifecycle.
It’s likely that some or all of these lessons can be applied to the types of long-running agentic tasks required in, for example, scientific research or financial modeling.