AI-native engineering
프롬프트에서 루프까지: AI 에이전트가 일을 끝내게 만드는 네 가지 설계
프롬프트를 잘 쓰는 법을 넘어, 에이전트가 필요한 정보를 읽고 안전하게 행동하며 검증 근거로 완료를 증명하는 실행 시스템을 살펴봅니다.
AI 에이전트가 코드를 바꿨다. 그런데 테스트는 돌지 않았고, 실제 화면에서는 기능이 깨졌다. 반대로 테스트 하나를 통과한 뒤 전체 작업을 끝냈다고 보고하지만, 변경 범위가 요구와 어긋나는 경우도 있다. 코드는 나왔는데 일은 끝나지 않은 것이다.
이럴 때 가장 먼저 프롬프트를 고치게 된다. 프롬프트는 중요하다. 하지만 에이전트가 파일을 읽고, 도구를 쓰고, 코드를 바꾸고, 실패를 복구하는 과정은 프롬프트만으로 설명되지 않는다.
이 글은 코딩 에이전트에게 실제 저장소의 기능 작업을 맡기는 개발자와 테크 리드를 위한 실행 지도다. 하나의 작은 기능을 따라가며, 에이전트가 무엇을 확인해야 일을 끝냈다고 말할 수 있는지 살펴본다.
핵심은 간단하다. 완료의 단위는 코드 작성이 아니라 검증 가능한 상태 변화다.
- Prompt engineering: 무엇을 끝낼지 정한다.
- Context engineering: 지금 판단에 필요한 정보를 고른다.
- Harness engineering: 에이전트가 행동하고 검증할 환경을 만든다.
- Loop engineering: 결과를 다음 판단에 반영하고 멈출 시점을 정한다.
프롬프트는 컨텍스트의 일부다. 다만 이 글에서는 목표와 완료 기준을 다루는 설계 관점으로 따로 떼어 본다. 컨텍스트는 판단 재료, 하네스는 실행과 검증이 가능한 환경이다. 루프는 근거를 모아 다음 행동과 종료 시점을 정한다.
먼저 전체 구조: 네 설계는 한 시스템 안에서 겹친다
네 개념을 차례로 익혀야 할 발전 단계로 보면 관계를 놓치기 쉽다. 프롬프트를 잘 쓴 뒤 컨텍스트를 추가하고, 그다음에 하네스와 루프를 붙이는 순서가 아니다. 네 관점은 하나의 실행 시스템 안에서 계속 겹치고 영향을 주고받는다.
실행이 한 번 끝나면 파일이 바뀌고, 테스트가 통과하거나 실패하고, 새로운 제약이 드러난다. 이 결과는 다음 판단의 컨텍스트가 된다. 에이전트는 갱신된 상태를 보고 다음 행동을 고른다.
도구의 이름·스키마·사용 설명이 모델에 전달되면 컨텍스트다. 실제 도구 구현, 실행 권한, 샌드박스와 테스트 러너는 하네스다. 도구의 실행 결과가 다시 모델에 들어오면 그 결과는 다음 판단의 컨텍스트가 된다.
이 네 분류는 업계가 합의한 독립 계층이 아니라 작업 실패를 진단하기 위한 렌즈다. 특히
harness engineering과 loop engineering의 경계는 팀마다 다를 수 있다.
이 글에서는 하네스를 에이전트가 안정적으로 행동하고 검증할 수 있는 환경으로, 루프를 피드백과
성공·중단 조건을 관리하는 제어 구조로 정의한다.
가상 예시: 문의 폼 중복 제출 막기
하나의 작은 기능을 네 관점으로 따라가 보자. 이해를 돕기 위해 만든 가상의 상황이며, 실제 서비스에서 발생한 사고나 장애가 아니다.
웹 서비스의 문의 폼에서 첫 요청을 처리하는 동안 추가 submit 이벤트가 발생해
같은 요청이 여러 번 전송될 수 있다고 가정한다. 전송 중에는 추가 제출을 막고 상태를
알리며, 실패하면 입력값을 유지한다. 기존 API 계약은 바꾸지 않고 실제 외부 전송 없이
검증한다.
이 예시는 동일한 페이지의 첫 요청이 진행 중일 때 추가 submit 이벤트를 막는
UX 수준의 보호를 다룬다. 응답 유실 후 재시도처럼 같은 작업이 다시 요청될 수 있는 상황을
안전하게 처리하려면 클라이언트와 서버가 idempotency key를 공유하고 처리 결과를 저장하는
멱등성 설계가 필요하다. 여러 탭의 별도 제출이나 직접 API 호출까지 제어하려면 인증·인가,
서버 측 상태 검사, 속도 제한 같은 별도 경계가 필요하다. 클라이언트의 버튼 잠금은 정확히 한
번 처리를 보장하지 않으며 보안 경계도 아니다.
코드 변경량은 적지만, 요구 해석·현재 구조 파악·API 호환성·UI 상태·오류 복구·외부 연동의 안전성을 함께 다루어야 한다. 그래서 네 가지 설계가 어떻게 맞물리는지 보기 좋다.
1. Prompt engineering: 무엇을 끝냈다고 볼 것인가
처음에는 이렇게 요청할 수 있다.
문의 폼이 중복 제출되지 않게 고쳐줘.
의도는 알 수 있지만 판단 기준은 부족하다. 요청을 클라이언트에서 차단할지, 서버까지 바꿔 멱등성을 보장할지 범위도 모호하다. 이런 프롬프트만 주면 에이전트는 코드 변경을 완료로 착각하기 쉽다.
이 예시에서는 기존 API 계약을 유지하고 같은 폼 인스턴스의 추가 제출만 막는다. 실패한 뒤의 동작과 완료를 어떻게 확인할지도 분명히 해야 한다.
작업 프롬프트는 더 긴 설명이 아니라 더 분명한 계약이어야 한다.
목표
- 요청을 처리하는 동안 같은 폼의 추가 제출을 막는다.
유지할 것
- 기존 API 요청과 응답 형식을 바꾸지 않는다.
- 기존 폼 필드와 검증 규칙을 유지한다.
필요한 동작
- 전송 중에는 추가 submit 이벤트가 네트워크 요청으로 이어지지 않게 한다.
- 버튼 클릭과 Enter 키 제출이 같은 핸들러를 거치게 한다.
- 전송 중, 성공, 실패 상태를 텍스트와 상태 알림 영역으로 전달한다.
- 실패 시 입력값을 유지하고 다시 제출할 수 있게 한다.
안전 제약
- 외부 연동은 모의 어댑터로 대체한다.
- 테스트 환경에 운영 자격 증명을 제공하지 않는다.
완료 증거
- 자동 테스트를 통과한다.
- 첫 요청이 끝나기 전 submit 이벤트가 두 번 발생해도 모의 API 호출은 1회다.
- 실패 후 잠금이 풀리고 입력값이 남으며, 재시도하면 새 요청이 1회 발생한다.
- 변경 범위가 이 요구에 한정됐는지 검토한다.
이제 에이전트는 어디까지 자율적으로 결정할 수 있고, 무엇으로 완료를 증명해야 하는지 알 수 있다. 프롬프트의 역할은 코드 한 줄까지 지정하는 것이 아니라 목표, 제약, 완료 증거를 분명히 하는 것이다.
2. Context engineering: 지금 어떤 사실을 봐야 하는가
작업 계약이 분명해도 서비스의 현재 상태를 모르면 올바르게 바꿀 수 없다. 어떤 파일이 폼을 그리는지, 이미 제출 상태를 관리하는 코드가 있는지, API의 요청 계약은 무엇인지 알아야 한다. 저장소의 수정 규칙, 접근성 기준, 개인정보 처리 경계도 결과에 영향을 준다.
Anthropic은 context engineering을 프롬프트를 포함해 추론 시점에 모델에 제공되는 전체 정보를 선별하고 유지하는 전략으로 설명한다. 시스템 지침, 도구, 외부 데이터, 메시지 기록까지 모두 컨텍스트에 포함된다. 중요한 것은 많은 토큰을 넣는 일이 아니라, 원하는 결과에 가장 유용한 정보를 고르는 일이다.
문의 폼 작업에 필요한 컨텍스트는 다음과 같다.
- 폼의 HTML 구조와 현재 상태
- 클라이언트 제출 핸들러
- API 요청·응답 계약
- 기존 테스트와 검증 명령
- 상태 표시와 키보드 조작에 관한 UI 규칙
- 외부 전송과 비밀값을 다루는 안전 규칙
반면 저장소의 모든 문서, 관련 없는 과거 작업 기록, 실제 API 키와 운영 데이터는 제공할 이유가 없다. 정보가 많다고 판단이 좋아지는 것은 아니다. 불필요한 정보는 중요한 규칙을 숨기고, 비밀값과 실제 사용자 데이터는 위험만 늘린다.
컨텍스트는 한 번 모아 놓고 끝나지 않는다. 테스트 실패가 새로운 제약을 드러내면 그 실패 메시지와 관련 코드가 다음 판단의 컨텍스트가 된다. 반복할수록 컨텍스트를 늘리기보다 필요한 정보에 더 또렷하게 초점을 맞춰야 한다.
3. Harness engineering: 행동과 검증을 실제로 가능하게 만들기
“테스트해”라고 쓰는 것과 에이전트가 실제로 테스트할 수 있는 것은 다르다. 명령을 찾을 수 없거나 외부 전송을 안전하게 대체할 수 없다면, 에이전트는 검증을 생략하거나 위험한 실행을 사람에게 넘길 수밖에 없다.
어떤 명령을 실행해야 하는지, 실패를 어떻게 해석할지, 외부 연동을 안전하게 대체할 방법이 있는지가 실행 가능성을 결정한다.
OpenAI의 harness engineering 사례는 에이전트가 안정적으로 일하려면 의도를 분명히 하는 것과 함께 실행 환경과 피드백 루프를 설계해야 함을 보여 준다. 저장소 구조, 문서, 도구, 테스트, CI, 관측 수단과 아키텍처 규칙이 모두 하네스의 일부가 될 수 있다.
이 예시의 하네스는 거창한 멀티 에이전트 프레임워크가 아니다. 오히려 작은 도구와 경계의 조합에 가깝다.
- 관련 파일을 찾는 검색 도구
- 변경 범위를 제한하는 저장소 규칙
- 코드를 수정하는 편집 도구
- API 성공과 실패를 재현하는 모의 응답
- 회귀 문제를 찾는 자동 테스트
- 버튼과 Enter 키 제출, 실패 후 재시도를 확인할 로컬 브라우저
- 의도하지 않은 변경을 찾는 변경 내역(diff) 검토
- 운영 자격 증명과 외부 전송을 작업에서 분리하는 안전 경계
하네스가 좋으면 에이전트가 실패 정보를 직접 읽고 작업을 수정할 수 있다. 동시에 하네스는 에이전트가 할 수 있는 행동의 범위도 정한다. 언제 사람의 승인이 필요한지, 어떤 데이터를 읽으면 안 되는지, 어떤 외부 작업을 수행하면 안 되는지를 시스템으로 표현한다.
4. Loop engineering: 증거가 다음 행동을 바꾸게 만들기
에이전트는 보통 한 번의 모델 호출로 작업을 완료하지 않는다. 현재 상태를 보고, 행동하고,
환경의 결과를 읽은 뒤 다음 행동을 고른다.
OpenAI의 에이전트 구축 가이드도 이런 while 루프를 에이전트 실행의
핵심으로 다루며, 도구 호출·최종
출력·오류·최대 턴 수 같은 종료 조건을 예로 든다.
Anthropic의 에이전트 설계 사례도 매 단계에서 도구 결과와 코드 실행 같은 환경의
실제 근거를 확인하고, 최대 반복 수와
사람이 판단할 지점을 둘 필요가 있다고 설명한다.
중요한 것은 반복 횟수가 아니라, 매번 다음 판단을 위한 근거가 생기는지다. “다시 해봐”는 루프 설계가 아니다. 실패한 테스트, 브라우저에서 관찰한 상태, 수정 후의 변경 내역처럼 실행 환경에서 얻은 증거가 다음 행동을 바꿔야 한다.
문의 폼 작업이라면 현재 폼·제출 핸들러·API 계약·테스트 범위를 먼저 읽는다. 최소 변경을 계획해 구현한 뒤 자동 테스트와 브라우저 검증을 실행한다. 완료 근거가 부족하면 수정과 검증을 반복하고, 충분하면 조직의 규칙과 위험도에 따라 사람의 승인·병합·배포 단계로 넘어간다.
실패가 다음 행동을 바꾸는 순간
가상의 첫 구현이 버튼의 클릭 핸들러에서만 버튼을 비활성화하고, 폼의
submit 핸들러에는 진행 중 가드를 두지 않았다고 해 보자. 버튼을 누른 직후
Enter 키로 폼을 다시 제출하자 모의 API 호출이 2회 기록됐다. “중복 제출을 막았다”는
에이전트의 판단과 환경의 증거가 충돌한다.
이 증거를 반영한 다음 시도에서는 버튼이 아니라 폼의 submit 핸들러에 진행 중
가드를 둔다. 비동기 요청을 시작하기 전에 가드를 동기적으로 설정해 버튼 클릭과 Enter 키
제출이 같은 경로를 거치게 한다. 다시 검증하자 첫 요청이 끝나기 전에 발생한 두 번의
submit 이벤트가 모의 API 호출 1회로 이어졌다.
끝은 아니다. 오류 응답을 만들어 잠금이 풀리는지, 입력값이 남는지, 재시도했을 때 새 요청이 1회만 발생하는지를 확인한다. 이것이 단순 반복과 루프 설계의 차이다. 실패·증거·수정·재검증이 다음 행동을 바꾼다.
성공과 안전한 중단은 다르다
이 작업의 성공 조건은 “에이전트가 코드를 작성했다”는 사실이 아니다.
- 같은 폼의 첫 요청이 진행 중인 동안 버튼 클릭이나 Enter 키로 발생한 추가 제출이 네트워크 요청으로 이어지지 않는다.
-
전송 상태를 텍스트와
aria-live영역으로 알리고, 오류 후에는 입력값을 유지하며 제출 제어를 다시 활성화한다. - 기존 API 계약을 유지하고 모든 변경을 합의한 요구 범위에서 설명할 수 있다.
- 자동 테스트와 실제 화면 검증이 통과했으며, 모의 어댑터만 호출됐고 운영 어댑터 호출은 0회다.
성공 조건과 별개로 실행 중단 조건도 필요하다. 최대 턴·시간·비용을
넘겼거나, 같은 실패가 반복되거나, 추가 권한이나 사람의 판단이 필요하면 루프를 멈추고
제어를 넘긴다. 이때 성공 조건을 충족하지 못했다면 결과는 완료가 아니라
미완료 또는 사람 판단 필요다. 루프가 멈춘 사실이 작업 성공을
뜻하지는 않는다.
실패 증상으로 설계의 빈틈 찾기
실제 작업의 실패는 네 영역 중 하나만의 문제인 경우가 드물다. 불분명한 프롬프트가 잘못된 컨텍스트 선택으로 이어질 수 있고, 테스트 도구가 없으면 루프도 제대로 돌지 않는다. 그래도 증상을 보면 어디를 먼저 살펴볼지 정할 수 있다.
| 관찰한 증상 | 먼저 살펴볼 설계 |
|---|---|
| 에이전트가 원한 것과 다른 기능을 만든다 | Prompt: 목표·제약·완료 조건이 분명한가 |
| 기존 API나 저장소 규칙을 깨뜨린다 | Context: 권위 있는 계약과 관련 파일을 봤는가 |
| 코드는 만들었지만 실행·테스트하지 못한다 | Harness: 필요한 도구와 안전한 실행 환경이 있는가 |
| 같은 시도를 반복하거나 너무 일찍 완료를 선언한다 | Loop: 피드백·성공 조건·중단 조건이 구체적인가 |
이 표는 원인을 단정하는 진단표가 아니라 조사 순서를 정하는 출발점이다. 프롬프트를 계속 늘리기 전에 현재 실패가 목표 문제인지, 정보 문제인지, 환경 문제인지, 피드백 문제인지 구분할 필요가 있다.
잘 묻는 법을 넘어, 끝낼 수 있는 시스템으로
프롬프트가 도착점을 정하고, 컨텍스트가 판단을 돕는다. 하네스는 실행과 검증을 가능하게 하고, 루프는 충분한 근거를 모아 성공 또는 안전한 중단을 결정한다.
AI-native engineering을 코드 생산량의 문제로 보면 에이전트가 작성한 코드의 양이 성과가 된다. 반대로 완료를 증명하는 시스템의 문제로 보면 질문이 달라진다.
- 목표와 제약이 분명한가?
- 현재 판단에 필요한 정보가 들어 있는가?
- 에이전트가 안전하게 행동하고 검증할 수 있는가?
- 피드백이 다음 판단을 바꾸고 있는가?
- 성공 또는 중단을 판단할 근거가 있는가?
좋은 에이전트 작업은 모델의 결과를 믿는 것으로 끝나지 않는다. 에이전트가 실제로 무엇을 바꿨는지, 어떤 검증을 거쳤는지, 어떤 경계 안에서 행동했는지를 확인할 수 있어야 한다. 잘 쓴 프롬프트는 그 시스템을 시작하지만, 일을 끝내는 것은 전체 설계다.