Skip to content

About

디스코드 채널에서 자연스럽게 사람들의 대화에 참여하고 지속 학습하는 챗봇.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

discord-bot-become-human-2

English

Discord 그룹 채팅의 전체 맥락을 사람처럼 읽고 필요한 순간에 자연스럽게 끼어드는 AI 에이전트 봇입니다. 서버별 workspace는 봇의 정체성, 장기 기억, 스킬을 텍스트 파일로 담아 두며, OpenAI Codex 또는 OpenAI 호환 LLM과 샌드박스 도구 실행으로 대화와 작업을 확장합니다.


요구사항

  • Node.js 24.11 이상(24 계열) 또는 26 이상
  • Discord 봇 계정 (Developer Portal에서 생성)
  • OpenAI Codex 계정 — 또는 OpenAI API 호환 엔드포인트 (OpenAI, OpenRouter, 로컬 모델 등)
  • bubblewrap (bwrap) — 코드 샌드박스 실행용, Linux 필요 (sandbox.enabled: true일 때만 요구됨)
# Debian/Ubuntu
sudo apt install bubblewrap

# Arch
sudo pacman -S bubblewrap

# Fedora
sudo dnf install bubblewrap

Windows나 bwrap를 설치할 수 없는 환경에서는 config.json에서 sandbox.enabled를 false로 설정하면 bwrap 없이 실행됩니다. 단, OS 수준 격리가 제공되지 않으므로 신뢰할 수 있는 환경에서만 사용하길 권장합니다.


설치

git clone <repo>
cd discord-bot-become-human-2
npm install

설정

1. Discord 봇 토큰

Discord Developer Portal에서 봇을 만들고 토큰을 발급받습니다.

프로젝트 루트에 .env 파일을 만들고 토큰을 넣습니다:

DISCORD_BOT_TOKEN=여기에_봇_토큰

봇 초대 시 필요한 권한:

  • View Channel, Send Messages, Read Message History, Add Reactions

필요한 Gateway Intents (Developer Portal > Bot 탭에서 활성화):

  • Message Content Intent
  • Server Members Intent (선택, 사용자 프로필 품질 향상용)

2. LLM 연결

OpenAI Codex를 사용한다면:

npm run login:codex

브라우저 창이 열리면 로그인합니다. 완료되면 인증 정보가 자동으로 저장됩니다.

OpenAI API나 다른 호환 엔드포인트를 사용한다면:

봇을 처음 실행하면 ~/.discord-bot-become-human-2/config.json이 생성됩니다. 그 안의 llm 항목을 수정합니다:

{
  "llm": {
    "provider": "openai-compatible",
    "model": "gpt-5.5",
    "baseURL": "https://api.openai.com/v1",
    "apiKeyEnv": "OPENAI_API_KEY",
    "contextWindow": 128000
  }
}

.env에 API 키도 추가합니다:

OPENAI_API_KEY=여기에_API_키

3. 실행

npm run dev

처음 실행하면 봇이 들어있는 서버마다 설정 폴더가 자동으로 만들어집니다.


봇 성격 설정

봇의 성격과 동작 방식은 텍스트 파일로 설정합니다. 파일은 서버별로 분리되어 있어서 서버마다 다른 봇처럼 운영할 수 있습니다.

설정 파일 위치:

~/.discord-bot-become-human-2/guilds/<서버ID>/workspace/

기존 workspace에는 템플릿 변경이 자동으로 반영되지 않습니다. 갱신하려면 봇을 중지하고 최신 templates/workspace/의 SOUL.md, GROUP.md, TOOLS.md와 기본 스킬을 각 workspace에 덮어쓴 뒤 재시작하세요. memory/, users/와 커스텀 스킬은 유지합니다.

SOUL.md — 봇의 정체성

봇의 이름, 성격, 말투, 해서는 안 되는 행동을 정의합니다.

## Identity
- Name / nickname: 봇 이름이나 닉네임
- Role in this server: 이 서버에서 맡은 역할

## Personality
- Default tone: 친근하고 가볍게
- Humor style: 유머는 적당히, 억지로 웃기려 하지 않기

## Speaking Style
- Preferred language(s): 한국어
- Default response length: 짧고 간결하게

## Boundaries
- 개인 DM 내용이나 민감한 주제는 다루지 않기

GROUP.md — 서버 분위기

이 서버가 어떤 곳인지, 어떤 분위기인지 알려줍니다. 봇이 대화에 끼어들 타이밍을 잡을 때 참고합니다.

## What this server is
- Server purpose: 개발자들이 모인 스터디 서버
- Languages commonly used: 한국어

## Social Norms
- How casual or formal people are: 친한 사이, 반말 사용
- How much bot participation is usually welcome: 적당히, 너무 자주 끼어들지 않기

봇이 대화에 참여하는 방식

봇은 세 가지 경우에 반응합니다:

  1. 직접 호출 — 봇을 멘션하거나, 봇 메시지에 답장하거나, 봇 이름을 부를 때
  2. 자발적 참여 — 대화 주제와 분위기가 맞을 때 스스로 끼어듦 (GROUP.md 설정에 따라 조절 가능)
  3. 반응 — 말로 답하는 대신 이모지 반응으로 참여

대화 중간에 말을 걸지 않을 때도 있습니다. 이미 대화가 잘 흘러가고 있으면 조용히 지켜보는 게 기본 동작입니다.


기억

봇은 대화 내용을 기억합니다. 서버 전체에 대한 기억과 사용자 개인에 대한 기억을 따로 관리합니다.

  • 서버 기억 — workspace/memory/MEMORY.md에 저장됩니다. 직접 편집해서 봇이 알아야 할 정보를 미리 넣어둘 수 있습니다.
  • 사용자 기억 — workspace/users/<사용자ID>/USER.md에 저장됩니다. 대화를 통해 자동으로 채워집니다.
  • 기억은 서버별로 분리됩니다. 같은 사용자라도 다른 서버에서는 처음 만난 사람처럼 대합니다.

스킬 추가

봇의 기능을 확장하고 싶다면 workspace/skills/ 아래에 스킬 폴더를 만들 수 있습니다.

workspace/skills/
  my-skill/
    SKILL.md

SKILL.md 예시:

---
name: my-skill
description: 언제 이 스킬을 써야 하는지 — 예: "Use this skill when the user asks about X"
---

이 스킬은 ... 할 때 사용합니다.

## 지침
- ...

봇에게 채팅으로 "새 스킬 만들어줘"라고 해도 됩니다. 봇이 직접 스킬 파일을 작성합니다.

기본 내장 스킬: memory, skill-creator, weather, workspace-files, discord-actions


config.json 설정 항목

봇을 처음 실행하면 ~/.discord-bot-become-human-2/config.json이 기본값으로 생성됩니다.

discord

항목 기본값 설명
tokenEnv "DISCORD_BOT_TOKEN" 봇 토큰을 읽어올 환경 변수 이름
allowedGuildIds [] 허용할 서버 ID 목록. 비워두면 모든 서버에서 동작
allowedChannelIds [] 허용할 채널 ID 목록. 비워두면 모든 채널에서 동작
adminUserIds [] /compact, /dream 등 관리자 명령어를 사용할 수 있는 사용자 ID 목록
enableMentions true 봇 멘션 반응 활성화
enableReplies true 봇 메시지 답장 반응 활성화
enableReactions true 이모지 반응 기능 활성화
enableMessageEditStreaming true 스트리밍 답변 활성화 (메시지를 점진적으로 편집하며 출력)

llm

두 가지 provider 중 하나를 선택합니다.

OpenAI Codex:

{
  "llm": {
    "provider": "openai-codex",
    "model": "gpt-5.5",
    "reasoning": "medium",
    "codex": {
      "authPath": "~/.discord-bot-become-human-2/codex-auth.json",
      "transport": "auto",
      "usageLimit": {
        "enabled": false,
        "minRemainingPercent": 20,
        "pollIntervalMs": 60000
      }
    }
  }
}
  • reasoning: "low" / "medium" / "high" / "xhigh"
  • transport: "auto" / "responses" / "websocket"
  • usageLimit.enabled: 구독 잔여량 제한 활성화 (기본 false). 중지 중에는 Discord에 자리 비움으로 표시
  • usageLimit.minRemainingPercent: 계정 전체 Codex의 최소 잔여율 (기본 20). 기간별 잔여량 중 하나라도 미만이면 중지하고, 회복되면 자동 재개
  • usageLimit.pollIntervalMs: 구독 잔여량 조회 간격 (ms, 기본 60000). 조회 실패 시 일시 중지
  • GPT-6 모델을 사용하려면 model을 "gpt-6.1-sol", "gpt-6-sol" 또는 "gpt-6-luna"로 바꾼 뒤 봇을 재시작합니다. 기존 config.json의 모델 값은 자동으로 바뀌지 않습니다.
  • 업데이트를 배포할 때는 서버에서 npm ci와 npm run build를 실행한 뒤 봇을 재시작합니다. pi 모델 카탈로그는 설치된 의존성에서 읽으므로 소스나 dist만 교체하면 Unknown openai-codex model 오류가 계속 발생할 수 있습니다.

OpenAI 호환 엔드포인트:

{
  "llm": {
    "provider": "openai-compatible",
    "model": "gpt-5.5",
    "baseURL": "https://api.openai.com/v1",
    "apiKeyEnv": "OPENAI_API_KEY",
    "contextWindow": 128000,
    "reasoning": "medium"
  }
}
  • apiKeyEnv: API 키를 읽어올 환경 변수 이름
  • contextWindow: 모델의 컨텍스트 윈도우 크기 (토큰 수)

runtime

항목 기본값 설명
rootDir "~/.discord-bot-become-human-2" 런타임 데이터 저장 루트 경로
defaultLocale "ko-KR" 봇이 사용할 기본 언어
timezone "Asia/Seoul" 봇이 시간 표현에 사용할 타임존

conversation

기본값

항목 기본값 설명
maxRecentMessages 100 컨텍스트에 포함할 최근 이벤트 수
maxParticipantsForProfileLoad 16 한 번에 로드할 최대 사용자 프로필 수
cooldownMs [10000, 30000] 답변 후 쿨다운 시간 범위 (ms). 범위 안에서 무작위 선택

notEngaged — 비참여 상태에서 참여 진입 조건

항목 기본값 설명
directTriggerDebounceMs [0, 1000] 멘션·이름·답글·슬래시 등 직접 트리거 후 응답까지 지연 범위 (ms)
ambientDebounceMs [3000, 9000] 앰비언트 참여 후 응답까지 지연 범위 (ms)
ambientEngagementEnabled true 직접 트리거 없이 자발적으로 대화에 참여할지 여부
ambientMinSilenceMs 300000 앰비언트 참여를 시도하기 위한 최소 침묵 시간 (ms, 기본 5분)
ambientDecisionCooldownMs 900000 앰비언트 참여 판단 LLM 호출 사이 최소 간격 (ms, 기본 15분)
ambientConfidenceThreshold 0.78 앰비언트 참여를 결정하는 LLM 신뢰도 최솟값
ambientMaxPerHour 2 시간당 최대 앰비언트 참여 횟수

engaged — 참여 중 상태에서 응답 조건

항목 기본값 설명
minSecondsBetweenBotReplies 20 연속 응답 사이 최소 간격 (초)
minSecondsBetweenUnpromptedReplies 90 자발적 응답 사이 최소 간격 (초)
maxConsecutiveBotReplies 1 사람 메시지 없이 연속으로 보낼 수 있는 최대 답변 수
replyConfidenceThreshold 0.7 응답하기 위한 LLM 신뢰도 최솟값
silentStayConfidenceThreshold 0.55 이모지 반응하기 위한 LLM 신뢰도 최솟값
disengageAfterUnrelatedHumanMessages 8 봇과 무관한 사람 메시지가 이 수에 도달하면 참여 종료
disengageAfterIdleMs 900000 마지막 사람 메시지로부터 이 시간이 지나면 참여 종료 (ms, 기본 15분)

engaged.followUpBatch — 참여 중 메시지 묶음 처리

항목 기본값 설명
directTriggerDebounceMs [1000, 2000] 직접 트리거 메시지가 있을 때 flush 전 대기 범위 (ms)
quietDebounceMs [3000, 5000] 일반 메시지일 때 flush 전 대기 범위 (ms)
maxWaitMs 15000 최대 대기 시간. 이 시간이 지나면 강제로 flush (ms)
maxMessages 4 이 수를 초과하면 즉시 flush

memory

compaction — 이벤트 로그 압축

항목 기본값 설명
enabled true 이벤트 로그 압축 활성화
maxEventsBeforeCompaction 120 이 이벤트 수를 초과하면 오래된 것을 압축
minEventsPerSummary 20 한 번 압축할 때 최소 포함 이벤트 수

dream — 장기 기억 업데이트

항목 기본값 설명
enabled true Dream 실행 활성화
intervalMinutes 120 Dream 실행 최소 간격 (분)
runOnConversationEnd true 대화 종료 후 Dream 실행 여부
runOnCompaction true 압축 후 Dream 실행 여부
allowEditSoul true Dream이 SOUL.md를 편집할 수 있는지 여부
allowEditGroup true Dream이 GROUP.md를 편집할 수 있는지 여부
allowEditUserProfiles true Dream이 사용자 프로필을 편집할 수 있는지 여부

tools

봇이 사용할 수 있는 도구를 켜고 끕니다. 모두 기본값 true.

항목 설명
workspaceFiles workspace 파일 읽기·쓰기
memory 기억 읽기·쓰기
discordActions Discord 메시지 전송·수정·삭제·반응
fetchUrl URL 내용 가져오기
readAttachment 메시지 첨부 파일 읽기
sandboxExec 샌드박스 코드 실행
searchInternet 인터넷 검색 (search 설정도 필요)
imageGeneration Codex OAuth로 이미지 생성·편집 (openai-codex에서만 제공)

sandbox

항목 기본값 설명
enabled true true: bwrap로 OS 수준 격리. false: bwrap 없이 직접 실행 (cwd 고정·env 정화·셸 차단 적용, OS 격리 없음 — 비권장)
network true 샌드박스 내 네트워크 허용 (enabled: true일 때만 유효)
timeoutMs 30000 샌드박스 실행 최대 시간 (ms)
outputLimitBytes 131072 샌드박스 출력 최대 크기 (bytes)

search (선택)

인터넷 검색 기능에 사용할 검색 API를 설정합니다. tools.searchInternet이 true여야 동작합니다.

{
  "search": {
    "provider": "tavily",
    "apiKey": "tvly-..."
  }
}

observability (선택)

LLM 호출을 Langfuse로 추적합니다.

{
  "observability": {
    "langfuse": {
      "publicKeyEnv": "LANGFUSE_PUBLIC_KEY",
      "secretKeyEnv": "LANGFUSE_SECRET_KEY",
      "host": "https://cloud.langfuse.com"
    }
  }
}

환경 변수에 키를 넣습니다:

LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...

Docker로 배포

Docker가 설치된 Linux 서버에서 바로 실행할 수 있습니다.

실행

docker run -d \
  --name bot \
  --restart unless-stopped \
  --env-file .env \
  -v bot-data:/root/.discord-bot-become-human-2 \
  neurowhai/discord-bot-become-human-2:latest

직접 빌드하려면:

docker build -t discord-bot-become-human-2 .

봇 데이터(config.json, codex-auth.json, guild workspace)는 bot-data named volume에 영속화됩니다.

초기 설정

컨테이너를 처음 실행하면 config.json이 기본값으로 생성됩니다. 설정을 변경하려면:

docker exec -it bot sh -c 'cat /root/.discord-bot-become-human-2/config.json'
# 호스트에서 볼륨 경로의 파일을 편집한 뒤 재시작:
docker restart bot

config.json은 시작 시 한 번만 읽힙니다. 변경 후에는 반드시 재시작해야 반영됩니다.

Codex 로그인 (openai-codex 사용 시)

docker run --rm -it \
  -v bot-data:/root/.discord-bot-become-human-2 \
  neurowhai/discord-bot-become-human-2:latest \
  node dist/scripts/login-openai-codex.mjs

로그 확인

docker logs -f bot

JSON 형식으로 구조화된 로그가 필요하면 --env-file 파일에 추가합니다:

LOG_FORMAT=json

bwrap 샌드박스

이미지 안에 bwrap이 setuid로 설치되어 있어 --privileged 없이도 샌드박스가 동작합니다. 일부 커널 설정에서 user namespace가 제한된 경우 --security-opt seccomp=unconfined를 추가합니다.


개발 명령어

npm run dev       # 봇 실행
npm run build     # 빌드
npm test          # 테스트
npm run check     # 타입 체크
npm run lint      # 린트

로그 레벨 조절:

LOG_LEVEL=debug npm run dev

런타임 파일 구조

모든 데이터는 ~/.discord-bot-become-human-2/ 아래에 저장됩니다.

~/.discord-bot-become-human-2/
  config.json
  codex-auth.json

  guilds/
    <서버ID>/
      workspace/
        SOUL.md
        GROUP.md
        TOOLS.md
        memory/
          MEMORY.md       # 서버 장기 기억
          events.jsonl    # Discord 이벤트 로그
          history.jsonl   # 대화 압축 아카이브
        users/
          <사용자ID>/
            USER.md       # 사용자 프로필
        skills/           # 서버별 스킬

config.json과 codex-auth.json은 봇 에이전트에게 노출되지 않습니다. 에이전트는 현재 서버의 workspace 안에서만 파일을 읽고 쓸 수 있습니다.


기술 스택

  • Node.js / TypeScript
  • discord.js — Discord 이벤트 수신 및 메시지 전송
  • pi agent harness (@earendil-works/pi-agent-core, @earendil-works/pi-ai) — ReAct 스타일 에이전트 실행
  • bwrap — 샌드박스 실행 격리 (Linux)

참고한 프로젝트

  • pi — 에이전트 실행 코어 및 OpenAI Codex provider
  • nanobot — workspace 기반 장기 기억, Dream memory lifecycle, skill 구조 설계에 영향을 받았습니다

About

디스코드 채널에서 자연스럽게 사람들의 대화에 참여하고 지속 학습하는 챗봇.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages