Agent는 어떻게 설계하는가 — 상태 관리가 핵심
Agent를 상용에 올릴 수 있는지를 진짜로 결정하는 것은 상태 관리다. 도구는 일하는 "손"이고, **상태야말로 Agent의 "작업 현장"**이다.
상태 관리가 없을 때의 4가지 사고 유형
- 같은 인터페이스를 반복 호출한다
- 사용자가 방금 확정한 제약을 잊어버린다
- 실패 응답을 성공으로 이해한다
- 작업 도중에 컨텍스트를 잃어버린다
제1류: 세션 상태 (Session State)
- 기록 대상: 이번 대화 턴에서 무슨 일이 있었나, 사용자가 지금 무엇을 묻고 있나, 모델이 방금 어떤 판단을 했나
- 생명주기: 현재 세션 안에서만 유효
- 예시: 사용자가 "이번엔 면접 톤으로 답해줘"라고 말한 것 — 이것은 현재 답변의 스타일 제약이며 반드시 장기 선호가 되어야 하는 것은 아니다
제2류: 작업 상태 (Task State)
- 발동 조건: 작업이 한 단계를 넘어가는 순간 진행 상황을 추적해야 한다
- 전형적인 진행 상태 열거값:
- 요구사항 명확화 완료
- 자료 수집 완료
- 도구 미실행
- 사용자 확인 대기
- 최종 결과 취합 중
- 역할(양방향): Agent가 매번 처음부터 다시 시작하지 않게 하고, 동시에 핵심 동작을 빠뜨리지 않게 한다
- 예시: 데이터를 가져왔는지, 변동 항목을 설명했는지, 결론을 확인했는지를 알아야 하며, 매번 처음부터 다시 계획을 세우면 안 된다
제3류: 사용자 상태 (User State)
- 내용: 사용자 신원, 권한, 선호, 과거 선택, 장기 목표
- 핵심 요구: 과거 대화 내용에만 의존해 유지해서는 안 되고 구조화해서 관리해야 한다
- 예시: 사용자가 어떤 프로젝트를 볼 수 있는지, 어떤 역할인지, 상용하는 출력 포맷이 무엇인지
- 판단 기준: 이런 것들은 모두 결정론적으로 조회해야 하며, 모델이 대화 조각들 사이에서 유사도로 추측하게 두면 안 된다
제4류: 외부 시스템 상태 (External State)
- 내용: 주문 결제 여부, 재고 사용 가능 여부, DB 쓰기 성공 여부, 알림 발송 여부
- 성질 규정: 이것들은 외부 시스템 안의 사실이지, 모델 컨텍스트 안의 글자가 아니다
- 철칙: 핵심 결정을 내리기 전마다 외부 상태를 다시 확인해야 한다 — 직전 단계에서 "사용 가능"을 봤다고 해서 다음 단계에서도 계속 사용 가능하다고 기본 가정하면 안 된다
상태 쓰기 전략 (5문)
미리 정의해야 할 다섯 가지 질문:
- 어떤 상태를 모델이 쓸 수 있는가
- 어떤 것이 반드시 도구 반환에서 와야 하는가
- 어떤 것이 이번 턴에만 유효한가
- 어떤 것을 장기 보존해야 하는가
- 어떤 것은 심지어 기존 값을 덮어써야 하는가
전략이 없을 때의 결과:
- 임시 정보가 장기 기억으로 침전된다
- 이미 실효한 상태가 계속 이후 의사결정에 딸려 들어간다
핵심 통찰
- 능력(도구)과 통제 가능성(상태)은 별개다 — Function Calling은 "할 수 있는가"를 풀고, 상태 시스템은 "상용에 올릴 수 있는가"를 푼다. 면접과 아키텍처 리뷰의 진짜 분수령은 후자에 있다.
- "상태야말로 작업 현장"은 매우 강력한 멘탈 모델 — 도구 호출은 순간적 동작이고, 상태는 동작들을 가로지르는 연속적 현장이다. 현장이 없으면 모든 도구 호출이 뿌리 없는 나무가 되어 중복 호출, 제약 유실, 성패 오판이 발생한다.
- 상태는 생명주기에 따라 계층화해야지 같은 컨텍스트에 밀어 넣으면 안 된다 — 세션급 / 작업급 / 사용자급 / 외부급, 네 계층의 생존 기간이 차례로 길어진다(한 턴 → 한 작업 → 세션을 넘어 → 외부 시스템이 결정). 이것들을 하나의 memory에 섞으면 반드시 문제가 생긴다.
- 임시 제약을 장기 선호로 승격시키지 말 것 — "이번엔 면접 톤으로"는 이번 턴의 스타일 제약일 뿐이다. 이걸 구분하지 못하면 Agent는 우발적 지시를 인격 설정으로 고착시키는데, 이는 기억 계열 제품에서 가장 흔한 실패 지점이다.
- 작업 상태의 가치는 양방향이다 — 매번 처음부터 다시 하는 것(중복 노동, 중복 과금)도 막고, 핵심 동작 누락도 막는다. 한쪽만 강조하면 불완전하다.
- 사용자 상태는 "유사도 검색"이 아니라 "결정론적 조회"여야 한다 — 신원, 역할, 권한 같은 정보를 벡터 소환으로 추측하는 것은 위험하다. 이것들은 구조화 저장소에 대한 확정적 쿼리에서 와야 한다. 이 한 줄이 RAG와 상태 관리의 경계를 긋는다.
- 외부 사실 ≠ 컨텍스트의 글자 — 컨텍스트에 "재고 사용 가능"이라고 적혀 있는 것은 모델이 그 문장을 본 적이 있다는 뜻일 뿐, 지금도 성립한다는 뜻이 아니다. 핵심 결정 전에는 반드시 다시 조회해야 하며, 그러지 않으면 스냅샷을 실시간으로 착각하는 것이다.
- 상태 쓰기 권한은 DB 권한처럼 설계해야 한다 — "모델이 자율적으로 쓰기"와 "도구 실행 결과 반환"은 신뢰도가 완전히 다른 두 소스다. 모델이 외부 사실형 상태를 마음대로 쓰게 하는 것은 환각이 시스템의 진리값을 오염시키도록 허용하는 것과 같다.
- 쓰기 전략이 없으면 두 방향의 부패가 동시에 발생한다 — 위로의 부패(임시 정보가 장기 기억으로 침전)와 아래로의 부패(실효 상태가 계속 의사결정에 참여). 둘 다 장기 운영 후에 한꺼번에 터진다.
- 상태에 3속성을 정의하면 바로 테이블 구조가 된다 — 생명주기, 읽기·쓰기 권한, 검증 방식. 이 세 컬럼을 채우는 순간 상태 설계는 구호에서 스키마로 바뀐다.
엔지니어링 실전 Tips
- 답변 순서: 먼저 부정(도구 목록은 핵심이 아니다) → 결론 제시(상태 시스템이 핵심이다) → 4가지 상태 → 3속성(생명주기 / 읽기·쓰기 권한 / 검증 방식) → 쓰기 전략. 디테일보다 구조가 점수를 더 받는다.
- "작업 진행 상황"을 명시적 열거 필드로 만들 것. 모델이 과거 대화에서 자기가 어느 단계에 있는지 추론하게 두지 말 것.
- 권한류 정보는 언제나 결정론적 쿼리로. 역할, 가시 프로젝트 범위는 벡터 검색으로 명중시키면 안 된다.
- 핵심 동작 전에 외부 상태 갱신을 강제할 것. "조회"를 선택적 단계가 아니라 의사결정의 전치 단계로 만들 것.
- "모델이 쓸 수 있는 것"과 "도구가 쓸 수 있는 것"을 두 개의 테이블로 분리할 것. 외부 사실형 상태는 모델 쓰기 금지.
- 모든 상태에 만료/실효 규칙을 부여할 것. 실효 상태가 계속 이후 의사결정에 딸려 들어가는 것을 방지.
- 임시 제약은 별도 보관하고 세션과 함께 파기할 것. 장기 기억으로 침전되는 것을 방지.