소개
시도하고자 했던 것과 그 이유
2주차에 coco-brain(LLM Wiki) 구조를 완성한 후, 3주차 목표는 "지식이 자동으로 쌓이고, 스스로 품질을 유지하는 자동화 파이프라인" 을 구축하는 것이었습니다.
제 개인적인 일상에서는 매일 반복되는 세 가지 루틴이 있었어요:
(재테크) 투자 종목 분석 → 매번 처음부터 다시 확인
(건강) 식단/운동 기록 → 누적 데이터가 활용되지 못함
(업무) 경쟁사 일별 실적 분석 → 수작업으로 진행
이를 해결하기 위해 도메인별 Ingest 파이프라인 + 워크플로우 명령어 + 품질 관리 시스템을 구축했습니다.
핵심 목표는 단순한 자동화가 아니라, 코코가 스스로 판단하고 제게 검토를 요청하는 구조를 만드는 것이었습니다.
진행 방법
사용한 도구
도구
역할
Hermes Agent
AI 에이전트 실행 엔진
Discord
채널별 인터페이스
Oracle Cloud E2.1.Micro
서버 (서버 용량이 적어서 OpenViking 등을 구현 못함)
Obsidian
지식 저장소 편집 UI
GitHub
버전 관리 + 10분 자동 동기화
defuddle 0.18.1
웹페이지 → 마크다운 변환
1단계: 투자 Ingest 파이프라인 구축
Bloomberg RSS 뉴스를 자동으로 수집하고, 투자 관련 뉴스만 필터링하는 구조를 만들었습니다.
rss_news_watch.py에 저장 기능 추가:
python
def save_to_coco_brain(items: list) -> None:
"""새 뉴스를 sources/news/에 저장"""
brain_path = Path.home() / "coco-brain" / "sources" / "news"
brain_path.mkdir(parents=True, exist_ok=True)
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
news_file = brain_path / f"{today}-bloomberg.md"
existing = news_file.read_text(encoding="utf-8") if news_file.exists() else f"""---
title: Bloomberg 뉴스 {today}
type: raw
domain: investment
source: Bloomberg RSS
created: {today}
updated: {today}
used_by: []
---
# Bloomberg 뉴스 {today}
"""
new_lines = []
for item in items:
time_str = fmt_time(item.published_at)
new_lines.append(f"## {item.title}")
new_lines.append(f"- 시간: {time_str}")
new_lines.append(f"- 링크: {item.url}")
new_lines.append("")
news_file.write_text(existing + "\n".join(new_lines), encoding="utf-8")투자 뉴스 필터링 스크립트 (investment_news_filter.py):
python
KEYWORDS = [
'NVDA', 'PLTR', 'nvidia', 'palantir',
'AI', 'artificial intelligence', '반도체', 'semiconductor',
'금리', 'rate', 'Fed', 'Federal Reserve',
'S&P', 'nasdaq', 'inflation', 'GDP',
]Cron 자동화 설정:
bash
# 투자 뉴스 필터링 → us_market.md 업데이트 (매일 11:00 KST)
hermes cron add "0 2 * * *" \
--name "Bloomberg 투자뉴스 필터링 → us_market.md" \
--script investment_news_filter.py \
--no-agent2단계: Promotion State + Self-eval 하네스 구축
핵심 프롬프트 (AGENTS.md에 추가):
markdown
## Promotion State 규칙 (업무 도메인)
- 경쟁사 편성표 분석 보고서 생성 시:
- 저장 위치: context/work/reports/YYYY-MM-DD-competitor.md
- promotion_state: draft (자동)
- derived_from: sources/market_data/ 원본 파일 명시
## Self-eval 규칙 (업무 도메인)
업무 보고서 생성 후 검토 요청 전에 아래 4단계 self-eval을 먼저 수행한다.
1. LOAD → index.md → context/work/ → sources/ 순서로 참조
2. GENERATE → 보고서 초안 생성
3. CLAIM → based_on / confidence / reason 명시
4. SELF-EVAL → accuracy / completeness / action_needed 평가
## 검토 요청 규칙 (업무 도메인)
업무 보고서 생성 후 #운영 채널(1507282248804728842)에 아래 형식으로 검토 요청.
📋 [검토 요청] {보고서 종류}
파일: context/work/reports/YYYY-MM-DD-{type}.md
생성일: YYYY-MM-DD
출처: {derived_from 파일명}
📌 핵심 요약:
- {핵심 내용 2~3줄}
🔍 Self-eval 결과:
- confidence: 높음/중간/낮음
- 누락 데이터: {있으면 명시}
- 추가 확인 필요: {있으면 명시}
✅ verified 또는 ❌ rejected 로 답변해주세요!실제 코코 검토 요청 예시:
📋 [검토 요청] 경쟁사 편성표 분석 보고서
파일: context/work/reports/2026-06-01-competitor.md
생성일: 2026-06-01
출처: sources/market_data/2026-06-01-(경쟁사 이름).md
📌 핵심 요약:
- (경쟁사 A 이름) 26개 OO 블록 수집
- (경쟁사 B 이름)은 OO 채널 기준 18건 반영
🔍 Self-eval 결과:
- confidence: 중간
- 누락 데이터: 내부 실적 데이터 미연결
- 추가 확인 필요: 라이브 채널 자동 수집 기준 확인 필요
✅ verified 또는 ❌ rejected 로 답변해주세요!3단계: 역링크(used_by) + Obsidian 그래프 연결
SCHEMA.md에 역링크 규칙 추가 (16번 섹션):
markdown
## 16. 역링크 규칙 (used_by)
### frontmatter (기계 처리용)
used_by:
- context/work/reports/YYYY-MM-DD-competitor.md
### 본문 (Obsidian 그래프용)
## 이 자료가 기여한 문서
- [[파일명]] — 간단한 설명코코가 보고서를 생성할 때마다 자동으로:
sources/파일의 frontmatter에used_by추가본문 맨 아래에
[[wikilink]]추가Obsidian 그래프에서
sources/ → reports/연결선 자동 생성
4단계: 워크플로우 명령어 구현
markdown
## 워크플로우 명령어
### /ingest [자료 설명 또는 파일 경로]
1. sources/ 적절한 폴더에 저장
2. 핵심 내용 추출 후 context/ 업데이트
3. 역링크(used_by) 추가
4. log.md에 기록
### /search [검색어]
1. index.md 먼저 확인
2. 관련 context/ 파일 검색
3. sources/ 원본도 확인
4. 결과 요약 후 출처 명시
### /save [저장할 내용]
→ 도메인 판단 후 context/ 저장
### /promote [파일 경로]
→ members/ → context/ 승격 + verified 변경
### /brain-status
→ coco-brain 현황 요약 출력
(sources 최근 파일 / 오늘 기록 여부 / Lint 결과)5단계: 피트니스 트레이너 코코 + workout-pr.md
주간 피트니스 요약 스크립트 핵심 파싱 로직:
python
def parse_kcal(text):
for pat in [r'kcal:\s*약?\s*([\d,]+)', r'총열량:\s*약?\s*([\d,]+)']:
m = re.search(pat, text)
if m:
return float(m.group(1).replace(',', ''))
return 0
def parse_protein(text):
# 범위 형식(148.5~150.5g) 포함 처리
m = re.search(r'단백질:\s*약?\s*([\d,]+(?:\.\d+)?)(?:~[\d,.]+)?g', text)
return float(m.group(1).replace(',', '')) if m else 0트레이너 피드백 예시:
📊 주간 피트니스 요약 (2026-05-30 ~ 2026-06-05)
✅ 칼로리 적자 유지 중 (1705kcal). 감량 페이스 좋아요!
📊 단백질 거의 달성! (122g / 목표 135g)
📊 운동 3일. 목표까지 2일 더!workout-pr.md 자동 생성 스크립트:
python
# 볼륨(무게 × 반복수) 기준 최고 기록 자동 추출
if exercise not in prs or volume > prs[exercise]['volume']:
prs[exercise] = {
'weight': weight, 'reps': reps,
'volume': volume, 'date': date, 'split': split
}결과와 배운 점
배운 점
1. "AI가 말함 ≠ 사실 확인됨" Promotion State(draft→verified)를 도입하면서 가장 크게 배운 점입니다. 코코가 생성한 보고서를 바로 사용하지 않고, 제가 승인한 것만 verified로 올라가는 구조를 만들었어요.
2. 역링크가 살아있는 지식 지도를 만든다 [[wikilink]]를 추가하자 Obsidian 그래프에서 sources/ → reports/ 연결선이 자동으로 생겼어요. 단순한 파일 저장이 아니라 지식이 어디서 왔고 어디에 쓰였는지 추적할 수 있게 됐습니다.
3. 평가자 고정이 핵심이다 (Autoresearch 불변식) Self-eval 하네스에서 confidence와 action_needed를 명시하게 만들면서, 코코가 스스로 "이 보고서는 (경쟁사 B) 데이터가 빠져서 신뢰도가 중간"이라고 판단하게 됐어요.
4. lint.py가 주간 건강검진 역할 매주 월요일 자동으로 돌아가는 Lint가 broken wikilink, missing frontmatter를 자동으로 찾아줍니다. 33개 오류 → 0 오류로 만드는 과정에서 wikilink 파싱 버그, 백틱 예외 처리 등을 개선했어요.
나만의 꿀팁
Oracle 서버에서 파일 수정 → git push를 원칙으로 하면 로컬 충돌이 줄어요
워크플로우 명령어는 Hermes 내장 명령어와 충돌하지 않는 이름(
/brain-status)을 써야 해요식단 파일에
1,938kcal같은 쉼표 포함 숫자가 있으면 파싱 시.replace(',', '')처리가 필수
시행착오
1. /status 명령어 충돌 Hermes 내장 /status 명령어와 충돌해서 coco-brain 현황 대신 Hermes Gateway 상태가 출력됐어요. /brain-status로 이름을 바꿔 해결했습니다.
2. 로컬 ↔ Oracle 충돌 반복 WSL Obsidian Git(10분)과 Oracle 서버 cron(10분)이 동시에 push하면서 충돌이 자주 발생했어요. Oracle 서버에서 편집하는 것을 원칙으로 정하면서 해결됐습니다.
3. 식단 파싱 형식 다양성 날짜별로 kcal: 약 1,938kcal / 총열량: 약 1,881 kcal / 단백질: 약 148.5~150.5g 등 형식이 달라서 파싱이 계속 실패했어요. 여러 패턴을 순서대로 시도하는 방식으로 해결했습니다.
4. Oracle A1.Flex 용량 부족 메모리 확장을 위해 Oracle A1.Flex(4코어/24GB)를 생성하려 했지만 AD-1 용량 부족으로 실패했습니다. 현재 E2.1.Micro에서 계속 운영 중이에요. (따라서 OpenViking, Autoresearch, Ouroboros 설치가 어려운 수준입니다 ㅠㅠ)
도움이 필요한 부분
Oracle A1.Flex 용량 확보 방법 (AD-1 외 다른 AD 시도 또는 자동 재시도 스크립트)
OpenViking 도입 (현재 메모리 97MB 여유로 설치 불가)
앞으로의 계획
내용
AutoResearch + Crawl4AI 도입
경쟁사 편성표 자동 크롤링 (현재 수동)
OpenViking 도입 (L0/L1/L2 계층 로딩)
도움 받은 글 (옵션)
참고한 지피터스 글이나 외부 사례를 알려주세요.
gpters — LLM Wiki Ingest/Query/Lint 루프 사례 — used_by 역링크 개념과 Schema 3단계 승격 원칙 적용에 영감
gpters — 수당 지식 창고 구축기 — Self-eval 하네스 4단계 구조 도입에 참고
Giacomo — Autoresearch · Ouroboros · Hermes Self-Evolution 정리 — "평가자 고정이 진짜 기술" 원칙을 Self-eval 설계에 적용
kepano/obsidian-skills — defuddle을 활용한 클린 마크다운 크롤링 방법 적용
매번 도움 주시고 열심히 준비해주시는 지아코모 스터디장님, 그리고 스터디원 분들의 뛰어난 사례글들이 배움에 있어서 큰 참고가 되었습니다 :) 감사드립니다!