OpenAI Codex 팀이 공개한 에이전트 루프 문서를 공부하면서, AI모델을 사용하는 것과 AI Agentg를 사용하는 것의 차이를 정리했습니다.
- codex 문서: - https://openai.com/index/unrolling-the-codex-agent-loop/
실습자료는 저의 github에 공개되어 있습니다.
- https://github.com/choisungwook/portfolio/tree/master/computer_science/ai/langgraph-agent-loop
이 글에서 다루는 것
- AI 모델을 직접 호출하는 것과 AI 에이전트를 사용하는 것이 어떻게 다른지 비교합니다.
- AI 모델만 사용했을 때 부딪히는 한계(기억 부재, 도구 사용 불가, 단발성 요청)를 정리합니다.
- AI 에이전트의 핵심 기능인 Loop와 Tools를 LangGraph 예제를 만듭니다.
- kuberntes pod의 잘못된 이미지 태그 오류(ImagePullBackOff)를 디버깅하는 AI Agent를 만들어봅니다.
AI 모델
AI 모델을 사용한다는 것은 모델에게 요청을 보내고 모델이 생성한 답변을 받는 것을 말합니다.

LangGraph로 AI 모델만 사용하는 코드는 매우 간단합니다.
- 모델 선택
- 모델에게 사용자 요청 전달
- 모델의 응답 수신
아래는 LangChain init_chat_model로 모델을 호출하는 예제입니다.
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
import os
load_dotenv()
def main():
llm = init_chat_model(os.getenv("LLM_MODEL", "openai:gpt-4o-mini"))
question = "오늘 서울 날씨 어때?"
print(f"[USER] {question}")
response = llm.invoke(question)
print(f"[ASSISTANT] {response.content}")
if __name__ == "__main__":
main()
AI 모델 호출과 응답 과정을 LangSmith로 추적하면 요청과 응답 span 1개만 보입니다. 호출 흐름이 단순합니다.

AI 모델만 사용하는 것의 한계
AI 모델만 사용하면 요청에 대한 응답을 한 번 생성하는 기능밖에 못합니다. 그래서 프로덕션에 그대로 쓰기에는 한계가 있습니다. 대표적인 한계 세 가지를 정리하면 다음과 같습니다.
- 이전 요청을 기억하지 못합니다. AI 모델은 현재 요청만 알 뿐 이전 대화 맥락을 가지고 있지 않습니다.
- 인터넷 검색이나 파일 시스템 접근 같은 행위는 AI 모델 혼자서 할 수 없습니다.
- 모든 요청이 단발성입니다. AI 모델 호출은 한 번에 끝나기 때문에 꼬리질문을 이어가는 식의 진행이 어렵습니다.
이 한계를 극복하려고 사용자의 요청을 AI 모델이 더 잘 해결하도록 감싸는 소프트웨어가 등장했습니다. 이 소프트웨어를 AI 에이전트라고 부릅니다. 챗 AI 인터페이스, CLI 도구(Claude Code, Codex CLI) 등이 모두 AI 에이전트에 해당합니다. 같은 AI 모델을 사용하더라도 어떤 AI 에이전트를 쓰느냐에 따라 답변과 성능이 달라집니다.

AI 에이전트의 대표 기능: Loop
AI 에이전트의 대표 기능 중 하나는 Loop입니다. 앞에서 설명했듯 AI 모델 호출은 단발성이라 모델이 사용자에게 추가 정보를 요구하거나 스스로 후속 작업을 이어갈 수 없습니다. AI 에이전트는 AI 모델이 “끝났다”고 신호할 때까지 모델과 요청, 응답을 반복합니다. 이 반복 과정이 Loop입니다.
Codex CLI 문서에서는 AI 에이전트와 AI 모델이 한 맥락으로 주고받는 한 번의 대화를 turn이라고 부르고, turn이 여러 번 발생할 때 아래처럼 반복된다고 설명합니다.

Loop는 직접 만들 수도 있습니다. 2026년 5월 기준으로 LangGraph로 Loop를 만드는 학습 자료가 많습니다.
from langgraph.graph import StateGraph, START, END
graph = (
StateGraph(State)
.add_node("call_model", call_model)
.add_node("tools", ToolNode(tools))
.add_edge(START, "call_model")
.add_conditional_edges("call_model", should_continue, {"tools": "tools", END: END})
.add_edge("tools", "call_model")
.compile()
)
위 코드의 Loop는 다음과 같이 동작합니다. AI 에이전트가 사용자 요청을 AI 모델에 전달합니다. AI 모델이 도구 사용이 필요하다고 응답하면 AI 에이전트가 도구를 실행하고 그 결과를 모델에게 다시 전달합니다. AI 모델이 도구가 더 이상 필요 없다고 판단하면 Loop를 종료합니다.

Loop의 실제 예제는 다음 챕터인 Tools에서 같이 살펴봅니다.
AI 에이전트의 대표 기능: Tools
AI 모델은 학습된 데이터 범위 밖의 내용은 답변을 생성하지 못합니다. 또는 답을 만들더라도 잘못된 정보를 만들어내는 할루시네이션이 발생합니다.
예를 들어 학습 데이터가 2025년 12월 31일까지라면, 오늘인 2026년 5월 1일의 날씨를 물어봤을 때 모델은 모른다고 답합니다.
- 예제 코드: https://github.com/choisungwook/portfolio/blob/master/computer_science/ai/langgraph-agent-loop/src/ex02_weather_agent.py
llm = init_chat_model(os.getenv("LLM_MODEL", "openai:gpt-4o-mini"))
question = "오늘 서울 날씨 어때?"
print(f"[USER] {question}")
response = llm.invoke(question)
print(f"[ASSISTANT] {response.content}")

AI 모델이 자신이 모르는 영역을 확인할 수 있는 수단이 필요한데, 그 수단이 바로 Tools입니다. AI 모델에게 요청할 때 사용 가능한 도구 목록을 함께 알려줘야 합니다. LangGraph에서는 bind_tools로 어떤 도구를 사용할 수 있는지 모델에 전달합니다.
llm = init_chat_model(os.getenv("LLM_MODEL", "openai:gpt-4o-mini")).bind_tools(tools)
도구는 직접 코드로 작성할 수도 있고, Skills나 MCP처럼 표준화된 도구 인터페이스를 사용할 수도 있습니다. 아래 코드는 서울 날씨를 조회하는 도구를 직접 작성한 예입니다.
from langchain_core.tools import tool
@tool
def get_seoul_weather() -> dict | str:
"""서울의 현재 날씨를 반환한다. 기온(섭씨), 풍속, 날씨 코드를 포함."""
url = "https://api.open-meteo.com/v1/forecast"
params = {"latitude": 37.5665, "longitude": 126.9780, "current_weather": "true"}
try:
r = httpx.get(url, params=params, timeout=10)
r.raise_for_status()
return r.json()["current_weather"]
except (httpx.HTTPError, KeyError, ValueError) as e:
return f"ERROR: open-meteo 호출 실패 — {type(e).__name__}: {e}"
llm = init_chat_model(os.getenv("LLM_MODEL", "openai:gpt-4o-mini")).bind_tools(tools)
위 코드를 실행하면 AI 에이전트는 Loop로 동작합니다. AI 모델이 AI 에이전트에게 get_seoul_weather 도구의 실행 결과를 요청하기 때문입니다.

AI 에이전트는 get_seoul_weather 도구를 실행해 날씨를 조회하고, 그 결과를 AI 모델에게 전달합니다. AI 모델은 받은 결과를 보고 최종 응답을 생성합니다.

kubernetes pod 오류를 진단하는 AI 에이전트 구현
일부러 잘못된 nginx 이미지 태그를 사용하는 pod를 만들고, AI 에이전트가 이미지 문제를 디버깅하는 예제입니다.
spec:
containers:
- name: nginx
image: nginx:1.99-totally-fake-tag

AI 모델만 사용한 경우
AI 에이전트가 아닌 AI 모델만 호출하면 현재 상황을 디버깅하지 못하고 일반적인 디버깅 절차만 알려줍니다.
llm = init_chat_model(os.getenv("LLM_MODEL", "openai:gpt-4o-mini"))
question = "내 nginx 파드가 안 떠요. ErrImagePull인 것 같은데 디버깅 좀 해줘."
print(f"[USER] {question}")
response = llm.invoke(question)
print(f"[ASSISTANT] {response.content}")

LangSmith로 추적하면 OpenAI 모델 요청과 응답 1개만 보입니다.

AI 에이전트를 사용한 경우
LangGraph로 Loop를 구성하고 kubectl을 사용할 수 있는 도구를 만들었습니다.
graph = (
StateGraph(State)
.add_node("call_model", call_model)
.add_node("tools", ToolNode(tools))
.add_edge(START, "call_model")
.add_conditional_edges("call_model", should_continue, {"tools": "tools", END: END})
.add_edge("tools", "call_model")
.compile()
)
@tool
def kubectl_get_pods() -> str:
"""default namespace의 모든 Pod 목록과 상태를 반환한다."""
return _run(["kubectl", "get", "pods", "-o", "wide"])
@tool
def kubectl_describe_pod(name: str) -> str:
"""특정 Pod의 상세 정보(이벤트 포함)를 반환한다."""
return _run(["kubectl", "describe", "pod", name])
@tool
def kubectl_get_events() -> str:
"""default namespace의 최근 이벤트를 시간순으로 반환한다."""
return _run(["kubectl", "get", "events", "--sort-by=.lastTimestamp"])
llm = init_chat_model(os.getenv("LLM_MODEL", "openai:gpt-4o-mini")).bind_tools(tools)
AI 모델은 도구를 사용해 pod 상태를 확인하고 오류 원인을 정확하게 찾았습니다.

LangSmith를 보면 kubectl get pod와 kubectl describe pod 도구가 실행된 흔적이 남아 있습니다.

LangGraph 실행 과정을 살펴보면 AI 에이전트 Loop가 동작하는 모습을 확인할 수 있습니다.

참고자료
- OpenAI, Unrolling the Codex Agent Loop: https://openai.com/index/unrolling-the-codex-agent-loop/
- 예제 저장소: https://github.com/choisungwook/portfolio/tree/master/computer_science/ai/langgraph-agent-loop
'전공영역 공부 기록' 카테고리의 다른 글
| 스터디 챕터 8 정리 - LLM As Judge, AI Agent (0) | 2026.05.05 |
|---|---|
| 스터디 챕터 7 정리 - 프러덕션을 위해, Streamlit을 FastAPI로 마이그레이션 (0) | 2026.05.04 |
| AI에게 youtube 영상을 내 관점으로 분석하게 시키는 방법 (0) | 2026.04.26 |
| macOS끼리 SSH 연결이 자꾸 끊길 때 keepalive 설정하기 (0) | 2026.04.26 |
| LM studio CLI(lms) 사용방법과 openclaw연동(예제 gemma4 MLX) (0) | 2026.04.26 |