AgenticOS 1.2.1: API 워커와 챗봇 수신 연결을 따로 세는 법

AgenticOS에서 API 워커를 늘릴 때는 HTTP 요청을 받는 프로세스 수와 챗봇의 상시 수신 연결 수를 따로 세어야 합니다. 1.2.1은 공유 Redis의 봇별 임대권으로 수신 연결의 담당자를 고릅니다. 정상적으로 공유 Redis의 임대권을 사용하는 동안 워커를 두 개로 늘려도 같은 봇의 상시 수신 연결이 두 개로 늘어나는 것은 아닙니다. 메시지 재전송을 걸러내는 장치도 별도로 봐야 합니다.

이 글은 2026년 10월 17일 UTC 기준 AgenticOS 1.2.1 릴리스와 해당 태그의 소스를 검토한 운영 해설입니다. 실제 서버, Redis, Telegram 또는 모델 API를 실행하지 않았습니다. 아래 시간표는 동작을 설명하기 위한 가상 예시이며, 측정값이나 복구 시간 보장이 아닙니다.

공유 Redis의 연결 임대권으로 워커 A만 봇 수신 연결을 유지하고 워커 B는 대기하며, 별도 메시지 중복 억제 단계가 같은 메시지의 재전송을 거르는 설명도
AI가 생성한 설명용 이미지입니다. 공유 Redis가 정상인 같은 등록 봇의 예시입니다. 아래 중복 억제는 같은 봇·플랫폼·채팅·메시지 ID의 재전송 때 첫 처리의 중복 억제 키가 유지되는 정상 경로를 가정합니다. 실제 화면이나 전달 보장이 아닙니다.

어떤 프로젝트이고, 왜 지금 볼 만할까

Vstorm의 AgenticOS는 Pydantic AI 기반 에이전트를 만들고 사내 문서와 도구, 웹 채팅과 메신저 채널에 연결하는 자체 호스팅 플랫폼입니다. 작은 팀이라면 내부 문서 질의나 지원 문의 초안 같은 반복 업무를 하나의 봇으로 묶는 용도를 생각할 수 있습니다. 이 글은 그중 메신저 수신부의 배포 구조만 다룹니다.

저장소는 2026년 7월 31일 생성됐고, 10월 17일 22:30 UTC 무렵 누적 별 108개와 포크 21개를 확인했습니다. 같은 날 올라온 Show HN 소개도 확인했지만 당시 1점, 댓글 0개였습니다. 최근 기간별 별 증가량은 검증하지 않았습니다. 따라서 급성장이나 널리 검증된 도구라고 소개하기보다, 새로 공개된 배포 문제와 구현을 살펴볼 만한 프로젝트로 봅니다.

1.2.1은 10월 17일 22:27:49 UTC에 공개된 정식 릴리스 항목이며, 소스 기준점은 2f43f2b입니다. 코드는 Apache-2.0, 백엔드는 Python 3.12 이상을 요구합니다. 다만 배포 이미지의 PyMuPDF 등 의존성에는 별도 조건이 있으므로 프로젝트의 의존성 라이선스 안내도 확인해야 합니다. 전체 배포를 Apache-2.0 하나로 판단하면 안 됩니다. 자체 호스팅에도 서버와 운영 비용이 들며, 선택한 외부 모델과 도구의 요금·약관은 별도입니다. 외부 모델을 연결하면 질문과 해당 실행에 포함된 문서·도구 결과가 그 제공자에게 전송될 수 있으므로, 자체 호스팅을 곧 모든 데이터의 로컬 처리로 이해하면 안 됩니다.

워커 두 개가 같은 봇을 시작하는 이유

Uvicorn의 lifespan 설명에 따르면 각 워커는 자신의 시작·종료 수명주기를 실행합니다. AgenticOS도 이 시작 경로에서 활성화된 polling 봇을 읽고 수신 연결을 엽니다. 웹 요청 처리 프로세스를 늘리는 설정이 상시 연결의 개수에도 영향을 주는 이유입니다.

유지관리자가 보고한 문제 #2168는 두 워커에서 같은 Telegram 봇의 polling이 충돌하는 상황이었습니다. 같은 이슈는 Mattermost의 중복 연결이 이벤트를 두 번 받을 가능성도 지적했지만, 이 경로는 추가 확인 대상으로 남겼습니다. 이는 직접 재현한 결과가 아닙니다. 1.2.1의 대응은 각 워커가 무조건 연결을 여는 대신, 공유 Redis에서 해당 봇의 담당자 자리를 먼저 얻도록 하는 것입니다.

한 봇과 두 워커로 읽는 정상 경로

같은 등록 봇을 보는 워커 A와 B가 있고, 둘 다 동일한 Redis를 사용한다고 가정해 봅시다.

  1. A가 봇 등록 행의 ID로 만든 channel:stream:<bot_id> 키를 먼저 얻습니다. 키에는 A의 담당자 식별자가 들어갑니다.
  2. B가 같은 키를 얻지 못하면 그 봇의 수신 연결을 열지 않습니다. B의 API 요청 처리 능력이 사라지는 것은 아닙니다.
  3. A는 임대권을 갱신하며 연결을 유지합니다. 담당자가 바뀌었음을 확인하면 자신의 연결을 닫습니다.

임대권 구현의 기본 만료는 30초, 갱신 루프의 대기는 10초입니다. 봇 두 개와 워커 두 개가 있어도 하나씩 균등 배치되는 것은 아닙니다. 먼저 얻는 워커가 둘 다 맡을 수도 있습니다. 또한 키는 등록 행의 ID를 기준으로 하므로, 같은 외부 봇을 서로 다른 등록 행이나 별도 배포에 중복 등록하는 문제까지 자동으로 해결한다고 보면 안 됩니다.

30초 만료가 30초 복구를 뜻하지는 않는다

다음은 실제 실행 결과가 아닌 가상의 시계입니다. A가 t=0에 임대권을 갱신하고 t=1에 비정상 종료했다고 합시다. B의 확인이 t=5, 15, 25, 35에 이뤄진다면 t=30에 키가 만료돼도 다음 확인인 t=35에야 인계할 수 있습니다. 장애 시점으로부터 34초입니다. 이후 연결을 여는 시간도 따로 필요합니다.

실제 루프는 10초를 쉰 뒤 갱신과 봇 조회를 순서대로 기다립니다. 실행 지연까지 포함한 정확한 10초 주기가 아닙니다. 정상 종료 역시 연결 중지와 남은 작업 정리를 거친 뒤 임대권을 반환하므로, 종료 신호부터 몇 초 안에 교체된다고 단정할 수 없습니다.

설정을 수정한 요청이 B에서 처리되면 B가 임대권을 가져오고 새 설정으로 연결을 엽니다. A는 이후 갱신에서 소유권 변경을 확인하면 연결을 닫습니다. 따라서 전환 중 잠깐의 겹침까지 없애는 엄격한 단일 연결 보장은 아닙니다. 해당 태그의 갱신은 GET 후 EXPIRE 두 호출이며, 원자적 비교·갱신 스크립트라고 설명하면 부정확합니다. 해제할 때 쓰는 비교 후 삭제와 구분해야 합니다.

연결 하나와 답변 한 번은 다른 문제다

한 연결만 유지해도 플랫폼이 같은 메시지를 다시 보낼 수 있습니다. AgenticOS의 별도 메시지 중복 억제 코드는 봇 ID, 플랫폼, 채팅 ID, 메시지 ID를 조합한 키를 Redis의 SET NX로 먼저 차지합니다. 기본 유지 시간은 15분입니다. 이것은 어떤 워커가 연결을 유지할지 정하는 임대권과 목적도 키도 다릅니다.

공유 Redis에 연결할 수 없으면 수신 임대권은 처리를 계속하는 방향으로 동작하고, 메시지 중복 억제도 Redis 오류 때 처리를 허용합니다. 여러 연결이나 반복된 에이전트 실행·모델 비용·답변이 다시 나타날 수 있다는 뜻입니다. 다만 모든 Redis 오류를 같은 것으로 취급해서는 안 됩니다. 임대권 갱신은 연결 불가와 명령 거부를 구분합니다. 이 구현을 ‘정확히 한 번 전달’로 설명하거나 15분을 영구 중복 방지로 이해해서는 안 됩니다.

작은 팀이 내려야 할 배포 결정

API 처리량 때문에 프로세스를 늘리는 결정과, 같은 봇의 수신 담당자를 몇 개 둘지의 결정을 분리하세요. 컨테이너 하나의 워커 수만 보지 말고 복제본 전체의 API 프로세스 수를 함께 세는 것이 출발점입니다. 동일한 봇을 처리하는 워커가 같은 Redis를 사용하는지도 배포 구성으로 확인해야 합니다.

단일 복제본·단일 워커로 시작하면 이 특정한 경쟁 워커 상황은 줄일 수 있지만, 메시지 재전송이나 모델 제공자 재시도까지 없어지는 것은 아닙니다. 여러 워커가 필요하다면 임대권을 부하 균등화 장치로 기대하지 말고, 연결 충돌 로그와 반복 답변, Redis 연결 상태를 함께 관찰해야 합니다.

전환 전에는 현재 이미지 태그와 복제본·워커 수를 기록하고, 사본 환경의 테스트용 봇으로 시작·종료·설정 변경을 확인하는 편이 좋습니다. 문제가 생기면 워커 확장을 되돌릴 수 있도록 이전 배포 구성을 보관하세요. 버전 자체의 되돌리기는 데이터베이스 변경과 호환성을 별도로 확인해야 하며, 이 글은 롤백 실행이나 호환성을 검증하지 않았습니다. 위 절차는 제안하는 점검 방법이지 여기서 수행한 테스트가 아닙니다.

이 프로젝트에서 얻을 만한 실무 관점은 단순합니다. 에이전트가 모델을 호출하는 부분만 보지 말고, 그 앞에서 외부 메시지를 받아오는 프로세스의 수명과 소유권도 설계해야 합니다. API 워커, 봇 연결, 메시지 처리 횟수를 따로 세면 어떤 확장이 필요한지와 무엇을 관찰해야 하는지가 더 분명해집니다.

댓글