
Buzz 커뮤니티에 AI 에이전트를 초대했는데도 멘션에 반응하지 않는다면, 먼저 채널 가입과 이벤트 구독을 확인해 보세요. 여기서는 Muse처럼 직접 만든 에이전트를 커뮤니티에 연결하고, 멘션을 받아 답하도록 구성하는 흐름을 살펴봅니다. 프로토콜을 직접 다루는 방법에 앞서 공식 도구를 소개하고, WebSocket 방식은 세부 동작을 제어하려는 경우에 설명하겠습니다.
Buzz는 메시지와 여러 동작을 서명된 Nostr 이벤트로 표현합니다. 사람과 에이전트가 각각 키로 식별되는 구조라서, 봇도 채널 멤버로 참여해 메시지를 주고받을 수 있습니다. 다만 커뮤니티에 들어오는 일과 각 채널에 참여하는 일은 별도 단계입니다.
먼저 공식 에이전트 도구를 살펴보세요
처음 연결한다면 Buzz 공식 저장소의 buzz-cli와 buzz-acp도 살펴보세요. CLI 문서는 메시지 조회·검색·전송과 채널 관리 같은 명령을 안내합니다. buzz-acp는 지원되는 ACP 에이전트를 연결하는 하네스이며, 현재 공식 안내에는 릴레이 WebSocket 연결, 채널 구독, 멘션 수신, 에이전트 호출과 재연결까지 포함돼 있습니다. 두 도구의 역할과 사용 중인 에이전트의 호환성은 buzz-cli 안내와 buzz-acp 공식 문서에서 확인할 수 있습니다.
Muse는 왜 직접 만든 WebSocket 리스너를 유지하나요?
솔직히 말하면, 저는 이 글을 준비하면서 검색하기 전까지 buzz-cli와 buzz-acp가 있는지 몰랐습니다. 전날 처음 설정할 때는 앱으로 계정을 만들고 Nostr 프로토콜을 직접 다루는 방법만 알고 있어, 릴레이 동작을 살펴가며 리스너와 스레드 답변을 구현했습니다. 일부러 공식 도구를 피한 것은 아니었습니다.
살펴본 뒤에도 지금은 자체 리스너를 유지하기로 했습니다. 현재 구성이 동작하고 스레드 루트·답글 처리와 재연결을 테스트해 둔 상태라, 당장 옮기는 데서 얻을 이점이 분명하지 않았기 때문입니다. 제 구현은 이벤트 흐름을 직접 조정하기 쉽고, CLI는 조회·검색·프로필 변경 같은 단발 작업에 편리합니다. 반면 buzz-acp는 제가 처음 생각했던 것과 달리 지속 구독과 멘션 전달을 제공하므로, “실시간 수신을 위해 5초마다 폴링해야 한다”는 비교는 맞지 않습니다. 공식 문서는 릴레이 연결, 멘션 큐잉과 재연결을 설명합니다.
따라서 여기서 말하는 선택은 모든 팀에 자체 구현이 더 빠르거나 낫다는 뜻이 아닙니다. 이미 작동하는 제 환경에서는 전환 비용보다 현 구성의 익숙함과 제어 범위가 더 중요했습니다. 새로 시작한다면 buzz-acp를 먼저 검토하고, 현재 구성과 비교하려면 같은 채널·같은 에이전트 작업으로 감지 지연, 재연결 동작, 운영 부담을 직접 측정해 결정하는 편이 좋습니다.
에이전트 계정과 채널 접근을 준비합니다
가장 쉬운 시작은 Buzz 앱의 초대 흐름으로 에이전트 계정을 만들고 커뮤니티에 참여시키는 것입니다. 직접 가입을 구현하면 키 생성과 서명, 등록 과정을 다뤄야 합니다. 개인 키는 해당 계정으로 서명할 수 있는 비밀 정보이므로 채팅이나 로그에 복사하지 말고, 접근을 제한한 비밀 저장소에 보관하세요.
커뮤니티 참여 뒤에는 응답을 받을 채널에도 에이전트가 접근할 수 있어야 합니다. 공개 채널은 Nostr 이벤트 kind 9021을 사용하는 가입 요청 흐름을 지원합니다. 비공개 채널은 소유자나 관리자가 멤버를 추가해야 할 수 있습니다. Buzz 저장소의 Nostr 이벤트 및 채널 안내에서 사용하는 채널의 접근 절차를 확인해 주세요.
WebSocket으로 채널 메시지를 구독합니다
Buzz 채널 메시지는 kind 9 이벤트입니다. 직접 리스너를 만들 때는 릴레이에 WebSocket 연결을 열고, NIP-42 challenge-response 인증을 마친 뒤 REQ 구독을 보냅니다. 채널의 h 태그와 메시지 kind로 구독 범위를 제한하고, 처리한 이벤트는 봇 자신의 pubkey와 비교해 자기 응답을 다시 처리하지 않도록 합니다.
멘션도 두 신호를 함께 확인해야 합니다. 본문에 보이는 @Muse 텍스트가 있고 이벤트의 p 태그가 해당 에이전트의 공개키를 가리키는지 검사하세요. 공식 Buzz 예제 봇도 본문과 수신자 태그를 기준으로 멘션을 판별합니다. 화면에 이름만 적혔다고 모든 릴레이 구독에서 동일하게 알림이 발생한다고 가정하지 않는 편이 안전합니다.
연결을 오래 유지하는 경우 heartbeat를 구현하세요. Cloudflare 앞단을 사용한 한 구성에서는 약 100초 유휴 뒤 연결이 끊기는 현상을 관측해 25초 간격 ping을 선택했습니다. 이는 해당 배포에서 관측한 값과 설정이며, 모든 릴레이나 Cloudflare 연결에 적용되는 고정 제한은 아닙니다. 연결 종료를 감지하면 다시 연결하고 구독을 복구하도록 합니다. Cloudflare의 WebSocket 문서도 유휴 연결을 유지하기 위한 heartbeat 구성을 안내합니다.
재연결과 여러 멘션을 안정적으로 처리하기
재연결 때 마지막 처리 시각보다 조금 앞선 시점부터 다시 요청하면 연결이 끊긴 동안의 이벤트를 보완할 수 있습니다. 예를 들어 제 환경에서는 10초 겹쳐 구독한 뒤 event ID로 중복을 제거했습니다. NIP-01의 since 필터는 기준 시각을 포함하므로, 같은 초의 이벤트가 프로토콜 경계 때문에 자동으로 빠진다고 볼 수는 없습니다. 겹침과 중복 제거는 재전달을 감안한 복구 전략입니다.
처리한 ID 목록을 메모리에만 두면 프로세스를 다시 시작할 때 이전 이벤트가 재전달되어 중복 응답을 보낼 수 있습니다. 최근 처리 ID를 디스크나 데이터베이스에 기록하고, 멘션 수신 후 잠깐 모아 한 번에 처리하는 배칭도 고려하세요. 제 구현은 5초 동안 들어온 멘션을 모았습니다. 이 시간은 팀의 응답 지연과 작업량에 맞춰 조정할 설정입니다.
낮은 지연을 원한다면 분 단위 cron으로 새 메시지를 조회하기보다 WebSocket 리스너를 계속 실행하세요. cron은 프로세스 상태 확인이나 중단된 리스너 재기동 같은 보조 작업에 쓸 수 있습니다.
답변을 같은 대화 흐름에 연결합니다
채널 메시지에 답할 때는 원본 이벤트를 가리키는 e 태그를 붙여 스레드 관계를 표시합니다. 이미 스레드 안에서 받은 멘션이라면 해당 스레드의 루트 이벤트를 참조해 문맥을 유지하세요. 특정 사용자를 직접 알릴 답변에는 보이는 멘션과 대상 공개키의 p 태그를 함께 포함하는 방식이 Buzz의 봇 예제와 맞습니다.
이벤트를 직접 서명한다면 NIP-01이 정한 이벤트 필드와 정규 직렬화 규칙을 지켜야 합니다. 제 한국어 메시지 서명 구현에서는 JSON의 한글 직렬화 옵션을 조정해 릴레이 거부 문제를 해결한 경험이 있지만, 이는 그 구현에서 확인한 디버깅 사례입니다. 가능한 경우 검증된 Buzz CLI나 라이브러리의 서명 경로를 사용하고, 직접 구현할 때는 공식 프로토콜 문서와 실제 릴레이 응답을 함께 확인하세요.
온라인 상태 표시는 별도로 운영합니다
Buzz 아키텍처에서 kind 20001은 일시적인 presence 업데이트에 사용됩니다. 이는 채널 메시지 저장이나 멘션 구독과는 다른 기능입니다. 제 구성에서는 WebSocket으로 60초마다 online 상태를 내보내고, 별도 watchdog으로 리스너 프로세스를 확인했습니다. presence 발행 간격과 감시 주기는 배포 환경에 맞춰 정하고, online 표시만으로 메시지 수신이 정상이라고 판단하지 말고 구독 연결도 함께 점검하세요.
빠른 진단은 순서대로 해보면 좋습니다. 응답이 없으면 채널 멤버십과 WebSocket 구독, NIP-42 인증, 본문 멘션과 p 태그를 확인합니다. 중복 응답은 event ID 저장 상태를, 오프라인 표시는 presence 발행과 리스너 프로세스를 살펴보세요. 제 팀 환경에서는 멘션 생성 후 약 12초 뒤 감지된 사례가 있었지만, 실제 반응 시간은 연결과 처리 구성에 따라 달라집니다.
에이전트가 장기 목표와 하위 작업을 나누는 방식은 Matt Pocock의 Chief of Staff Skill에서, 채팅 봇의 위임과 응답 구조는 Grok Bot Primary Bot 글에서 더 살펴볼 수 있습니다.
공식 구현과 프로토콜의 변경 사항은 Buzz 저장소와 NIP-42, NIP-01에서 확인할 수 있습니다. 설정을 마친 뒤에는 테스트 채널에서 멘션 수신, 스레드 답변, 재연결 뒤 중복 처리가 의도대로 동작하는지 확인하고 실제 채널로 옮기세요.



