채팅에 상주하는 AI 에이전트는 긴 조사나 여러 도구 호출을 거치는 응답 생성 중에, 사용자로부터 '괜찮아요', '그거 다시 해줘'와 같은 새로운 메시지가 도착할 수 있습니다. 생성 중인 LLM(Large Language Model) 호출을 단순히 무시하고 계속 진행하게 두면, 엉뚱한 장문이 나중에 전송되어 사용자를 혼란스럽게 만들고, 반대로 프로세스를 강제로 종료하면, 생성 도중에 이미 발화했던 도구 호출(메일 전송/티켓 업데이트 등)만 공중에 떠 있는 상태로 남게 됩니다. 본 글에서는 상주 에이전트가 '응답 생성 중단'을 안전하게 처리하기 위한 설계를 정리합니다.
왜 취소는 단순히 '생성을 멈추는 것'만으로는 부족한가
사용자 관점의 '취소하고 싶다'는 실제로는 여러 계층이 복합적으로 얽혀 있습니다.
- 출력 레이어: 아직 화면에 표시되지 않은 텍스트의 생성을 멈추는 것(스트리밍 중단)
- 부작용 레이어: 생성 과정에서 이미 실행해 버린 외부 API 호출/도구 호출을 어떻게 처리할지
- 상태 레이어: '취소되었다'는 사실을 대화 기록에 어떻게 기록하고, 다음 턴의 맥락에 모순 없이 인계할지
출력만 멈추고 부작용 레이어를 방치하면, '취소했는데 뒤에서 메일이 전송되고 있었다'라는 가장 신뢰도를 떨어뜨리는 사고로 이어질 수 있습니다.
패턴 1: 중단 가능한 지점을 도구 호출의 전후에 한정하기
LLM의 토큰 생성 자체는 임의의 순간에 중단해도 괜찮습니다(표시되지 않은 중간 출력을 버리기만 하면 되기 때문입니다). 반면, 부작용을 가지는 도구 호출은 '실행 시작 전' 또는 '실행 완료 후' 둘 중 한 곳에서만 안전하게 중단할 수 있습니다. 실행 중에 취소 신호가 오면, 해당 도구 호출 자체를 완료한 후에 다음 단계로 넘어가기 전에 멈추도록 설계합니다.
type CancelToken = { cancelled: boolean };
async function runTurn(steps: Step[], token: CancelToken) {
for (const step of steps) {
...
}
토큰 단위의 스트리밍 출력은 token.cancelled를 보는 순간 멈춰도 무방하지만, 도구 실행 루프에서는 '다음 단계에 진입하기 전'만을 체크포인트로 삼는 것이 핵심입니다.
패턴 2: 취소 시점에서 이미 실행된 부작용을 대화 기록에 명시하기
취소된 턴 안에서 이미 실행해 버린 도구 호출이 있는 경우, 그것을 마치 '흑역사'처럼 지우기보다는, '중단되었지만, 여기까진 실행 완료되었습니다'라는 형태로 대화 기록과 사용자 알림 양쪽에 남겨야 합니다.
| 상황 | 대응 |
|---|
| 도구 호출 전 취소 | 해당 단계는 미실행으로 기록. 사용자에게 알림 불필요 |
| ... | |
이러한 기록을 게을리하면, 다음 턴에서 에이전트가 '저 도구 호출은 아직 실행하지 않았다'고 오인하여 동일한 처리를 중복 실행할 위험이 생깁니다.
패턴 3: 신규 메시지에 의한 '암묵적 취소'와 명시적 취소를 구분하기
사용자가 '취소'라고 말하지 않고, 생성 중에 완전히 다른 주제의 메시지를 보내오는 경우도 있습니다. 이를 즉각적인 끼어들기(interruption)로 처리할지, 현재 생성을 끝낸 후에 새 메시지를 처리할지는 메시지의 내용에 따라 판단을 분리하는 것이 안전합니다.
- 신규 메시지가 명확한 정지 지시('멈춰', '그만해', '아니야' 등)를 포함 → 즉시 중단해도 좋음
- 신규 메시지가 무관한 별건의 요청 → 현재 생성을 중단하지 않고, 큐에 쌓아 순차적으로 처리함(멀티태스킹처럼 보이지만 실제로는 사고의 원인이 되기 쉬움)
- 판단이 모호할 경우 → 중단하지 않고 완주시키는 것이 좋음(중단으로 인한 부작용 불일치 위험이 응답이 다소 장황해지는 위험보다 크기 때문)
'멈춰'라는 말만으로 판단하는 것이 아니라, 현재 실행 중인 도구 호출이 취소 가능한 종류인지 여부까지 고려하여 어느 쪽으로 기울일지 결정해야 합니다.
요약
- 응답 생성의 취소는 '출력', '부작용', '상태' 3개 계층으로 나누어 생각할 필요가 있으며, 출력을 멈추는 것만으로는 불충분함
- 도구 호출의 중단은 실행 전/실행 후 체크포인트에 한정하고, 실행 중인 처리는 완료한 후에 멈춤
- 취소 시점에서 이미 실행된 부작용은 숨기지 않고 대화 기록과 사용자 알림에 남겨 중복 실행을 방지함
- 신규 메시지에 의한 암묵적인 중단 요구는 명확한 정지 지시인지 여부에 따라 즉시 중단과 완주를 구분하여 사용함
이 설계를 소홀히 할 경우, AI의 자동 처리가 이중으로 실행될 수 있다는 불안감 때문에 다루었던 이중 실행 문제를, 취소(キャンセル) 작업 자체가 야기하게 될 위험이 있습니다. 중단은 '멈추는' 기능인 동시에, '어디까지 진행되었는지 정확하게 기록하는' 기능으로 이해하는 것이 안전합니다.
필자는 Slack / Teams / Chatwork / LINE WORKS에 상주하며 채팅, 이메일, 캘린더, 회의록을 자동으로 수집하여 매일 아침 리포트를 전달하는 AI 에이전트 HACH를 개발하고 있으며, 장시간 작업 중단 및 재개, 그리고 부작용의 일관성 유지(整合性維持)는 추론 시 마스킹이나 AWS 내부 완결 설계와 더불어 운영상 중요한 관점이라고 생각합니다.
Discussion