상시 실행 에이전트는 중단 없이 계속 동작하면서, 여러 세션에 걸쳐 언제 어떻게 행동할지 스스로 판단합니다. 이 가이드에서는 에이전트를 이루는 핵심 구성 요소와 이들이 서로 맞물려 동작하는 방식을 단계별로 살펴봅니다.
최근 몇 달 사이 상시 실행 에이전트가 다시 주목받고 있습니다.
상시 실행 에이전트는 상태를 유지하며 먼저 움직이는 에이전트입니다. 세션을 넘나들며 컨텍스트를 관리하고, 사용자가 직접 지켜보지 않아도 스스로 작업을 수행합니다. 내부적으로는 다른 에이전트와 같은 핵심 루프로 동작합니다. 차이는 이를 둘러싼 아키텍처에 있습니다. 이 아키텍처는 에이전트가 언제 깨어나는지, 실행과 실행 사이에 무엇을 이어받는지, 작업 결과가 어떻게 사용자에게 전달되는지를 제어하는 구성 요소(primitive)로 이루어집니다.
이렇게 다시 주목받게 된 가장 큰 이유는 최근 모델이 발전하면서 상시 실행 에이전트를 실제로 운영하기가 한결 현실적으로 바뀌었기 때문입니다. 우선 최신 모델은 판단력이 좋아졌습니다. 사용자의 의도를 더 안정적으로 파악하고, 언제 사용자에게 확인을 구해야 하는지도 더 잘 압니다. 또한 지능을 활용하는 비용이 낮아지고 있으며, 그 혜택은 장기 작업에서 가장 큽니다. 예를 들어 어떤 장기 코딩 벤치마크에서 Opus 5.5는 해결한 작업 하나당 비용이 Opus 5보다 78% 적게 들었습니다. 일반적인 워크로드에서는 40% 감소에 그쳤습니다.
이런 경험을 자사 제품에 도입하는 방법을 묻는 고객도 늘고 있습니다. 기존 에이전트가 더 능동적으로 움직이도록 만들고 싶어 하는 회사도 있고, 처음부터 새로 만들려는 회사도 있습니다.
이 글에서는 상시 실행 에이전트를 이루는 구성 요소를 하나씩 짚어 보고, 이들이 어떻게 맞물려 동작하는지 살펴봅니다.
사실 상시 실행 에이전트는 실제로 "항상 켜져" 있지 않습니다. 사용자가 느끼는 경험을 그렇게 표현할 뿐입니다.
실제로 에이전트는 대부분의 시간을 잠들어 있다가 주기적으로 깨어나 일합니다. 이렇게 한 번 일하는 구간을 실행(run)이라고 합니다. 에이전트는 이벤트를 받아 작업을 마친 뒤, 무슨 일이 있었는지 기록으로 남깁니다. 실행은 세션(session) 안에서 이루어지며, 세션은 메시지와 도구 호출을 기록한 대화 내역입니다. 실행이 끝나면 에이전트는 다시 잠들고, 이 주기가 끝없이 반복됩니다.

상시 실행 에이전트를 둘러싼 아키텍처에는 다섯 가지 핵심 구성 요소가 있습니다. 이벤트 인박스, 타이머, 메모리, 권한, 아웃박스입니다. 하나씩 살펴보겠습니다.
대부분의 AI 에이전트는 사용자가 메시지를 보낼 때만 실행됩니다. 반면 상시 실행 에이전트는 웹훅, 예약 작업, 백그라운드 작업 등 다양한 이벤트로 실행될 수 있습니다.
이벤트 소스가 각자 에이전트를 직접 호출하게 만들고 싶은 유혹이 들 수 있지만, 이 방식에는 몇 가지 문제가 있습니다. 예를 들어 이벤트 두 개가 동시에 도착하면 실행이 서로 경합할 수 있고, 장애가 나면 이벤트가 통째로 유실될 수 있습니다.
이때 필요한 것이 이벤트 인박스입니다. 각 소스는 에이전트를 직접 호출하는 대신 인박스에 이벤트를 보내고, 워커가 이를 가져가 처리합니다.
가장 단순한 형태는 세 가지로 구성됩니다.
인박스는 이벤트별 상태를 추적해야 하며, 소스가 제공하는 고유 식별자로 중복 이벤트를 걸러낼 수 있습니다. 인박스에는 관계형 데이터베이스가 잘 맞고, 이벤트는 새 행으로 계속 추가하면 됩니다. 처음에는 사용자당 인박스 하나로 시작하길 권하며, 병렬 처리가 더 필요하면 그때 나누면 됩니다.

새 이벤트가 들어오면 핸들러는 이를 인박스에 기록하고 워커를 깨웁니다. 워커는 대기 중인 이벤트를 모두 읽어 실행을 시작합니다. 사용자의 답장처럼 이전 작업을 이어가는 이벤트는 기존 세션을 재개하고, 나머지는 새 세션을 시작합니다.
그다음 워커는 이벤트를 에이전트 루프에 전달하고, 실행이 끝나기를 기다린 뒤 해당 이벤트를 완료 처리합니다. 구현 세부 사항은 까다로울 수 있으니 몇 가지 모범 사례를 소개합니다.
타이머는 이벤트 인박스와 함께 상시 실행 에이전트가 먼저 움직이게 해 줍니다. 타이머는 크게 후속 확인(follow-up)과 스케줄(schedule)로 나뉩니다. 후속 확인은 답장 여부를 확인하는 것처럼 에이전트가 스스로 정해 두는 기한입니다. 반면 스케줄은 매일 보내는 뉴스레터처럼 정해진 주기로 반복되는 작업입니다.
타이머는 인박스와 별도로, 자체적인 영구 저장소(보통 또 다른 데이터베이스 테이블)에 둡니다. 인박스에는 바로 처리할 수 있는 이벤트만 있어야 하기 때문입니다. 후속 확인과 스케줄은 비슷한 스키마를 공유할 수 있지만, 스케줄에는 반복 주기 정보도 필요합니다.

타이머가 스스로 실행을 시작하는 것은 아닙니다. 대신 스케줄러(보통 백그라운드 서비스)가 일정한 간격으로 저장소를 조회해, 시간이 된 타이머를 작동시킵니다. 스케줄러는 매번 다음 순서로 동작합니다.
스케줄러는 직접 서비스를 만들어도 되고, 내구성 있는 실행 엔진(durable execution engine)을 써도 됩니다.
상시 실행 에이전트는 서로 끊어진 수많은 실행에 걸쳐 일하므로, 연속성을 유지하려면 메모리가 필요합니다.
이벤트 인박스, 타이머와 마찬가지로 메모리도 별도의 저장소를 두어야 합니다. Claude Code의 자동 메모리나 Messages API의 메모리 도구 같은 Anthropic 제품에서는 메모리를 파일 디렉터리로 구현합니다. 상시 실행 에이전트라면 이 디렉터리를 영구 저장소(보통 데이터베이스나 오브젝트 스토어)에 연결해야 합니다. 그래야 워커가 사라져도 메모리가 남습니다.
경험칙으로, 메모리에는 에이전트가 다시 조회할 수 없는 내용만 담아야 합니다. 이슈 트래커처럼 이미 다른 시스템에 있는 정보라면 내용 대신 해당 위치를 가리키는 포인터를 저장하세요. 상시 실행 에이전트가 저장해야 할 메모리 유형은 다음과 같습니다.
아래 다이어그램은 구성 예시입니다.

지금까지 설명한 것은 실행 중에 저장되는 메모리입니다. 여기에 드리밍(dreaming)을 더할 수도 있습니다. 드리밍은 과거 세션을 돌아보며 메모리를 정리하는 과정으로, 오래된 항목을 교체하고 여러 실행에 걸쳐서야 드러나는 패턴을 찾아낼 수 있습니다. 더 자세히 알고 싶다면 에이전트 메모리에 관한 글에서 다룬 내용을 참고하세요.
에이전트는 작업에 들어가기 전에 시스템 프롬프트, 도구 정의, 메모리 파일을 불러옵니다. 이 초기 컨텍스트 "오버헤드"는 매 실행마다 포함되므로 최대한 간결하게 유지하고, 프롬프트 캐싱으로 비용을 낮추기를 권합니다.
새 세션은 이 컨텍스트 오버헤드와 실행을 일으킨 이벤트만 가지고 시작합니다. 반면 기존 세션은 이전 실행의 메시지와 도구 호출까지 함께 되살립니다.
세션이 너무 길어지면 오래된 메시지를 압축하거나 새 세션을 시작할 수 있습니다. 어느 쪽이든 세부 내용이 일부 사라지므로, 계속 보존해야 할 정보는 작업하는 중간중간 메모리에 저장해 두어야 합니다.

상시 실행 에이전트에서 위험이 가장 큰 부분이 권한입니다. 실행은 사용자의 접근 권한을 쥐고 있으면서, 설계상 사람이 지켜보지 않는 상태로 동작합니다. 에이전트는 도구를 호출할 때마다 스스로 진행할지, 차단할지, 승인을 기다릴지 결정해야 합니다.
권한을 구성하는 요소는 다른 에이전트와 같습니다.
대부분의 AI 에이전트는 응답을 생성되는 대로 사용자에게 스트리밍합니다. 그래서 사용자는 Claude가 문제를 추론하고, 도구를 호출하고, 답변을 작성하는 과정을 지켜볼 수 있습니다.
반면 상시 실행 에이전트는 대부분의 작업을 백그라운드에서 처리합니다. 사용자는 단계별 과정 전체가 아니라 결과와 몇 가지 세부 내용만 받습니다.

실행은 세 가지 중 하나로 끝납니다.
대부분의 상시 실행 에이전트는 사용자에게 메시지를 바로 전달하는 "전송" 도구만으로 충분합니다. 정식 아웃박스가 필요한 경우는 에이전트의 메시지 전송 속도를 조절하거나, 오류가 났을 때 에이전트가 복구할 수 있게 하려는 때뿐입니다.
아웃박스는 이벤트 인박스와 대응되는, 발신 메시지 전용 테이블입니다. 워커에 대응하는 디스패처(보통 백그라운드 서비스)도 있습니다. 디스패처는 대기 중인 메시지를 읽어 무엇을 전달할지 정하고, 이를 사용자에게 보냅니다. 도구 호출 보류에서 나온 요청은 아웃박스를 거치게 할 수도 있고, 인터페이스에 바로 표시할 수도 있습니다.
전달 자체 외에, 에이전트가 보내는 메시지 양을 조절하는 일도 중요합니다. 너무 많이 보내면 소음이 되고, 너무 적게 보내면 사용자가 꼭 알아야 할 내용을 놓치게 됩니다. 적절한 균형은 평가(eval)를 만들어 찾기를 권합니다. 실무에서는 에이전트가 조용하게 시작해서 시간이 지날수록 사용자의 관심을 더 얻어 나가는 편이 낫습니다.
다섯 가지 구성 요소는 다음과 같이 맞물립니다.

모든 실행은 인박스에서 꺼낸 이벤트로 시작됩니다. 사용자 메시지든 웹훅이든 타이머든 마찬가지입니다. 워커가 이벤트를 가져가면 실행을 시작하고, 새 세션이나 기존 세션에서 에이전트를 깨웁니다. 에이전트는 메모리를 읽어 기본 상태를 파악하고, 주어진 권한 안에서 작업한 뒤, 새로 알게 된 내용을 메모리에 갱신합니다. 실행이 끝나면 에이전트가 아웃박스에 행을 추가하고, 디스패처가 그 메시지를 사용자에게 전달합니다.
이 요소들은 함께 하나의 순환 구조를 이룹니다. 실행 중에 타이머를 설정해 두면 나중에 에이전트가 다시 깨어나고, 사용자가 메시지에 답장하면 그 답변이 인박스의 이벤트로 돌아옵니다. 각 실행은 짧지만 이 순환이 끝없이 이어지기 때문에, 에이전트가 항상 켜져 있는 것처럼 느껴집니다.
William Hu가 작성했으며, Rodrigo Olivares와 Michael Segner가 도움을 주었습니다.