
12-Factor Agents는 이름부터 의도가 분명하다. 12-Factor App이 웹 애플리케이션을 “어떻게 배포 가능한 소프트웨어로 만들 것인가”를 정리했다면, 이 문서는 LLM 기반 에이전트를 “어떻게 프로덕션 고객에게 맡길 수 있는 소프트웨어로 만들 것인가”를 정리한다.
이 글의 핵심은 에이전트를 더 화려하게 만드는 방법이 아니다. 오히려 반대다. HumanLayer는 좋은 에이전트가 단순한 프롬프트 루프가 아니라, 대부분은 결정론적 소프트웨어이고 LLM은 그 안에서 제한된 결정을 내리는 부품이라고 본다. 이 관점이 중요하다. 에이전트를 “마법”으로 다루면 운영이 무너지고, “시스템”으로 다루면 비로소 반복 가능해진다.

왜 이 문서가 중요한가
대부분의 에이전트 논의는 “무슨 모델을 쓰는가”로 시작한다. 하지만 실제 프로덕션에서는 모델보다 더 중요한 질문이 있다.
- 프롬프트는 누가 소유하는가
- 컨텍스트는 어떻게 구성되는가
- 상태는 어디에 저장되는가
- 실패는 어떻게 압축되어 다시 입력되는가
- 사람이 개입해야 할 때는 어떤 경로로 들어오는가
12-Factor Agents는 이 질문들에 대한 답을 원칙 형태로 정리한다. 그래서 이 문서는 프레임워크 비교 글이라기보다 운영 원칙 문서에 가깝다. 에이전트를 붙이는 순간 생기는 불안정성은 대체로 모델 품질이 아니라, 이 경계들을 설계하지 않았기 때문에 생긴다.
12개 원칙을 네 묶음으로 보면 더 잘 보인다
| 묶음 | 포함되는 원칙 | 실무적 의미 |
|---|---|---|
| 입력과 지식 | 1, 2, 3, 4 | 어떤 말이 들어오고, 어떤 문맥이 LLM에 보이는지 통제한다 |
| 상태와 복구 | 5, 6, 9, 12 | 실행 상태와 업무 상태를 분리하지 않고, 재개 가능한 시스템으로 만든다 |
| 인간과 배포 면 | 7, 11 | 사람과 채널을 예외가 아니라 정상 경로로 다룬다 |
| 제어 흐름 | 8, 10 | 모델은 선택을 하고, 흐름은 deterministic code가 소유한다 |
이렇게 보면 이 문서가 왜 “12가지 트릭”이 아닌지 바로 보인다. 핵심은 기능 목록이 아니라 책임의 경계다.
첫 번째 교훈: 프롬프트보다 경계를 소유해야 한다
Factor 2, 3, 4는 사실 한 묶음으로 읽는 게 좋다.
프롬프트를 코드처럼 다루라
프롬프트를 그냥 문자열로 두면 금방 관리가 안 된다. 버전이 바뀌고, 사람이 붙이고, 다른 팀이 조용히 수정하고, 결과는 재현되지 않는다. 이 문서가 강조하는 건 프롬프트를 “마음대로 바꾸는 텍스트”가 아니라 테스트 가능한 자산으로 다루라는 점이다.
컨텍스트 윈도우는 제품의 입력면이다
많은 팀이 컨텍스트를 메모리처럼 취급하지만, 실제로는 더 정확히 말해 입력 조립 지점이다. 어떤 문서를 넣고, 어떤 로그를 빼고, 어떤 실패를 요약해서 다시 넣을지 결정하는 과정이 곧 제품 품질을 만든다.
Factor 3: Own your context window가 중요한 이유는 여기 있다. 컨텍스트는 부수적인 메모 저장소가 아니라, LLM이 세계를 보는 방식 그 자체다.
도구는 “마법”이 아니라 구조화된 출력이다
이 원칙은 에이전트 구현의 허세를 걷어낸다. 도구 호출은 특별한 우주가 아니라 구조화된 출력이다. 즉, 모델이 뭔가를 “알아서” 하는 것처럼 보이더라도, 실제로는 정해진 스키마를 채우고 deterministic code가 그 결과를 실행한다.
이 관점이 있으면 구현이 훨씬 선명해진다.
- 모델은 결정한다
- 코드는 실행한다
- 시스템은 결과를 기록한다
두 번째 교훈: 상태를 쪼개지 말고 하나로 보라
프로덕션에서 에이전트가 무너지는 이유 중 하나는 상태가 여기저기 흩어지기 때문이다. 대화 기록, job 상태, 승인 기록, 재시도 정보, 에러 로그가 각각 따로 놀면 재개가 어려워진다.
실행 상태와 비즈니스 상태를 나눠서 보면 복구가 어렵다
Factor 5는 이 문제를 정면으로 건드린다. 에이전트가 어떤 작업을 어디까지 했는지, 그리고 그 작업이 비즈니스적으로 어떤 의미인지가 따로 놀면 resume가 불안정해진다. 반대로 두 상태를 함께 설계하면 실패 후 복원이 쉬워진다.
Launch/Pause/Resume은 “좋은 UX”가 아니라 운영 요구사항이다
Factor 6은 단순한 편의 기능처럼 보일 수 있다. 실제로는 반대다. 장시간 실행되는 에이전트는 반드시 중단되고, 재개되고, 감사 가능해야 한다. 그렇지 않으면 운영자는 결국 브라우저 탭의 채팅 내역에 의존하게 된다.
에러는 그대로 다시 넣지 말고 압축하라
Factor 9가 실무적으로 중요한 이유도 여기 있다. 에이전트는 같은 실수를 길게 반복하기 쉽다. 에러를 원문 그대로 누적하면 컨텍스트가 오염된다. 필요한 건 원본 로그가 아니라, 다음 행동에 도움이 되는 형태의 압축된 실패 표현이다.
Stateless reducer는 과한 비유가 아니라 구조의 힌트다
Factor 12는 읽는 순간 농담처럼 보이지만, 사실 굉장히 실용적이다. 에이전트를 상태 기계로 보지 말고, 이벤트와 입력을 받아 다음 상태를 재구성하는 reducer로 보면 설계가 훨씬 안정적이 된다. 복구, 감사, 재현성이 모두 좋아진다.
세 번째 교훈: 사람은 예외가 아니라 도구 체계의 일부다
에이전트 시스템이 실제 제품이 되려면 사람을 “실패했을 때만 부르는 존재”로 두면 안 된다.
인간 개입은 정상 경로여야 한다
Factor 7은 중요한 운영 원칙이다. 고위험 작업에서는 사람의 승인이 경계 조건이 아니라 표준 흐름이어야 한다. 이걸 tool call처럼 다루면 감사 추적이 생기고, 워크플로우도 단순해진다.
사용자는 한 채널에만 있지 않다
Factor 11이 말하는 “trigger from anywhere”는 단순한 멀티채널 지원이 아니다. 이메일, Slack, SMS, webhook, cron 같은 진입점을 열어두면 에이전트는 더 넓은 운영 시스템에 붙을 수 있다. 즉, 에이전트는 챗봇이 아니라 이벤트에 반응하는 작업자가 된다.
네 번째 교훈: 제어 흐름은 모델에게 맡기지 말아야 한다
작은 에이전트가 더 낫다
Factor 10은 성능보다 구조를 말한다. 하나의 거대한 범용 에이전트보다, 목적이 분명하고 역할이 좁은 에이전트가 더 예측 가능하다. 이건 모델이 약해서가 아니라, 경계가 좁을수록 평가와 복구가 쉬워지기 때문이다.
결정은 모델이 해도, 흐름은 코드가 소유해야 한다
Factor 8의 메시지는 간단하다. “무슨 일을 할지”를 LLM이 고를 수는 있어도, “언제 멈추고 언제 재시도하고 언제 다른 경로로 갈지”는 코드가 결정해야 한다. 이 선을 넘기면 디버깅이 어려워진다.
HumanLayer의 문서를 읽고 나면, 많은 에이전트 프레임워크가 왜 기대만큼 안정적이지 않은지 감이 온다. 모델을 감싸는 레이어가 늘어날수록 좋아 보이지만, 실제로는 책임이 흐려질 수 있다. 반대로 이 문서가 제안하는 방식은 불편할 정도로 명시적이다. 그 명시성이 프로덕션에서는 장점이다.
이 문서를 실무에 적용하면 무엇이 달라지나
에이전트 제품을 설계할 때 아래 질문에 답할 수 없으면 아직 덜 성숙한 상태다.
- 프롬프트가 저장소에서 버전 관리되는가
- 컨텍스트 구성 로직을 코드로 추적할 수 있는가
- 실행 상태와 업무 상태를 같은 모델로 복원할 수 있는가
- 사람이 개입하는 승인 경로가 감사 가능한가
- 실패가 다음 turn에 유의미한 형태로 압축되는가
- 에이전트가 너무 커졌을 때 쪼갤 기준이 있는가
이 질문들에 예라고 답할 수 있으면, 에이전트는 데모를 넘어선다. 아니면 아직은 “LLM이 붙은 워크플로우”에 더 가깝다.
마치며
12-Factor Agents의 가장 좋은 점은 유행어를 더 만든 게 아니라, 유행어를 벗겨냈다는 데 있다. 이 문서가 말하는 것은 결국 아주 단순하다.
- 모델이 전부는 아니다
- 컨텍스트는 자산이다
- 상태는 복구 가능해야 한다
- 사람은 예외가 아니다
- 흐름은 코드가 소유해야 한다
에이전트를 만든다는 건 LLM에게 더 많은 자율성을 주는 일이 아니라, 자율성이 필요한 지점과 결정론이 필요한 지점을 정확히 나누는 일이다. 이 문서를 읽고 나면, 좋은 에이전트는 “더 똑똑한 모델”이 아니라 “더 잘 설계된 시스템”이라는 말이 훨씬 덜 추상적으로 들린다.