암호화폐 토큰을 조사하고 숫자를 환각하지 않는 5개 에이전트 군집(Swarm)을 구축했습니다
요약
암호화폐 데이터의 환각 문제를 해결하기 위해 5개의 특화된 에이전트로 구성된 Swarm 아키텍처 'Legate'를 소개합니다. 각 에이전트는 단일 작업과 좁은 데이터 영역에 집중하며, 실시간 소스 모듈을 통해 데이터의 신선도와 정확성을 보장합니다.
핵심 포인트
- 단일 프롬프트 대신 5개의 역할(Commander, Scout, Analyst, Sentinel, Synthesizer)로 작업을 분리
- 에이전트가 직접 API를 호출하는 대신 별도의 dossier composer 레이어를 통해 데이터를 수집
- 데이터 소스는 예외를 발생시키지 않고 null을 반환하여 시스템 안정성 유지
- 모든 데이터 값에 소스, 샘플링 시간 등 신선도(freshness) 메타데이터를 포함
제가 시도해 본 모든 "AI 암호화폐 어시스턴트"는 동일한 실패 패턴을 보였습니다. 토큰에 대해 물어보면 아주 깔끔하고 자신감 있게 가격을 알려주지만, 그 가격은 그냥... 틀렸습니다. 혹은 8개월 전 학습 데이터에서 가져온 시가 총액을 알려주기도 합니다. 실제로 돈을 투자할 만한 대상에 대해서라면, 자신감 있는 추측은 답변이 없는 것보다 더 나쁩니다.
그래서 저는 Legate를 구축했습니다. 모든 숫자가 실시간 소스로 추적되며, 무언가를 찾을 수 없다면 지어내는 대신 못 찾는다고 말하는 연구 도구입니다. 이것은 아키텍처(Architecture)이며, 저에게 가장 많은 것을 가르쳐준 세 가지 버그에 대한 내용입니다.
하나의 프롬프트는 잘못된 형태입니다
가장 단순한 버전은 하나의 커다란 프롬프트입니다: "여기 토큰이 있으니, 모든 것을 말해줘." 이것은 작동하지 않습니다. 모델은 가격 데이터, 온체인(On-chain) 안전성, 소셜 센티먼트(Social sentiment)를 단 한 번의 패스(Pass)로 다뤄야 하며, 이 과정에서 정보들이 서로 뒤섞여 버립니다. 더 나쁜 것은, 모델이 실제 데이터가 없기 때문에 그 공백을 허구로 채운다는 점입니다.
Legate는 작업을 순차적으로 실행되는 다섯 가지 역할로 나눕니다:
Commander → Scout → Analyst → Sentinel → Synthesizer
- Commander는 주제를 조사 전용의 세 가지 쿼리(Query)로 분해하고 이를 분류합니다 (토큰 / 체인 / 프로토콜 / 내러티브). 또한 컨트랙트 주소, 티커(Ticker), 핸들(Handle)과 같은 힌트들을 추출합니다.
- Scout는 뉴스 및 내러티브(Narrative)를 담당합니다.
- Analyst는 순수하게 정량적(Quantitative)인 역할을 수행합니다: 가격, 유동성(Liquidity), TVL, 공급량, 홀더 집중도. 웹 검색은 허용되지 않습니다. 구조화된 데이터(Structured data)만 사용합니다.
- Sentinel은 소셜 맥락(Social pulse)을 담당합니다: Twitter, Reddit, 거버넌스(Governance).
- Synthesizer는 세 가지 조사 결과를 하나의 브리핑으로 병합하며, 각 섹션은 주제 유형에 따라 적응합니다.
각 역할은 서로 다른 시스템 프롬프트(System prompt)를 가진 동일한 모델입니다. 성공의 핵심은 모델이 아닙니다. 각 에이전트가 단 하나의 작업과 하나의 좁은 데이터 영역만을 갖는다는 점에 있습니다.
에이전트들은 API를 호출하지 않습니다
숫자의 정직함을 실제로 유지해 주는 부분은 에이전트들이 보지 못하는 레이어(Layer)입니다. 각 조사는 Promise.allSettled와 소스별 타임아웃(Timeout)을 사용하여 약 14개의 소스 모듈(CoinGecko, DexScreener, DefiLlama, Helius, Etherscan 및 기타)로 확장되는 dossier composer를 가집니다:
// 모든 소스는 WithFreshness<T> | null을 반환합니다 — 절대 예외(throw)를 발생시키지 않습니다.
async function getPrice(id: string): Promise<WithFreshness<Price> | null>
이 구조를 유지하는 두 가지 규칙이 있습니다:
- 소스는 절대 예외를 발생시키지 않습니다 (Sources never throw). 속도 제한 (rate limit), 4xx 에러, 연결 끊김 등이 발생하더라도 소스는
null을 반환하고 조용히 건너뜁니다. 하나의 느린 API가 전체 실행을 지연시킬 수 없습니다. - 모든 값은 신선도 (freshness) 정보를 포함합니다. 각 값은
{ source, sampledAt, endpoint, cached }와 함께 전달되며, 이 메타데이터는 브리핑의 끝까지 유지됩니다. 그곳에서 Synthesizer는 **데이터 신선도 표 (Data Freshness table)**를 추가합니다. 독자는 해당 가격이 CoinGecko로부터 3초 전 실시간으로 가져온 것임을 확인할 수 있습니다.
가장 중요한 세부 사항은 다음과 같습니다: 소스가 null을 반환하면, dossier는 LLM이 읽는 마크다운(markdown)에 직접 _Sources unavailable: x, y_를 렌더링합니다. 따라서 모델은 데이터의 공백을 인지하게 되며, 이를 억지로 메우는 대신 "보유자 집중도(holder concentration) 정보를 확인할 수 없습니다"라고 작성합니다. 부재(absence)를 드러내는 것이 환각 (hallucinations)을 제거하는 핵심입니다.
가장 많은 것을 가르쳐준 세 가지 버그
1. 주소로부터 체인을 유도하세요, 모델을 절대 믿지 마세요.
하나의 Solana 토큰이 계속해서 Base 체인에 있는 것처럼 분석되었습니다. 근본 원인은 체인 정보가 순전히 LLM의 추측에 의존했고, 그 추측이 틀렸기 때문입니다. 하지만 base58 민트 (mint) 주소는 오직 Solana일 수밖에 없으며, 0x… 주소는 EVM일 수밖에 없습니다. 이제 체인은 주소 형식으로부터 유도되며, 모델의 추측은 무시됩니다. 교훈: 입력값으로부터 결정론적 (deterministic)으로 알 수 있는 사실이라면, 모델이 투표하게 두지 마세요.
2. 추론 모델 (reasoning model)은 최근 날짜를 "미래"로 취급합니다.
모델이 4개월 전의 역대 최고가 (all-time-high)를 "미래 데이터 / API 오류 가능성"으로 계속 표시하며 그와 관련된 위험을 지어내는 문제가 있었습니다. 해결책: 모든 조사 (probe)의 컨텍스트 (context)에 현재 날짜를 주입합니다. 지나고 나면 당연해 보이지만, 사고 과정 (chain-of-thought)을 읽기 전까지는 보이지 않는 문제입니다.
3. 신뢰할 수 없는 데이터에는 울타리(fence)가 필요합니다.
도시에(dossiers)에는 모델에 입력되는 트윗, 뉴스 스니펫(snippets)과 같은 제3자 텍스트가 포함되어 있습니다. 오염된 스니펫은 프롬프트(prompt)를 하이재킹(hijack)하려고 시도할 수 있습니다. 이제 모든 도시는 중첩된 울타리 토큰(fence tokens)이 무력화된 <UNTRUSTED_DATA> 울타리로 감싸져 있으며, 각 프로브(probe)의 프롬프트에는 가드레일(guardrail) 조항이 포함되어 있습니다. 읽기 전용 연구 도구의 최악의 상황은 코드 실행이 아니라 잘못된 브리핑(briefing)을 받는 것이지만, 울타리를 치는 것은 저렴한 보험과 같습니다.
비용을 절감해 준 또 다른 방법은 커맨더(Commander)가 먼저 스코프 게이트(scope gate)를 실행한다는 점입니다. 만약 시를 써달라거나 시스템 프롬프트(system prompt)를 유출하라는 요청을 하면, 나머지 4개의 에이전트가 실행되기도 전에 거절합니다. 따라서 주제에서 벗어난 요청은 5번이 아닌 단 1번의 LLM 호출 비용만 발생합니다.
결과물
Solana 컨트랙트(contract) 주소를 붙여넣으면 하나의 브리핑을 얻게 됩니다: 가격 및 유동성, 온체인(on-chain) 안전성(민트/동결 권한(mint/freeze authority)이 포기되었는가?, 상위 홀더 집중도), pump.fun 기원 플래그, 소셜 펄스(social pulse) — 모든 줄에는 인용이 포함되며, 하단에는 최신성 테이블(freshness table)이 제공됩니다. 만약 애그리게이터(aggregators)가 아직 새로운 민트(mint)를 인덱싱(index)하지 않았더라도, 온체인 및 DEX 데이터는 체인에서 직접 바로 해결됩니다.
직접 테스트해 보고 싶다면 베타 기간 동안 라이브로 무료로 이용할 수 있습니다: legatelabs.xyz. 또한 동일한 엔진을 본인의 텔레그램(Telegram) 봇에 연결할 수도 있습니다.
과거의 나에게 해주고 싶은 말
모델 자체는 결코 어려운 부분이 아니었습니다. 어려운 부분은 모델 주변의 배관(plumbing) 작업이었습니다. 소스가 조용히 실패하게 만들고, 프롬프트에서 데이터의 부재를 가시화하며, 입력값이 이미 결정한 사항을 LLM이 결정하도록 내버려 두지 않는 작업 말입니다. 만약 LLM을 통해 사실을 보고하는 무언가를 구축하고 있다면, 바로 그곳에 당신의 시간이 투입될 것입니다.
LLM 출력을 실제 데이터에 근거하게 만드는(grounding) 당신의 접근 방식은 무엇인가요 — 검색(retrieval), 도구 호출(tool calls), 아니면 다른 무엇인가요? 여러분에게 무엇이 효과적이었는지 궁금합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기