TL;DR
Anansi는 조직 내부의 대화·문서·티켓을 받아 구조화된 엔티티 그래프와 합성 프로필을 생성하는 자가 호스팅 메모리 엔진으로, POST /v1/ingest와 GET /v1/context 두 호출로 통합할 수 있다. 각 엣지는 사실의 유효 시점과 시스템이 이를 기록한 시점을 분리해 저장하는 바이템포럴 모델을 사용해 과거 상태와 변경 시점을 근거와 함께 재구성할 수 있다. 검색은 Postgres에서 pgvector와 BM25를 결합한 하이브리드 쿼리로 수행되며, 로컬 Ollama나 nomic-embed-text 같은 경량 임베딩을 이용해 약식으로 5분 내에 실습해볼 수 있다.
섹션별 상세

- Anansi의 기본 사용 흐름은 두 API 호출로 이루어지며 POST /v1/ingest와 GET /v1/context가 핵심 엔드포인트다. — 초반 TL;DR 섹션과 Quickstart 단계, API 표에서 두 엔드포인트의 역할(ingest=202 반환, context=합성된 프로필 반환)을 확인할 수 있다.
- 로컬 빠른 시작은 Docker Compose와 nomic-embed-text(274MB), 또는 호스트의 Ollama를 활용하면 약 5분 내에 동작하는 인스턴스를 만들 수 있다. — Quickstart의 'Start the stack'와 'Give it something to embed' 섹션에 구체적 이미지 크기(274 MB)와 옵션별 소요 시간을 밝히고 있다.
- 엔티티 그래프의 각 엣지는 valid time(사실이 성립한 시점)과 recorded/knowledge time(시스템이 그 사실을 기록한 시점)이라는 두 개의 독립적 시간 축을 가진다. — lib/db/schema.ts와 lib/ai/query-engine.ts 구현 설명 및 'Two clocks' 소제목에서 bi-temporal 구현 세부가 기술되어 있다.
curl -X POST http://localhost:3000/v1/ingest \
-H "Authorization: Bearer $ANANSI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"userId":"user_123","content":"User is building a voice agent. Prefers TypeScript. Team of 4.","sourceType":"conversation"}'로컬에 키를 발급한 뒤 POST /v1/ingest로 사용자의 텍스트를 보낼 때 쓰는 명령이다. 응답은 202를 반환하고 실제 임베딩 작업은 백그라운드 큐에서 처리되기 때문에 호출자 경로에 지연을 남기지 않는다. 즉시 202을 받고 이후 GET /v1/context로 결과를 조회하면 관련 벡터·청크·프로필을 얻을 수 있다.
curl -G http://localhost:3000/v1/context \
-H "Authorization: Bearer $ANANSI_API_KEY" \
--data-urlencode "userId=user_123" \
--data-urlencode "q=what is the user building?"GET /v1/context는 이미 합성된 프로필(static/dynamic)과 관련 청크를 반환하는 주된 읽기 경로이다. 임베딩이 아직 반영되지 않은 경우에도 키워드 검색을 섞어 하이브리드 방식으로 어느 정도 결과를 제공해 빈 응답을 피한다. 질의별로 반환된 similarity 점수를 통해 의미적 유사도와 검색 상태를 확인할 수 있다.
import AnansiMemory from "anansi-memory";
const memory = new AnansiMemory({ apiKey: process.env.ANANSI_API_KEY, baseUrl: "http://localhost:3000" });
await memory.ingest({ userId: "user_123", content: "User is building a voice agent. Prefers TypeScript. Team of 4.", sourceType: "conversation" });
const ctx = await memory.context({ userId: "user_123", q: "what is the user building?" });
const systemPrompt = `You are a helpful assistant.
${memory.formatForPrompt(ctx)}`;TypeScript SDK를 통해 로컬 인스턴스에 연결하고 메모리를 인제스트·조회하는 예제이다. baseUrl을 로컬 API로 지정해야 호출이 호스티드 서비스가 아닌 사용자의 인스턴스로 향한다는 점이 중요하다. SDK는 /v1 API를 얇게 감싼 클라이언트 역할을 하므로 자체 로직은 거의 없고 formatForPrompt로 바로 시스템 프롬프트에 넣기 쉬운 형태를 만든다.
용어 해설
- 바이-템포럴 모델(Bi-temporal model)
- — 사건의 실제 발생 시점(valid time)과 시스템이 이를 기록한 시점(knowledge time)을 독립적으로 보관하는 시계열 모델로, 언제 사실이 성립했는지와 언제 시스템이 그 사실을 알았는지를 별도로 조회할 수 있게 해준다.
- 엔티티 그래프(Entity graph)
- — 문서·대화에서 추출한 엔티티와 관계를 노드와 엣지로 구조화한 그래프이며, 각 엣지에 시간 축과 출처 근거를 연결해 질문 시 관련 실체와 근거를 신속하게 재구성하는 핵심 데이터 구조이다.
- 하이브리드 검색(pgvector + BM25)(Hybrid retrieval (pgvector + BM25))
- — 벡터 유사도(pgvector)와 전통적 BM25 랭킹을 reciprocal rank fusion으로 결합해 의미적 유사성과 키워드 신호를 동시에 반영하는 단일 SQL 쿼리 기반 검색 방식이다.
- 인제스트·컨텍스트 API(Ingest / Context API)
- — POST /v1/ingest로 데이터를 비동기 큐에 넣어 임베딩과 청킹을 수행하고 GET /v1/context로 이미 합성된 프로필과 관련 청크를 즉시 반환해 시스템 프롬프트로 바로 사용할 수 있게 하는 API 패턴이다.
- 오픈코어 라이선스(MIT + EE)(Open-core license (MIT + EE))
- — 엔진 핵심은 MIT로 누구나 자체 배포할 수 있으나 SSO·SCIM·감사·거버넌스 같은 엔터프라이즈 표면은 LICENSE-EE로 별도 상용 라이선스가 필요하도록 분리한 라이선스 모델이다.
기술
- Postgres와 Redis를 데이터·작업 큐로 활용하고 pgvector로 벡터를 저장하며 ts_rank BM25와 reciprocal rank fusion으로 하이브리드 검색을 구현한다.
- Ollama를 로컬 인퍼런스·임베딩 백엔드로 사용하거나 nomic-embed-text 같은 경량 임베딩 이미지를 가져와 임베딩 처리 파이프라인을 구성한다.
- TypeScript SDK(anansi-memory), Python SDK, LangChain 통합(anansi-langchain)과 Vercel AI SDK 미들웨어를 통해 애플리케이션 레이어에 빠르게 연결할 수 있도록 클라이언트를 제공한다.
활용 사례
- 제품·운영팀의 내부 위키와 채팅 로그가 불일치할 때 문서화된 절차(runbook)와 관찰된 실무 행동의 차이를 시점별로 찾아내어 언제 정책이 바뀌었는지 근거와 함께 밝히는 내부 지식 감사.
- 에이전트가 고객이나 직원의 과거 발언을 근거로 결정을 내려야 하는 시나리오에서, 시스템이 언제 어떤 정보를 알았는지를 분리해 조회해 실수성 발언(후입력된 정보로 인한 잘못된 재구성)을 줄이는 장기 대화형 메모리.
- 자가호스팅 요건이 강한 조직에서 모든 컨텐츠를 로컬에 남기고 싶을 때, 로컬 Ollama와 Compose만으로 완성 가능한 임베딩·합성 파이프라인을 운영하는 내부 플랫폼 통합.
언급된 리소스
AI 요약 · 북마크 · 개인 피드 설정 — 무료
출처 · 인용 안내
인용 시 "요약 출처: AI Trends (aitrends.kr)"를 표기하고, 사실 확인은 원문 보기 기준으로 진행해 주세요. 자세한 기준은 운영 정책을 참고해 주세요.