LabHub
배우기 러닝패스 코스

AI 에이전트 — 모델이 아니라 그래프 · 상태 스키마와 리듀서 · 실습

지나온 길이 한 칸만 남는다

LabHub 에서 이어서 보기

목표

에이전트 상태를 열쇠 목록이 아니라 합치는 규칙으로 설계한다. 리듀서가 없을 때 무슨 일이 생기는지 직접 재현한 뒤, 이어 붙이기·중복 제거·최댓값·창 자르기 네 가지 리듀서를 만들고, 입력과 출력 스키마를 나눠 바깥에 나갈 열쇠를 좁힌다.

왜 중요한가

LangGraph 의 상태는 열쇠마다 채널이 하나씩 있는 구조다. 노드는 바꾸고 싶은 열쇠만 담은 딕셔너리를 돌려주고, 그래프가 채널별로 적용한다. 이때 리듀서를 안 적은 열쇠는 덮어쓴다 — 세 노드가 차례로 쓴 trace 가 마지막 하나만 남는 것이 그래서다. 오류가 나지 않아서 "로그가 안 남는다" 로 보이고, 로그 코드를 의심하다 시간을 버린다.
반대쪽 문제도 있다. 리듀서를 붙이면 그 열쇠는 끝없이 자라는데, 체크포인터는 상태를 통째로 저장한다. 노드가 서른 번 돌면 체크포인트도 서른 개고 하나하나가 그 시점의 상태 전체다. 그래서 자라는 열쇠에는 상한을 리듀서 안에 적어 둔다 — 노드마다 흩어 두면 한 곳만 빠뜨려도 조용히 새어 나간다.
마지막으로 상태에는 바깥에 보이면 안 되는 것이 섞인다. 출력 스키마로 나갈 열쇠를 화이트리스트로 정하면, 새 열쇠가 늘어도 저절로 막힌다.
채점기는 여러분이 적어 둔 설명을 믿지 않는다. 여러분의 모듈을 실제로 불러서 리듀서를 매번 다른 값으로 직접 두드려 보고, 그래프를 돌려 나온 상태를 채점기가 따로 계산한 값과 대조한다. 노드 이름과 숫자는 실행마다 바뀐다.

단계

1. /root/work/agstate/state.pyCATALOG·State·노드 셋(intake·lookup·finishbuild_graph() 를 만드세요. 노드는 바꾸는 열쇠만 돌려주고, 손대지 않은 열쇠는 그대로 남아야 합니다.
2. overwrite_demo(names) 를 더해 리듀서 없는 열쇠가 덮어써지는 것을 재현하게 하세요. 이름마다 노드를 하나씩 만들어 줄줄이 잇고, 노드마다 seen 에 자기 이름 하나를 씁니다.
3. StatetraceAnnotated[list, operator.add] 를 붙여 세 노드의 발자국이 순서대로 쌓이게 하세요.
4. 리듀서 merge_sources(old, new) 를 만들고 sources 열쇠에 붙이세요. 같은 출처는 한 번만 남고 순서는 처음 본 순서를 지킵니다.
5. used_callsoperator.add 를, peak_ms 에 직접 만든 keep_max(old, new) 를 붙이세요.
6. RECENT_KEEP = 3 과 리듀서 keep_recent(old, new) 를 만들어 recent 열쇠가 뒤에서 세 개만 남게 하세요. finish 는 한 번에 두 개를 씁니다.
7. InputState·OutputState 를 만들고 build_public()StateGraph(State, input=InputState, output=OutputState) 로 컴파일한 그래프를 돌려주게 하세요. 결과에는 answer 만 나와야 합니다.
8. /root/work/agstate/state_report.json/root/work/agstate/state_report.md 에 상태 설계를 기록하세요.

참고

단계 8개

  1. 노드는 바꾸는 열쇠만 돌려준다
  2. 리듀서가 없으면 마지막 하나만 남는다
  3. 발자국을 쌓는 리듀서
  4. 같은 출처를 두 번 적지 않는다
  5. 더할 것과 가장 큰 것만 남길 것
  6. 자라는 열쇠에 상한을 건다
  7. 나갈 것만 내보낸다
  8. 왜 그렇게 정했는지 남긴다