Show HN: Jido Assembly; Pure Elixir로 구현한 Slack 클론과 통합 에이전트
요약
Jido Assembly는 Elixir와 BEAM의 강력함을 활용하여 Slack 클론 형태의 에이전트 네이티브 채팅 애플리케이션 쇼케이스입니다. 이 시스템은 Agents가 단순한 챗봇을 넘어, 채널과 스레드에서 사람들과 동일하게 상호작용하는 아키텍처를 보여줍니다. 이는 복잡한 동시성, 영속적인 상태 관리, 실시간 업데이트 처리를 위한 개발자 사례 연구입니다.
핵심 포인트
- 에이전트가 애플리케이션의 참가자로 기능하는 에이전트 네이티브 아키텍처 제시
- Elixir와 BEAM을 활용하여 복잡한 채팅 시스템 구현 가능성 입증
- 동시 참가자, 영속적 상태, 실시간 라우팅 등 엔터프라이즈급 기능을 시연
Jido Assembly는 Jido 생태계가 무엇을 만들 수 있는지 보여주는 쇼케이스입니다. 이는 다중 사용자 채팅 애플리케이션, 즉 Slack 클론으로, Jido, AI Agents, Hologram, 그리고 BEAM의 강력함을 보여주기 위해 제작되었습니다.
저희는 이를 에이전트 네이티브(agent-native) 애플리케이션을 위한 아키텍처 사례 연구로 구축했습니다. 사람들은 채널, 다이렉트 메시지, 스레드에서 채팅합니다. Jido Agents가 이 방들에 참가자로서 참여합니다. Jido Messaging은 채팅 모델을 영속화하고, Jido Chat은 메인 운영(ops) 방을 Telegram 및 Discord에 연결합니다. Hologram은 인터랙티브한 Elixir 사용자 인터페이스를 제공합니다.
Assembly에서 에이전트 네이티브하다는 것은 Agents가 사람들과 동일한 방, 메시지, 스레드, 이벤트를 사용한다는 것을 의미합니다. 그들은 별도의 챗봇 기능이 아니라 애플리케이션의 참가자입니다. Jido Agent는 상태와 동작을 가지며 Jido 런타임(runtime)을 통해 실행되는 모듈입니다.

Assembly가 포함하는 것
Assembly는 팀 채팅 애플리케이션에서 기대할 수 있는 기능들, 즉 채널, 다이렉트 메시지, 스레드, 반응(reactions), 멘션(mentions), 검색, 존재 여부(presence), 그리고 모바일 방 전환 기능을 포함합니다.
이러한 범위는 시스템의 모든 부분에 실제 작업할 거리를 제공합니다. 이 애플리케이션은 동시 참가자, 영속적인 상태(durable state), 방 수준 라우팅, 실시간 업데이트, Agent 실행, 그리고 외부 공급자 경계(external provider boundaries)를 처리합니다. 이는 Jido 패키지들이 작은 Agent 예제 이상으로 어떻게 조합되는지를 보여줍니다.
Assembly는 프로덕션 Slack 대체품이 아니라 개발자 쇼케이스입니다. 인증(authentication), 권한 부여(authorization), 파일 업로드, 엔터프라이즈 관리, 또는 Slack API 호환성은 포함하고 있지 않습니다.
시드된 #ops-workflow 방은 Jido 부분을 추가합니다. 여기에는 세 개의 Agents와 샘플 공급자 트래픽, 그리고 워크플로우 데이터가 포함되어 있습니다. 개발자 인스펙터는 인터페이스 뒤에 있는 Signals 및 메시지 메타데이터를 표시합니다.
기본 작업 공간(workspace)은 LLM 키나 공급자 자격 증명 없이 실행됩니다. 시드된 데이터는 검사를 위해 인터페이스를 사용할 수 있도록 유지합니다. Anthropic 키를 추가하여 라이브 Agent 라운드를 실행할 수 있습니다. Telegram 또는 Discord 자격 증명을 추가하여 라이브 서비스를 연결할 수 있습니다.
Assembly에서 메시지를 따라가기
로컬 메시지는 세 가지 필수 단계를 거칩니다. 프로바이더 브릿지(provider bridge)가 구성된 경우 네 번째 단계에 진입할 수 있습니다.
1. 사람이 메시지를 보냅니다
Hologram 액션은 브라우저 이벤트를 받습니다. 이는 초안(draft) 및 대기 중(pending) 상태와 같은 로컬 컴포넌트 상태를 업데이트한 다음, Hologram Command를 서버로 전송합니다.
이는 Jido.Assembly.Pages.Assembly.action/3에서 간소화된 클라이언트 측의 전송 경로입니다.
component
|> put_state(:draft, "")
|> put_state(:send_pending, true)
...
이 Command는 Assembly 채팅 컨텍스트(chat context)를 호출합니다. 해당 컨텍스트는 Jido Messaging과 그 SQLite 어댑터(adapter)를 통해 메시지를 작성합니다. Jido Messaging은 애플리케이션의 표준 방(room), 참가자(participant), 메시지, 스레드(thread), 반응(reaction) 기록을 제공합니다.
서버 측에서는 메시지를 영속화하고, 현재 브라우저에 액션을 반환하며, 동일한 액션을 워크스페이스 전체에 방송합니다. 이 예시는 Jido.Assembly.Pages.Assembly.Commands.command/3와 그 방송 헬퍼(broadcast helper)에서 간소화되었습니다:
case Chat.send_message_command(
params.room_id,
params.body,
...
2. Jido 에이전트가 방에서 응답합니다
Jido는 Agent 런타임(runtime)을 제공합니다. Jido AI는 ReqLLM을 통해 LLM 기반의 Agent Strategy와 모델 접근성을 추가합니다. 에이전트 실행은 온디맨드(on demand) 방식입니다. 사람이 ops Agent 패널에 프롬프트를 입력하고 라운드를 시작하기 위해 Ask를 선택합니다.
Assembly는 #ops-workflow에서 세 개의 에이전트를 정의합니다:
- Triage Agent: 영향도(impact)와 심각도(severity)에 중점을 둡니다.
- Bridge Agent: 프로바이더 및 전달 상태(delivery state)를 설명합니다.
- Runbook Agent: 점검 사항, 승인, 인계(handoff)를 제안합니다.
각 에이전트는 표준 Jido AI Agent 모듈입니다:
use Jido.AI.Agent,
name: "assembly_triage_agent",
model: :assembly_haiku,
...
Assembly는 각 Agent 턴(turn)을 위해 단기 실행 환경(runtime)을 시작합니다. Agent는 최근의 방 컨텍스트(room context)를 받고 제한된 응답(bounded response)을 반환합니다. 이 데모에서는 한 라운드에 최대 세 개의 Agent가 실행될 수 있고, 프롬프트는 두 라운드 동안 계속될 수 있으며, 각 답변은 420자로 제한됩니다. Agent 간 채팅이 활성화되면, 나중의 Agent는 자신보다 먼저 실행된 Agent들의 응답을 읽을 수 있습니다.
Agent 응답은 별도의 AI 지속성 경로(AI persistence path)를 사용하지 않습니다. Assembly는 이를 인간 메시지와 동일한 채팅 명령을 통해 전송합니다. 따라서 같은 메시지, Signal, 스레드, 반응(reaction), 검색 동작(search behavior)을 받습니다.
3. 커밋된 이벤트는 각 클라이언트를 업데이트합니다
Jido Messaging은 영구적인 변경 사항(durable change)을 커밋한 후에 Signal을 반환합니다. Signal은 jido.messaging.room.message_added와 같은 유형을 가진 구조화된 이벤트입니다.
Jido Signal은 이러한 이벤트를 위한 CloudEvents 호환 래퍼(envelope)와 라우팅을 제공합니다.
동일한 커밋 및 브로드캐스트 패턴이 메시지, 반응, 방 생성에도 적용됩니다. 존재 여부(Presence)는 다릅니다. Phoenix Presence는 임시 세션 상태를 추적하며, Assembly는 정규화된 존재 신호(normalized presence Signals)를 연결된 클라이언트들에게 브로드캐스트합니다.
4. 설정 시 Telegram 및 Discord가 방에 참여합니다
Jido Chat은 프로바이더 중립적인 대상(provider-neutral targets)과 페이로드(payloads)를 정의합니다. Telegram 및 Discord 어댑터는 각 서비스에 대해 해당 계약(contracts)을 구현합니다.
Assembly는 이러한 프로바이더들을 표준화된 #ops-workflow 방에 바인딩합니다. 들어오는 Telegram 또는 Discord 메시지는 일반적인 방 메시지가 될 수 있습니다. Assembly 컴포저에서 전송되는 최상위 레벨 메시지는 구성된 모든 어댑터를 통해 라우팅될 수 있습니다.
프로바이더는 변경되지만, 대화 모델은 변하지 않습니다. 사람, Agent, Telegram 참여자, Discord 참여자가 같은 방에 참여할 수 있습니다.
경계가 명확합니다. 들어오는 프로바이더 메시지가 자동으로 Agent 라운드를 시작하지는 않습니다. Agent 답변은 표준 방에 저장되지만, Assembly는 기본적으로 이를 프로바이더들에게 전파(fan out)하지 않습니다.
왜 Hologram을 선택했는지
Assembly의 사용자 인터페이스 레이어로는 Hologram을 선택했습니다. 이를 통해 프로젝트가 브라우저 동작과 서버 작업을 모두 Elixir로 사용할 수 있게 되었습니다.
LiveView는 주된 뷰 상태를 서버 측 소켓 할당(socket assigns)에 유지합니다. 브라우저 이벤트는 보통 LiveView 프로세스에 도달합니다. 이 프로세스가 자신의 상태를 업데이트하고 렌더링된 차이점(diffs)을 브라우저로 전송합니다. 클라이언트 전용 동작은 JavaScript 명령어 또는 후크를 사용할 수 있습니다. 이러한 모델은 서버 지향적인 Phoenix 애플리케이션에 잘 작동합니다. LiveView 문서는 이 프로세스와 이벤트 모델을 설명하고 있습니다.
Hologram은 컴포넌트 상태를 브라우저에 유지하며 필요한 Elixir 코드를 JavaScript로 컴파일합니다. 액션(Actions)은 클라이언트에서 실행됩니다. 명령어(Commands)는 인터페이스가 데이터베이스, API 또는 기타 보호된 리소스를 필요로 할 때 서버에서 실행됩니다. Hologram은 Action-to-Command 요청에는 HTTP/2를 사용하고 브로드캐스트 액션에는 Server-Sent Events (SSE)를 사용합니다. 아키텍처 가이드가 이러한 분할을 문서화하고 있습니다.
| 관심사 | LiveView | Hologram |
|---|---|---|
| 주 상태 | 서버 소켓 할당 | 브라우저 컴포넌트 상태 |
| ... | ||
| Assembly는 많은 로컬 인터페이스 이벤트를 가집니다. 사람들은 방을 전환하고, 스레드를 열고, 초안을 편집하고, 데모 참가자를 선택하며, 패널을 조작합니다. Hologram은 이러한 액션들을 Elixir 코드를 사용하여 브라우저에서 실행합니다. 영속적인 쓰기(Durable writes), Agent 호출, 검색 및 브릿지 작업은 서버 명령어(Commands)로 남아 있습니다. |
LiveView도 이 애플리케이션을 지원할 수 있습니다. 하지만 우리는 Hologram을 선택했는데, 그 이유는 클라이언트 액션, 서버 명령어, 그리고 브로드캐스트 모델이 Assembly의 로컬 이벤트와 영속적인 이벤트에 직접 매핑되기 때문입니다. 또한 인터페이스 로직을 Elixir로 유지한다는 점도 장점입니다.
물론 트레이드오프(tradeoff)가 있습니다. Hologram은 아직 전체 인-프로세스 상호작용 테스트를 위한 LiveViewTest 스타일의 API를 제공하지 않습니다. Assembly는 단위 테스트에서 액션과 명령어를 테스트하고, 브라우저 테스트는 JavaScript 동작, SSE 전송 및 크로스 탭 업데이트에 할당합니다.
워크스루 뒤에 숨겨진 패키지들
각 패키지는 애플리케이션 내에서 하나의 명확한 역할을 가지고 있습니다.
| 패키지 | Assembly에서의 책임 |
|---|---|
| Jido 및 Jido AI | Triage, Bridge, 그리고 Runbook Agent 실행. |
| ... | |
| 책임 영역은 분리되어 유지됩니다. Jido AI는 에이전트 응답을 생성하지만, 메시지 공간(room)과 메시지 기록은 Jido Messaging이 소유합니다. Jido Chat은 제공업체들을 연결하지만, 두 번째 메시지 모델을 생성하지는 않습니다. Jido Signal은 커밋된 이벤트들을 전달합니다. Hologram은 이 이벤트들을 인터페이스에 적용합니다. |
Elixir/OTP와 BEAM이 중요한 이유
Assembly는 많은 독립적인 활동들을 동시에 실행합니다. 사람들이 메시지를 보내고, Jido는 각 에이전트 턴마다 별도의 단기 런타임을 시작합니다. 제공업체 어댑터들은 외부 이벤트를 수신하고, Phoenix는 접속 상태를 추적하며 업데이트를 배포합니다. Hologram은 활성 클라이언트 연결을 유지합니다.
BEAM은 동시 작업(concurrent work)을 위해 구축되었습니다. 그 가벼운 프로세스들이 각 활동들을 격리합니다. 이들은 공유 가능한 변경 가능한 상태(shared mutable state) 대신 메시지를 통해 통신합니다. 느린 에이전트 응답이나 제공업체 요청이 다른 채팅 활동을 멈추게 하지 않으면서 자체 프로세스를 차지할 수 있습니다.
OTP 감독(supervision)은 장기 실행 서비스에 명확한 실패 경계(failure boundaries)를 제공합니다. 실패한 감독된 프로세스는 애플리케이션 전체를 재시작하지 않고도 다시 시작될 수 있습니다. Phoenix PubSub과 Presence는 같은 런타임 모델을 사용하여 공간 업데이트를 배포하고 연결된 참가자들을 추적합니다.
Elixir는 패턴 매칭(pattern matching), 불변 데이터(immutable data), 그리고 명시적인 데이터 변환 기능을 추가합니다. 이러한 기능들은 패키지들 사이에서 이동하는 기록(records)과 이벤트들에 잘 맞습니다. 그 결과, 에이전트 실행, 메시지 영속성(message persistence), 접속 상태, 제공업체 트래픽, 실시간 인터페이스 업데이트를 위한 단일 런타임 모델을 갖게 됩니다.
구축 시작하기
Assembly는 레퍼런스 애플리케이션으로 읽기에 충분히 작습니다. 클라이언트 액션(client Actions)은 app/pages/assembly_page.ex에서 시작하세요. 서버 커맨드(server Commands)는 app/pages/assembly/commands.ex에서, 메시징은 lib/jido_assembly/chat.ex에서, 에이전트 라운드는 lib/jido_assembly/agents.ex에서, 제공업체 라우팅은 lib/jido_assembly/bridges.ex에서 계속 진행하세요.
프로젝트를 시작한 후, #ops-workflow를 여세요.
메시지를 보냅니다. 에이전트 라운드를 실행합니다. 반응을 추가합니다. 개발자 인스펙터를 열고 결과로 나오는 시그널(Signals)을 따라갑니다.
- 설정 단계, 프로바이더 구성, 테스트 노트 및 프로젝트 제한을 위해 Jido Assembly를 실행하세요.
- Jido를 사용하여 첫 번째 에이전트를 구축하는 것을 시작해 보세요.
- Assembly가 사용하는 패키지를 확인하기 위해 Jido 생태계를 탐색해 보세요.
Jido Assembly는 하나의 장소에서 완전한 구성을 보여줍니다: Elixir 인터페이스, 내구성 메시징(durable messaging), 온디맨드 에이전트(on-demand Agents), 구조화된 이벤트(structured events), 그리고 BEAM 위에서 함께 실행되는 선택적 프로바이더 브릿지(optional provider bridges)입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 HN Show HN (AI)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기