9장 · 에이전트 루프 직접 구현왜 에이전트 루프가 필요한가 — 결과를 봐야 다음 할 일이 정해진다ReAct — 생각, 행동, 관찰을 되풀이한다contents — 루프의 기억은 리스트 하나다종료 조건과 max_steps — 루프는 언제 멈추는가따라하기 — ReAct 루프 만들기정리와 체크리스트실습문제와 해답
9장. 에이전트 루프 직접 구현
정리와 체크리스트
9장에서 배운 것
- 에이전트 루프(agent loop) — 조회하고, 결과를 보고, 다음 할 일을 정하는 일을 끝날 때까지 되풀이하는 구조.
- ReAct — 한 바퀴를 생각(Thought) → 행동(Action) → 관찰(Observation)로 나눈 방식. 생각은 모델, 행동과 관찰은 우리 코드.
contents— 질문, 모델의 요청, 도구의 결과가 차례로 쌓이는 리스트. 루프의 기억이고, 매 바퀴 통째로 모델에게 갑니다.- 종료 조건 — 응답에 도구 요청이 없으면 최종 답변. 끝낼 때는 모델이 정합니다.
max_steps— 모델이 끝내지 않을 때를 대비한 반복 한도. 닿으면 티켓을 실제로 접수하고 그 번호를 안내합니다.- 병렬 함수 호출 — 모델이 한 응답에 도구 요청을 여러 개 담는 것.
한눈에 보는 핵심
contents = [질문]
for step in range(1, max_steps + 1):
response = client.models.generate_content(model=MODEL, contents=contents, config=config) # Thought
if not response.function_calls:
return response.text # 도구 요청이 없다 → 종료
contents.append(response.candidates[0].content) # 모델의 요청을 통째로 기록
parts = [도구를 실행한 결과 … for fc in response.function_calls] # Action
contents.append(types.Content(role="user", parts=parts)) # Observation
ticket = tools["create_ticket"](...) # 한도 도달 → 실제로 접수
return f"… 티켓({ticket['ticket_id']})으로 접수해 드렸어요."
| 모델이 정하는 것 | 우리 코드가 정하는 것 |
|---|---|
| 어떤 도구를, 어떤 인자로 | 쓸 수 있는 도구의 목록 |
| 한 번에 몇 개를 요청할지 | 도구의 실제 실행 |
| 몇 바퀴 만에 답할지 | 최대 몇 바퀴까지 허락할지 |
| 측정 | 이번 장의 값 |
|---|---|
| 바퀴 수 | 3 |
| 모델 호출 / 도구 실행 | 3번 / 4번 |
| 바퀴별 입력 토큰 | 694 → 1,427 → 2,003 |
체크리스트
- [ ] "배송중인 주문의 송장번호를 전부 알려 달라"가 한 번의 도구 호출로 풀리지 않는 이유를 설명할 수 있다.
- [ ] 6장부터 쓴 자동 함수 호출과 이번 장의 루프가 어떤 관계인지 말할 수 있다.
- [ ] ReAct의 세 단계를 말하고, 각각 코드의 어느 줄인지 짚을 수 있다.
- [ ] 루프가 정상적으로 끝나는 조건을 코드 한 줄로 가리킬 수 있다.
- [ ]
contents에 한 바퀴마다 무엇이 쌓이는지 순서대로 말할 수 있다. - [ ] 도구 결과를 돌려줄 때
role에 무엇을 쓰는지 안다. - [ ] 실행 결과에서 step 2의 주문번호가 어디서 왔는지 설명할 수 있다.
- [ ] 바퀴가 늘수록 입력 토큰이 늘어나는 이유를
contents로 설명할 수 있다. - [ ]
max_steps가 너무 작을 때와 너무 클 때 각각 무슨 일이 생기는지 말할 수 있다. - [ ] 8장의 도구가 예외를 내지 않는데도 루프에
try가 있는 이유를 설명할 수 있다.
한 줄 핵심
에이전트 루프는 "모델에게 묻고, 요청한 도구를 실행하고, 결과를 쌓아 다시 묻는" 반복문입니다. 다음에 무엇을 할지는 모델이 정하고, 어디까지 허락할지는 우리가 정합니다.