12-Factor Agents 소개
12-Factor Agents는 "What are the principles we can use to build LLM-powered software that is actually good enough to put in the hands of production customers?" 라는 한 줄 질문에서 출발하는 LLM 에이전트 설계 원칙 모음입니다. HumanLayer의 Dex가 정리해 공개한 12개의 원칙 으로, 이름에서 짐작되듯이 12 Factor Apps 의 정신을 LLM 기반 소프트웨어에 옮긴 형태를 취합니다.
저자는 plug-and-play 프레임워크(예: CrewAI, LangChain)부터 minimalist smolagents, production-grade LangGraph, Griptape에 이르기까지 "every agent framework out there" 를 다 사용해 본 뒤, 실제 운영에서 고객을 대상으로 동작하는 에이전트 대부분이 결국 "mostly just software" 라는 결론에 도달했다고 12-Factor Agents 저장소에서 밝힙니다. 즉, "goal과 tool 한 바구니, loop until done" 류의 패턴(Anthropic의 Building Effective Agents 글에서 정의된 형태)을 그대로 따르는 제품은 운영 단계에서 잘 살아남지 못한다는 진단입니다.
전통적인 코드는 본질적으로 모든 엣지가 사람 손으로 정의된 방향 그래프(Directed Graph, DG) 이고, 지난 20년간 Airflow / Prefect / Dagster / Inngest / Windmill 같은 DAG 오케스트레이터가 그 위에 관측성·재시도·관리 기능을 얹어 왔습니다. 12-Factor Agents 저장소에서는 "에이전트의 약속은 이 DAG를 던져 버리는 것" 이라고 정리합니다. 엔지니어가 노드와 엣지를 모두 코딩하는 대신 "목표(goal)와 가능한 전이(transitions)만" 주고 LLM이 실시간으로 경로를 선택하도록 맡기는 그림입니다.
이 약속을 단순한 루프로 옮기면, 에이전트는 "LLM이 다음 단계를 정하고 → 결정론적 코드가 도구를 실행하고 → 결과를 컨텍스트에 덧붙이고 → done이 될 때까지 반복" 하는 4단계의 사이클이 됩니다. 이 단순한 루프는 빠르게 70~80%의 품질에 도달하지만, 고객용 제품에서 요구하는 그 너머 구간으로는 잘 넘어가지 못합니다. 저자는 100명 이상의 SaaS 빌더와 대화하면서 다음과 같은 공통 패턴을 관찰했다고 적고 있습니다.
- 에이전트를 만들겠다고 결심
- 제품 디자인·UX·풀어야 할 문제 정의
- 빠르게 움직이기 위해
$FRAMEWORK를 잡고 "get to building" - 70~80% 품질에 도달
- 80% 가지고는 고객 대면 기능 대부분에 부족하다는 것을 깨달음
- 80%를 넘기려면 프레임워크·프롬프트·플로우를 리버스 엔지니어링해야 한다는 사실을 인식
- 처음부터 다시 짠다
12-Factor Agents는 이 사이클을 깨기 위한 small, modular concepts 의 모음을 지향합니다. 단일 라이브러리를 제공하는 것이 아니라, 각 원칙을 저장소의 content/ 디렉토리 아래 별도 마크다운 문서로 깊이 있게 다루는 가이드 모음에 가깝습니다. 저장소 본문에는 각 원칙을 시각화한 12개의 다이어그램과 Visual Nav 표가 함께 포함되어 있으며, 아래 요약 이미지는 그 Visual Nav 표를 한 장으로 정리한 것입니다.
12-Factor Agents의 12가지 원칙
저장소 첫 페이지의 The Short Version: The 12 Factors 로 정리된 12개 원칙은 다음과 같습니다 (각 항목 제목은 원문 그대로 옮긴 뒤 짧은 한국어 해설을 덧붙였고, 각 항목은 content/ 아래의 개별 문서로 연결됩니다).
- Factor 1 — Natural Language to Tool Calls: 자연어 입력을 곧장 자유 형식 텍스트가 아니라 구조화된 도구 호출로 변환하는 단계를 명확히 분리합니다.
- Factor 2 — Own your prompts: 프레임워크가 숨겨 둔 프롬프트에 의존하지 말고, 운영 코드처럼 자신의 프롬프트를 직접 소유하고 버전 관리할 것을 권합니다.
- Factor 3 — Own your context window: 흔히 Context Engineering 으로 불리는 영역으로, 컨텍스트 윈도우에 무엇이 어떤 순서로 들어가는지를 직접 통제합니다. 12-Factor Agents 가이드에서 가장 자주 참조되는 챕터로 꼽힙니다.
- Factor 4 — Tools are just structured outputs: 도구 호출은 본질적으로 LLM이 내놓는 구조화된 출력이라는 관점에서, 도구 정의와 검증을 일반 소프트웨어처럼 다룹니다.
- Factor 5 — Unify execution state and business state: 에이전트의 실행 상태와 도메인의 비즈니스 상태를 같은 모델로 통합해 일관성을 확보합니다.
- Factor 6 — Launch / Pause / Resume with simple APIs: 에이전트의 시작·정지·재개를 단순한 API로 분리해, 중간에 사람의 개입이 들어오거나 장기 실행이 필요할 때를 대비합니다.
- Factor 7 — Contact humans with tool calls: 사람에게 묻고 답을 받는 행위 자체를 별도의 도구 호출로 모델링해, 사람-기계 루프를 일반 도구 호출과 같은 흐름으로 다룹니다.
- Factor 8 — Own your control flow: 에이전트 내부의 제어 흐름을 프레임워크에 위임하지 말고, 일반 소프트웨어처럼 자신이 작성한 코드로 제어합니다.
- Factor 9 — Compact Errors into Context Window: 도구 오류와 예외를 그대로 흘리지 말고, 컨텍스트 윈도우에 적합한 형태로 압축해 다시 LLM에 전달합니다.
- Factor 10 — Small, Focused Agents: 거대한 단일 에이전트보다 작고 초점이 분명한 에이전트들을 조합하는 방향을 권합니다.
- Factor 11 — Trigger from anywhere, meet users where they are: 사용자가 이미 쓰는 슬랙·이메일·웹훅 등 어느 채널에서든 에이전트를 호출할 수 있도록 트리거를 다양화합니다.
- Factor 12 — Make your agent a stateless reducer: 에이전트를 가능한 한 상태 없는 reducer 형태로 두어, 입력 상태에서 출력 상태로 옮기는 순수 함수에 가깝게 만듭니다.
아래에서는 각 원칙의 핵심 내용을 다이어그램과 함께 차례로 살펴봅니다.
Factor 1 — Natural Language to Tool Calls
가장 흔한 패턴은 "can you create a payment link for $750 to Terri for sponsoring the february AI tinkerers meetup?" 같은 자연어 한 줄을 다음과 같은 구조화된 JSON 객체로 옮기는 작업입니다.
{
"function": {
"name": "create_payment_link",
"parameters": {
"amount": 750,
"customer": "cust_128934ddasf9",
"product": "prod_8675309",
"price": "prc_09874329fds",
"quantity": 1,
"memo": "Hey Jeff - see below for the payment link for the february ai tinkerers meetup"
}
}
}
이렇게 얻은 구조화된 페이로드를 결정론적 코드(deterministic code) 가 받아 실제 API 호출로 옮깁니다. 12-Factor Agents 저장소에서는 LLM의 출력 유형에 따라 분기하는 단순한 스위치 문 형태로 코드 예시를 제공합니다.
nextStep = await llm.determineNextStep(
"""
create a payment link for $750 to Jeff
for sponsoring the february AI tinkerers meetup
"""
)
if nextStep.function == 'create_payment_link':
stripe.paymentlinks.create(nextStep.parameters)
elif nextStep.function == 'something_else':
...
else:
# the model didn't call a tool we know about
...
원칙의 핵심은 "자연어 → 구조화된 객체" 단계를 별도 책임으로 분리하고, 그 뒤의 실제 실행은 평범한 코드로 다룬다는 것입니다. 전체 루프가 결과를 다시 LLM에 돌려주는 부분은 의도적으로 떼어 다른 원칙(Factor 3, 8 등)에서 다룹니다.
Factor 2 — Own your prompts
프롬프트 엔지니어링을 프레임워크에 외주 주지 말라는 원칙입니다. 일부 프레임워크는 다음과 같이 블랙박스 형태로 역할·목표·도구를 받아 내부에서 프롬프트를 조립합니다.
agent = Agent(
role="...",
goal="...",
personality="...",
tools=[tool1, tool2, tool3],
)
task = Task(instructions="...", expected_output=OutputModel)
result = agent.run(task)
12-Factor Agents 가이드는 그 대신 BAML 같은 도구 또는 손수 작성한 템플릿으로 시스템 메시지·유저 메시지·출력 스키마를 모두 직접 관리할 것을 권합니다. 다음은 가이드에 실린 BAML 예시로, 프롬프트가 DetermineNextStep 함수의 본문 자체에 명시되어 있고 반환 타입까지 DoneForNow | ListGitTags | DeployBackend | ... 형태로 명시되어 있습니다.
function DetermineNextStep(thread: string) -> DoneForNow | ListGitTags | DeployBackend | DeployFrontend | RequestMoreInformation {
prompt #"
{{ _.role("system") }}
You are a helpful assistant that manages deployments for frontend and backend systems.
...
{{ _.role("user") }}
{{ thread }}
What should the next step be?
"#
}
이렇게 프롬프트를 일급 코드로 다루면 (1) 완전한 통제, (2) 테스트·평가(eval) 가능, (3) 빠른 반복, (4) 투명성, (5) role hacking (예: OpenAI의 비표준 user/assistant 사용)을 얻을 수 있다고 정리합니다. 가이드의 한 줄 결론은 "I don't know what's the best prompt, but I know you want the flexibility to be able to try EVERYTHING." 입니다.
Factor 3 — Own your context window
"At any given point, your input to an LLM in an agent is 'here's what's happened so far, what's the next step'."
12-Factor Agents 저장소에서 Context Engineering 이라는 표현으로 가장 자주 참조되는 챕터입니다. LLM은 본질적으로 입력을 출력으로 매핑하는 무상태(stateless) 함수이므로, 좋은 출력을 얻으려면 좋은 입력을 직접 만들어 줘야 한다고 강조합니다. 좋은 컨텍스트에는 다음이 모두 포함됩니다.
- 모델에 주는 프롬프트와 지시
- RAG로 가져온 문서나 외부 데이터
- 과거 상태·도구 호출·결과 등 히스토리
- 관련은 있지만 별개인 대화/이벤트의 메시지(Memory)
- 어떤 형태의 구조화된 출력을 원하는지에 대한 지침
대부분의 LLM 클라이언트는 표준 messages 형식을 쓰지만, 12-Factor Agents 가이드는 토큰·어텐션 효율을 위해 자신만의 포맷을 만드는 것을 제안합니다. 예를 들어 전체 히스토리를 XML-스러운 이벤트 블록으로 묶어 단일 user 메시지로 전달하는 식입니다.
<slack_message>
From: @alex
Channel: #deployments
Text: Can you deploy the latest backend to production?
</slack_message>
<list_git_tags>
intent: "list_git_tags"
</list_git_tags>
<list_git_tags_result>
tags:
- name: "v1.2.3"
commit: "abc123"
date: "2024-03-15T10:00:00Z"
- name: "v1.2.2"
commit: "def456"
date: "2024-03-14T15:30:00Z"
</list_git_tags_result>
이런 thread 구조를 코드로 옮긴 예시는 다음과 같습니다.
class Event:
type: Literal["list_git_tags", "deploy_backend", "list_git_tags_result", "error", ...]
data: ListGitTags | DeployBackend | ListGitTagsResult | str
def event_to_prompt(event: Event) -> str:
data = event.data if isinstance(event.data, str) else stringifyToYaml(event.data)
return f"<{event.type}>\n{data}\n</{event.type}>"
def thread_to_prompt(thread: Thread) -> str:
return "\n\n".join(event_to_prompt(e) for e in thread.events)
자체 포맷을 쓰면 (1) 정보 밀도, (2) 에러 표시 방식 통제, (3) 민감 정보 필터링 같은 안전성, (4) 포맷을 유즈케이스에 맞게 진화시킬 유연성, (5) 토큰 효율을 모두 자신의 손에 둘 수 있다고 정리합니다. 12-Factor Agents 가이드는 컨텍스트 윈도우가 LLM과의 일차 인터페이스이며, 그 구조를 통제하는 것만으로도 에이전트 성능을 극적으로 끌어올릴 수 있다 고 단언합니다.
Factor 4 — Tools are just structured outputs
"도구(tool)" 라는 단어가 거창해 보이지만, 본질적으로는 LLM이 내놓는 구조화된 JSON 과 이를 받아 실행하는 결정론적 코드의 조합이라는 관점입니다. 예를 들어 CreateIssue 와 SearchIssues 두 도구를 두는 것은 LLM에게 "다음 두 스키마 중 하나로 JSON을 내놓아라" 라고 요구하는 것과 같습니다.
class Issue:
title: str
description: str
team_id: str
assignee_id: str
class CreateIssue:
intent: "create_issue"
issue: Issue
class SearchIssues:
intent: "search_issues"
query: str
what_youre_looking_for: str
패턴은 단순합니다. (1) LLM이 구조화된 JSON을 출력하고, (2) 결정론적 코드가 적절한 액션을 실행하며, (3) 결과는 컨텍스트로 다시 흘러 들어갑니다. LLM이 "도구를 호출했다" 고 해서 매번 똑같은 함수가 똑같은 방식으로 실행되어야 한다는 뜻은 아니며, 결정론적 코드가 라우팅·검증·재포맷팅 같은 모든 선택권을 쥡니다. JSON 모드·function calling·constrained generation 사이의 트레이드오프는 가이드가 Schema-Aligned Parsing, Vellum 비교 글, LlamaIndex 비교 같은 외부 리소스로 연결해 둡니다.
Factor 5 — Unify execution state and business state
전통적인 인프라에서는 실행 상태(execution state) 와 비즈니스 상태(business state) 를 분리해 다루는 것이 일반적입니다.
- 실행 상태: 현재 단계, 다음 단계, 대기 여부, 재시도 횟수 등
- 비즈니스 상태: 지금까지 에이전트 워크플로에서 일어난 일(OpenAI 메시지 목록, 도구 호출과 결과 목록 등)
이 둘을 분리하는 추상화는 가치가 있을 수 있지만 작은 에이전트에서는 과한 복잡도라는 진단입니다. 가능하면 두 상태를 하나로 합치고, "실행 상태는 컨텍스트 윈도우에서 추론 가능한 메타데이터" 정도로 두라는 권고입니다. Factor 3을 이미 따르고 있다면 LLM에 무엇이 들어가는지는 어차피 자신이 통제하고 있으므로, thread 하나만으로 충분한 단일 진실원(single source of truth)을 가질 수 있습니다.
이렇게 통합된 상태가 주는 이점은 다음과 같습니다.
- 단순성: 모든 상태에 대한 단일 진실원
- 직렬화: thread를 그대로 직렬화·역직렬화 가능
- 디버깅: 한 곳에서 전체 히스토리를 본다
- 유연성: 새 이벤트 타입 추가만으로 상태 확장
- 복구: thread를 불러오면 임의 시점에서 재개 가능
- 포킹: thread 일부를 복사해 새로운 상태 ID로 분기 가능
- 휴먼 인터페이스·관측성: thread → 마크다운 또는 풍부한 웹 UI 변환이 자명
Factor 6 — Launch / Pause / Resume with simple APIs
에이전트도 결국 프로그램이므로, 보통 프로그램에 기대하는 시작/조회/재개/정지 인터페이스를 그대로 갖춰야 한다는 원칙입니다.
- 사용자·앱·파이프라인·다른 에이전트 모두가 단순한 API로 에이전트를 시작할 수 있어야 합니다.
- 장시간 작업이 필요할 때는 결정론적 코드가 에이전트를 일시정지시킬 수 있어야 합니다.
- 웹훅 같은 외부 트리거가 에이전트를 깊은 통합 없이 재개시킬 수 있어야 합니다.
12-Factor Agents 가이드는 특히 도구 선택(tool selection)과 도구 실행(tool execution) 사이 에서 일시정지할 수 있어야 한다고 강조합니다. 많은 오케스트레이터가 이 지점에서의 인터럽트를 지원하지 않아 사람의 승인/검토 흐름을 끼워 넣기가 어렵다는 지적입니다. 이 원칙은 Factor 5(상태 통합), Factor 8(제어 흐름 소유)과 밀접하지만, 독립적으로도 구현할 수 있습니다.
Factor 7 — Contact humans with tool calls
LLM API의 응답은 매 호출마다 첫 토큰 에서 "자연어 텍스트로 시작할지, 구조화된 JSON으로 시작할지" 를 결정합니다. 이 고-위험(high-stakes) 토큰 선택 을 LLM에 떠넘기는 대신, 항상 JSON을 내놓되 그 안의 intent 필드로 사람에게 묻기/끝내기/도구 호출을 구분하자 는 것이 7번 원칙의 핵심입니다.
class Options:
urgency: Literal["low", "medium", "high"]
format: Literal["free_text", "yes_no", "multiple_choice"]
choices: List[str]
class RequestHumanInput:
intent: "request_human_input"
question: str
context: str
options: Options
if nextStep.intent == 'request_human_input':
thread.events.append({"type": "human_input_requested", "data": nextStep})
thread_id = await save_state(thread)
await notify_human(nextStep, thread_id)
return # break loop, wait for webhook
사람의 응답은 슬랙·이메일·SMS 같은 채널에서 웹훅으로 돌아오고, 동일한 thread에 response_from_human 이벤트로 덧붙은 뒤 다시 LLM에게 "다음 단계는?" 을 묻는 흐름으로 자연스럽게 이어집니다. 이 패턴이 갖는 이점은 (1) 사람 호출의 종류별로 명확한 도구 정의, (2) Agent->Human 으로 시작되는 outer loop 워크플로(예: 크론·이벤트로 시작되는 에이전트), (3) 여러 사람으로부터의 입력을 구조화된 이벤트로 추적, (4) Agent->Agent 호출로 자연스럽게 확장되는 다중 에이전트, (5) Factor 6과 합쳐졌을 때의 durable, multiplayer workflow 입니다.
Factor 8 — Own your control flow
제어 흐름을 자신이 작성하면 다양한 종류의 while/if/break 패턴을 마음대로 끼워 넣을 수 있습니다. 12-Factor Agents 가이드는 다음과 같은 커스텀 동작을 예시로 나열합니다.
- 도구 호출 결과의 요약·캐싱
- LLM-as-judge로 구조화된 출력 검증
- 컨텍스트 윈도우 압축이나 메모리 관리
- 로깅·트레이싱·메트릭
- 클라이언트 측 레이트 리미팅
- durable sleep / pause / "wait for event"
가이드의 코드 예시는 세 가지 분기 패턴을 한 번에 보여 줍니다.
def handle_next_step(thread: Thread):
while True:
next_step = await determine_next_step(thread_to_prompt(thread))
if next_step.intent == 'request_clarification':
thread.events.append({"type": "request_clarification", "data": next_step})
await send_message_to_human(next_step)
await db.save_thread(thread)
break # async — webhook이 돌아올 때까지 대기
elif next_step.intent == 'fetch_open_issues':
thread.events.append({"type": "fetch_open_issues", "data": next_step})
issues = await linear_client.issues()
thread.events.append({"type": "fetch_open_issues_result", "data": issues})
continue # sync — 새 컨텍스트로 곧바로 다음 단계 결정
elif next_step.intent == 'create_issue':
thread.events.append({"type": "create_issue", "data": next_step})
await request_human_approval(next_step)
await db.save_thread(thread)
break # async — 사람 승인 후 webhook
저자는 "모든 AI 프레임워크에 대해 가장 자주 들어오는 기능 요청은 도구 선택과 도구 호출 사이에서의 인터럽트/재개" 라고 단언하며, 이 단계를 통제할 수 없다면 (1) 메모리상에서 무작정 대기, (2) 위험도가 낮은 호출만 허용, (3) 그냥 LLM을 믿고 "yolo" — 셋 중 하나로 내몰린다고 적습니다.
Factor 9 — Compact Errors into Context Window
도구 호출이 실패했을 때 그 오류 메시지나 스택 트레이스를 컨텍스트 윈도우에 적합한 형태로 압축해 다시 LLM에 흘려 넣으면, 짧은 태스크에서는 LLM이 스스로 회복(self-healing)할 수 있다는 관찰입니다. 가이드는 다른 11개 원칙을 따르지 않더라도 이 한 가지만은 도입할 만하다고 말합니다.
thread = {"events": [initial_message]}
while True:
next_step = await determine_next_step(thread_to_prompt(thread))
thread["events"].append({"type": next_step.intent, "data": next_step})
try:
result = await handle_next_step(thread, next_step)
except Exception as e:
thread["events"].append({"type": "error", "data": format_error(e)})
# 루프를 돌며 다시 시도
다만 무제한 재시도는 에러 스핀-아웃(error spin-out) 을 부르므로, 가이드는 도구별 또는 전체에 대해 consecutive_errors 카운터를 두고 임계치(예: 3)를 넘으면 사람에게 에스컬레이션하거나 컨텍스트를 일부 재구성하는 패턴을 함께 제시합니다.
consecutive_errors = 0
while True:
...
try:
result = await handle_next_step(thread, next_step)
thread["events"].append({"type": next_step.intent + "_result", "data": result})
consecutive_errors = 0
except Exception as e:
consecutive_errors += 1
if consecutive_errors < 3:
thread["events"].append({"type": "error", "data": format_error(e)})
else:
break # 사람 호출, 컨텍스트 리셋 등으로 전환
저자는 "스핀-아웃을 막는 가장 강력한 방법은 Factor 10 — 작고 초점이 분명한 에이전트" 라고 마무리합니다.
Factor 10 — Small, Focused Agents
거대한 단일 에이전트보다 3~10단계, 많아야 20단계 안에서 특정 도메인을 잘 처리하는 작은 에이전트들을 주로 결정론적인 시스템 의 빌딩 블록으로 끼워 넣으라는 원칙입니다. 핵심 통찰은 LLM의 한계 자체에 있습니다.
"As context grows, LLMs are more likely to get lost or lose focus."
작은 범위로 쪼개면 컨텍스트가 짧게 유지되어 (1) 관리 가능한 컨텍스트, (2) 명확한 책임, (3) 더 나은 신뢰성, (4) 쉬운 테스트, (5) 디버깅 용이성 같은 이점을 얻습니다. "LLM이 더 똑똑해지면 어떻게 되느냐" 는 흔한 질문에 대해 가이드는 "그렇게 되더라도 작은 단위에서 동작하는 시스템은 그대로 가져가면서 점진적으로 범위를 넓혀 가는 편이 안전하다" 고 답합니다. NotebookLM 팀의 인용도 이 원칙을 뒷받침합니다.
"I feel like consistently, the most magical moments out of AI building come about for me when I'm really, really, really just close to the edge of the model capability."
Factor 11 — Trigger from anywhere, meet users where they are
사용자가 이미 사용 중인 채널에서 에이전트를 호출하고, 같은 채널로 답을 받게 만들라는 원칙입니다. Factor 6(launch/pause/resume API)과 Factor 7(사람 호출을 도구로 모델링)이 갖춰져 있으면 자연스럽게 도입할 수 있습니다. 가이드가 정리한 이점은 세 가지입니다.
- 사용자가 있는 곳에서 만나기: 진짜 동료처럼 느껴지는 AI 애플리케이션을 만들 수 있습니다.
- Outer Loop Agents: 사람뿐 아니라 이벤트·크론·장애 알림 등이 에이전트를 트리거할 수 있고, 에이전트가 5~90분 정도 일하다가 결정적 순간에 사람에게 도움/피드백/승인을 요청하는 식의 흐름이 가능합니다.
- 고-위험(high-stakes) 도구 허용: 다양한 사람을 빠르게 루프로 끌어들일 수 있으면, 외부 이메일 전송이나 운영 데이터 수정 같은 위험도가 높은 동작도 명확한 감사 흐름과 함께 위임할 수 있습니다.
Factor 12 — Make your agent a stateless reducer
마지막 원칙은 "여기까지 와서 약간의 재미를 위한" 정리에 가깝다고 저자 스스로 적습니다. 에이전트를 (state, event) → state 형태의 무상태 reducer로 보면, 함수형 프로그래밍의 foldl 패턴과 정확히 맞아떨어집니다. 지금까지 일어난 이벤트의 리스트와 다음 이벤트 하나를 받아 새로운 상태를 돌려주는 순수 함수에 가깝게 에이전트를 설계하라는 권고입니다. 앞서의 Factor 3(컨텍스트 윈도우 소유), Factor 5(상태 통합)와 합쳐지면, "thread를 받아 thread를 돌려주는 함수" 라는 깔끔한 추상화로 전체 시스템을 표현할 수 있게 됩니다.
명예의 전당: Factor 13 — Pre-fetch all the context you might need
12개 외에 Honorable Mentions 로 Factor 13: Pre-fetch all the context you might need 가 부록으로 추가되어 있습니다. "LLM이 필요할 가능성이 높은 컨텍스트는 가능하면 미리 가져와 컨텍스트 윈도우에 넣어 두라" 는 권고로, 12개 원칙을 보완하는 실용적인 팁입니다.
12-Factor Agents의 활용 방식
12-Factor Agents는 직접 import해서 쓰는 라이브러리가 아니라, 자신이 만들고 있는 에이전트의 구조를 12가지 항목으로 점검하는 체크리스트에 가깝습니다. 12-Factor Agents 저장소에서는 "there will be core engineering techniques that make LLM-powered software more reliable, more scalable, and easier to maintain" 라는 한 줄로 12개 항목의 공통 지향점을 정리합니다.
저자는 AI Engineer World's Fair에서 발표한 17분 분량 세션 영상과 추가 deep dive 영상을 함께 제공합니다. Context Engineering 영역에 관심이 있다면 content/factor-03-own-your-context-window.md 챕터부터 펼쳐 보는 것이 12-Factor Agents 저장소가 권하는 진입점입니다. 같은 방법론으로 만들어진 오픈소스 에이전트는 got-agents/agents에서, 동일한 저자가 "자신의 충고를 다 무시하고" 쿠버네티스 위에서 만들어 본 분산 에이전트 프레임워크는 kubechain에서 각각 확인할 수 있습니다.
npx/uvx create-12-factor-agent 라는 부트스트랩 도구가 GitHub Discussion #61에서 논의되고 있으며, 합의가 정리되면 12가지 원칙을 따른 시작점 템플릿을 한 줄 명령으로 만들어낼 수 있게 될 예정이라고 저장소에서 안내됩니다.
12-Factor Agents의 라이선스
12-Factor Agents 저장소는 코드와 콘텐츠에 서로 다른 라이선스를 적용합니다. 코드는 Apache License 2.0으로 공개되어 있어 개인 및 상업적 목적으로 자유롭게 사용할 수 있고, 글(콘텐츠) 및 이미지는 Creative Commons Attribution-ShareAlike 4.0(CC BY-SA 4.0) 라이선스로 공개되어 있어 출처 표기와 동일 라이선스 공유 조건을 만족하면 자유롭게 재사용·재배포할 수 있습니다. 라이선스 구분은 저장소 README의 License 섹션에 명시되어 있습니다.
더 읽어보기
- 12 Factor Apps — 본 가이드가 이름과 정신을 차용한 원조 12개 원칙(웹/SaaS 백엔드용)
- Building Effective Agents (Anthropic) — 본 가이드가 비판적으로 인용하는 "goal + tools + loop" 패턴의 정의 글
- The Outer Loop (theouterloop.substack.com) — 저자(Dex)가 outer loop agents 와 운영 패턴을 정리하는 뉴스레터
- The AI Agent Index (MIT) — 운영 중인 AI 에이전트를 메타데이터로 색인하는 MIT의 공개 인덱스(가이드에서 Related Resources 로 직접 인용)
- AI Engineer World's Fair "12-factor agents" 세션 영상 — 17분 분량 컨퍼런스 발표
- HumanLayer: 3세대 자율형 에이전트를 위한, 사람과 협업하는 SDK — 본 가이드 저자(HumanLayer)의 SDK 소개
- Google, Context Engineering을 위한 세션과 메모리의 개념 및 구현 전략 백서 — Factor 3 Own your context window 와 직접 맞닿는 주제
- Agentic Design Patterns: 지능형 에이전트 시대를 위한 설계 패턴 가이드 (424p) — 12-Factor Agents와 함께 보면 좋은 에이전트 설계 패턴 가이드
- GN⁺ 에이전트 설계는 여전히 어렵다 — 본 가이드와 같은 문제의식을 다룬 커뮤니티 토론 글
12-Factor Agents 프로젝트 GitHub 저장소
이 글은 GPT 모델로 정리한 글을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 덧글로 알려주시기를 부탁드립니다. ![]()
파이토치 한국 사용자 모임
이 정리한 이 글이 유용하셨나요? 회원으로 가입하시면 주요 글들을 이메일
로 보내드립니다! (기본은 Weekly지만 Daily로 변경도 가능합니다.)
아래
쪽에 좋아요
를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ ![]()














