LabHub
배우기 러닝패스 코스

AI 에이전트 — 모델이 아니라 그래프 · 중단점과 사람의 개입 · 실습

고액 환불이 승인 목록에 뜨지도 않았다

LabHub 에서 이어서 보기

목표

되돌릴 수 없는 일 앞에서 그래프를 멈추고, 사람이 값을 고치거나 거절한 뒤 이어서 돌린다. 멈추는 방법 두 가지를 모두 만들어 보고 둘의 차이를 직접 센 숫자로 확인한다.

왜 중요한가

LangGraph 에서 멈춤은 저장 위에 세워져 있다. 멈춘다는 것은 "다음 단계를 지금 하지 않고 남겨 둔 상태에서 나중에 이어서 한다" 는 뜻이라, 남겨 둘 곳(체크포인터)이 없으면 이어서 할 수도 없다. 그런데 체크포인터 없이 중단점만 주어도 오류가 나지 않는다 — 그래프는 조용히 멈추고 절반짜리 상태를 돌려준다. 이 실습에서 그것을 먼저 자기 눈으로 봅니다.
멈춘 뒤 사람이 하는 일은 승인만이 아니다. 금액을 깎기도 하고 거절하기도 한다. update_state 로 고친 값은 그 열쇠의 리듀서를 거쳐 들어가므로, 덮어쓰는 열쇠와 이어 붙이는 열쇠가 다르게 동작한다.
멈추는 방법은 두 가지다. interrupt_before 는 노드에 들어가기 전에 멈추고, 노드 안의 interrupt() 는 부른 그 자리에서 멈춘다. 후자는 재개할 때 그 노드를 처음부터 다시 돈다 — 앞에 둔 부수 효과가 두 번 일어난다는 뜻이다. 이 실습에서 몇 번 들어오는지 직접 셉니다.
채점기는 여러분이 적어 둔 설명을 믿지 않는다. 여러분의 모듈을 실제로 불러 임의의 금액과 사유로 돌려 보고, 멈춘 자리와 이어 돌린 결과를 채점기가 따로 계산한 값과 대조한다.

단계

1. /root/work/aghitl/approve.pyAUTO_LIMIT = 100000·RISKY·needs_approval(amount, reason)·State·노드 셋(intake·auto_settle·settletriage·build_graph() 를 만드세요. 아직 멈추지 않습니다.
2. build_forgotten()run_forgotten(amount, reason) 을 더하세요. 체크포인터 없이 interrupt_before=["settle"] 만 준 판을 돌려 무슨 일이 생기는지 적습니다.
3. SAVER = MemorySaver()·build_pausing()·thread(name)·start_case(amount, reason, name) 를 더해 진짜로 멈추게 하세요. start_case{"next": ["settle"], "outcome": "", "paid": -1} 를 돌려줍니다.
4. resume_case(name) 을 더해 invoke(None, config) 로 이어서 돌리게 하세요.
5. resume_case(name, amount=..., decision=...) 로 사람이 금액을 고치거나 거절한 뒤 이어서 돌리게 하세요. 거절이면 한 푼도 나가지 않습니다.
6. confirm 노드와 build_asking()·ask_and_answer(amount, reason, answer, name) 을 더하세요. 노드 안에서 interrupt() 로 멈추고 Command(resume=답) 으로 이어서 돌립니다. 노드에 몇 번 들어왔는지 SIDE_EFFECTS 로 셉니다.
7. handle(...) 을 더해 한 건을 끝까지 처리하고 요청값과 집행값, 승인 여부를 한 줄로 남기게 하세요.
8. /root/work/aghitl/approve_report.json/root/work/aghitl/approve_report.md 에 기록을 남기세요.

참고

단계 8개

  1. 사람이 봐야 하는 일을 가른다
  2. 체크포인터를 빠뜨리면 조용히 사라진다
  3. 진짜로 멈춘다
  4. 남겨 둔 데서 이어서 돌린다
  5. 승인자가 금액을 고치거나 거절한다
  6. 노드 안에서 멈추면 그 노드는 두 번 돈다
  7. 요청한 값과 나간 값을 함께 남긴다
  8. 무엇을 보았는지 기록한다