
Claude Code로 OSS 업데이트를 감시하고, 자사 구현과 대조하여 Notion에 R&D 티켓을 자동 생성하는 AI 에이전트
요약
Claude Code와 Notion MCP를 활용하여 OSS 업데이트를 감시하고 자사 코드와 대조하여 Notion R&D 티켓을 자동 생성하는 AI 에이전트 구축 사례를 소개합니다. 단순 정보 수집을 넘어 자사 컨텍스트를 반영한 구체적인 개선책을 워크플로우에 직접 반영하는 자동화 메커니즘을 다룹니다.
핵심 포인트
- Claude Code의 routine 기능을 활용한 정기적 에이전트 실행
- OSS 업데이트와 자사 구현(버전, 클래스, 추론 모드 등)의 정밀 대조
- Notion MCP를 활용하여 분석 결과를 R&D 티켓으로 자동 전환
- 정보 수집을 넘어 팀의 워크플로우(Backlog)로 연결하는 구조 설계
Nishika의 대표이사 CTO 마츠다입니다.
Nishika에서는 매주 토요일 아침, 아무도 출근하지 않는 시간에 다음과 같은 일이 자동으로 일어나고 있습니다.
- 자사 제품에서 사용하는 OSS repo에 대해 최근 1주일간의 변경 사항을 스캔합니다.
- 해당 변경 사항이 **자사 프로덕트의 구현(어떤 버전을 pin하고, 어떤 클래스를 상속하며, 어떤 추론 모드로 사용하고 있는지)**과 대조됩니다.
- "자사에게 의미 있는 업데이트"만 선별되어, 파일 경로 및 행 번호 수준으로 구체화된 개선책이 Notion의 R&D TODO 데이터베이스에 티켓으로 생성됩니다.
월요일 아침, 사람이 하는 일은 Backlog에 쌓인 티켓을 살펴보며 우선순위를 정하는 것뿐입니다.

게다가 이것은 "릴리스 노트 요약을 Slack으로 보내는" 종류의 bot이 아닙니다. 각 티켓에는 근거가 되는 상류의 PR/릴리스, 자사 코드의 대상 부분(파일·행 번호), 기대 효과가 구조화되어 작성되어 있어, 그대로 검증에 착수할 수 있는 입도(granularity)를 갖추고 있습니다.
이 기사에서는 이 메커니즘의 전체 설계와 정의(cron·프롬프트)의 실물, 운용하며 알게 된 주의점(ハマりどころ)을 작성합니다. 사용 중인 것은 Claude Code의 **routine(정기 실행 클라우드 에이전트)**과 Notion MCP뿐이며, 추가 인프라는 전혀 없습니다.
해결하고 싶었던 과제
AI 프로덕트 개발에서는 의존하고 있는 OSS 에코시스템의 움직임이 너무 빨라서, "캐치업(catch-up)"이 항상 밀리게 됩니다.
- OSS의 릴리스 노트를 읽을 시간이 없다. 읽더라도 "그래서 우리와 관련이 있는가?"라는 판단을 위해서는 자사 구현에 대한 기억이 필요하다.
- HuggingFace에 매주 나오는 신규 모델 중 자사의 배포 제약(GPU/VRAM/OS/라이선스)을 충족하는 것은 극히 일부다. 스크리닝 자체가 노동이다.
- 발견한 사람이 Slack에 붙여넣고 끝난다. 티켓이 되지 않으므로 실행되지 않는다.
즉, 과제는 정보 수집이 아니라, "외부의 업데이트 × 자사의 컨텍스트"의 곱셈과, 그 결과를 팀의 워크플로우(티켓)로 착지시키는 것이었습니다. 이 부분은 LLM 에이전트가 가장 잘할 수 있는 형태를 띠고 있습니다.
전체 아키텍처
routine은 크게 두 계통 ── ①이미 사용 중인 의존 OSS의 추적과 ②아직 사용하지 않는 OSS/모델의 발굴 ── 이 있으며, 둘 다 3층 파이프라인으로 구성되어 있습니다. 각 층은 독립된 에이전트(=독립된 routine)이며, Notion 페이지를 공유 메모리로 사용하여 통신합니다.
①은 감시 대상 OSS 패밀리마다 동일한 구성의 routine을 한 세트씩 실행하고 있습니다. 아래의 도표와 표는 그중 한 세트인 Whisper 계열 OSS를 감시하는 예시입니다.
| 층 | routine | cron (JST) | 역할 |
|---|---|---|---|
| Profile | Dependency Profile Refresh | 월간(매월 1일 09:17) | 자사 repo를 grep하여 "무엇을 어떻게 사용하고 있는지"를 Notion의 고정 페이지에 기록 |
| ... |
②가 Capability Discovery(매주 일요일)입니다. 이것은 "이미 사용 중인 의존의 추적"이 아니라, 아직 사용하지 않는 OSS/모델의 발굴입니다. HuggingFace Hub와 GitHub을 횡단 검색하여, "Product Capability Profile"(프로덕트가 해결하고자 하는 태스크·기존의 페인 포인트·수치 타겟·배포 제약·채택 여부의 triage 규칙을 작성한 고정 페이지)에 비추어 후보를 선별하고, [New Tech Update] 접두사로 PoC 티켓을 생성합니다.

사용 중인 메커니즘: Claude Code의 routine
Claude Code에는 /schedule로 만들 수 있는 routine이라는 기능이 있습니다. cron 식을 전달하면 Anthropic의 클라우드 상에 격리된 세션이 정기적으로 기동되어 프롬프트를 실행해 줍니다. 포인트는 세 가지입니다.
。상류 OSS도 자사의 private repo도 에이전트의 작업 디렉토리에 처음부터 놓아둘 수 있는 sources
에 GitHub repo를 지정하면, 세션 시작 시 clone된 상태로 시작합니다.
- MCP 커넥터를 연결할 수 있다. 이번에는 Notion MCP만 사용했습니다. 티켓 발행도 페이지 생성도 모두 이것으로 처리합니다. 에이전트는 매번 Zero-context(제로 컨텍스트)로 기동하므로,
프롬프트가 곧 사양서(Specification) 그 자체가 됩니다.
예를 들어 Whisper 계열 Digest routine의 구성은 다음과 같습니다 (거의 실제 사례와 유사함).
{
"name": "Whisper ASR Weekly Digest",
"cron_expression": "30 0 * * 6", // 매주 토요일 09:30 JST (UTC 지정)
...
티켓 발행(起票) 측의 routine에서는 sources가 자사 repo로 변경됩니다. 감시는 OSS repo를, 티켓 발행은 자사 repo를 clone하여 동작한다는 것이 이 파이프라인의 핵심입니다.
설계의 핵심
운영하면서 효과적이라고 느낀 설계 판단을 차례대로 작성하겠습니다. 프롬프트의 실제 내용을 인용하며 설명하겠지만, 전문이 길기 때문에 구조가 전달되는 부분만 발췌하겠습니다.
1. Notion 페이지를 「에이전트 간의 공유 메모리」로 만들기
각 routine은 독립된 세션이며, 서로의 실행을 직접적으로 알지 못합니다. 대신, 전 단계가 작성한 Notion 페이지를 다음 단계가 읽음으로써 파이프라인이 형성됩니다.
이 설계의 장점은 중간 생성물이 모두 인간도 읽을 수 있다는 것입니다. Digest 페이지는 인간이 읽어도 충분히 유용한 주간 보고서이며, 에이전트의 판단이 이상할 때는 중간 페이지를 확인하여 어느 계층에서 오류가 발생했는지 알 수 있습니다. 에이전트의 디버그 로그와 팀의 지식(Knowledge)이 동일한 것이 된다고 해도 과언이 아닙니다.
다음 단계가 이전 단계의 출력을 찾는 방법은 '고정 URL'이 아닌 동적 검색 방식을 사용합니다. 티켓 발행 routine의 프롬프트 내용:
`## Step 1: 최신 Whisper Updates 페이지를 가져오기
- notion-fetch를 사용하여 부모 페이지의 자식 페이지 목록을 가져온다.
- 제목이
Whisper Updates - YYYY-MM-DD형식인 것을 필터링한다. - 날짜 기준 내림차순으로 정렬하여 가장 최신 페이지 1건을 선택한다.
- 고정 URL을 전제로 하지 말 것. 반드시 동적으로 최신 페이지를 선택할 것.
최신 페이지가 당일의 것이 아닐 경우(weekly digest가 지연되거나 실패했을 가능성), 이용 가능한 최신 페이지로 진행하되 최종 보고에 그 내용을 명시할 것.`
이전 단계의 digest가 실패하더라도 티켓 발행 측은 전주 데이터를 바탕으로 동작할 수 있으며, 동시에 "지연된 데이터로 동작함"을 보고에 남길 수 있습니다. 파이프라인의 결합도를 느슨하게(Loosely coupled) 유지하면, 한쪽의 실패가 다른 쪽을 망가뜨리지 않습니다.
2. 「자사의 컨텍스트」를 기계적으로 유지되는 페이지로 만들기
이 시스템에서 가장 중요한 것은 digest의 triage(트리아지, 우선순위 분류) 정확도입니다. 그리고 triage 정확도는 "자사가 무엇을 어떻게 사용하고 있는가"를 에이전트가 얼마나 정확하게 알고 있느냐에 따라 결정됩니다.
이를 매번 repo 전체를 스캔(Full scan)하며 수행하면 속도가 느리고 불안정하기 때문에, 월간 Profile Refresh routine이 자사 repo를 grep하여 「Whisper Dependency Profile」이라는 고정 페이지에 써두고, 주간 digest는 그것을 읽기만 하는 분업 구조를 채택했습니다. Profile 페이지에는 고정(pin)된 버전, import 중인 심볼, 상속 중인 클래스, 사용 모델, 추론 모드(Batch/Real-time) 등이 나열되어 있습니다.

사람이 직접 쓰는 문서는 반드시 노후화(腐る)되지만, 매달 에이전트가 실제 코드로부터 재생성하는 문서는 노후화되지 않습니다. "에이전트에게 읽힐 자사 컨텍스트를 다른 에이전트가 정비한다"── 이 재귀적 구조를 깨닫고 나서 설계가 한결 수월해졌습니다.
Capability Discovery 계열의 「Product Capability Profile」도 같은 사상입니다. 여기에는 해결해야 할 태스크 목록, 알려진 페인 포인트(Pain point, 순위 포함), 수치 목표, 시도했으나 실패한 대책(동일한 제안을 반복하지 않기 위해), 채택 여부의 triage 규칙이 적혀 있으며, 프롬프트 내에서 "이 페이지가 정답(authoritative)이다"라고 선언하고 있습니다.
3. 「감시」와 「티켓 발행」을 분리하기
처음에는 하나의 routine으로 "상류를 보고 → 티켓을 작성한다"까지 수행하게 하는 안도 있었습니다. 분리한 이유는 두 가지입니다.
- 관심사의 분리(Separation of Concerns)가 곧 품질이 된다. digest 측은 「사실의 망라와 분류」, 기표(起票) 측은 「자사 구현과의 대조 및 시책화」에 각각의 컨텍스트 창(Context Window)을 전부 사용할 수 있습니다.
- digest는 단독으로도 가치가 있다. 티켓으로 생성되지 않는 🟡나 🟢 정보도, 주간 보고서로서 사람이 훑어볼 수 있습니다.
기표 측은 토요일 10:30, digest 측은 09:30. 1시간 차이를 둔 cron을 통해 느슨하게 결합(Loosely Coupled)하여 연결되어 있습니다.
4. 기표 품질을 지키는 가드레일(Guardrail)
「에이전트가 티켓을 기표한다」는 말을 들으면 많은 사람이 걱정하는 것은 쓰레기 티켓의 산일 것입니다. 실제로 그 부분이 설계를 가장 두텁게 한 곳입니다. 프롬프트의 실제 내용에서:
(a) 기표 전에 DB 스키마와 템플릿을 읽기
1. notion-fetch로 데이터베이스를 읽어, 속성 목록(상태 선택지, 라벨 선택지, 기타 필수 속성)을 파악한다. 2. 데이터베이스에 연결된 기본 템플릿의 구조를 확인한다.
추측으로 작성하게 하지 않습니다. 스키마는 사람이 언제든 바꿀 수 있으므로, 매번 다시 읽는 것이 정답입니다.
(b) 기존 티켓과의 중복 체크
3. 기존의 Backlog/In Progress 티켓을 notion-search로 확인하여, 동일한 시책의 중복 티켓을 만들지 않는다 (제목 유사도 또는 PR/commit 링크 일치로 판정). 다른 계통의 routine이 기표한 티켓과도 중복되지 않을 것.
여러 routine이 동일한 DB에 쓰기 때문에, 계통 간의 중복(예를 들어 동일한 CTranslate2의 성능 개선이 「의존성 업데이트」와 「신기술」이라는 두 가지 문맥으로 나오는 경우 등)까지 명시적으로 제거하고 있습니다.
(c) 쓰기 범위의 제한 ── 이것이 가장 효과적이었다
템플릿 내의 「목적」 섹션에만 다음 3개 항목을 구조화하여 기재: - 개요: 시책의 내용 (무엇을 어떻게 바꾸는지, 대상 리포지토리/파일/모듈) - 상세(PR): 근거가 되는 구체적인 GitHub PR / commit / release 링크 - 기대 효과: 정밀도/속도/VRAM/강건성/유스케이스 확장 중 해당되는 것. 「목적」 이외의 섹션(「골(Goal)」, 「보고」, 「우선순위 평가」 등)은 템플릿의 초기 상태 그대로 일절 편집·추가·덮어쓰기를 하지 말 것. 이것들은 나중에 티켓 담당자가 기입하는 칸이며, 본 routine의 책임 범위를 벗어남.
에이전트는 「목적」만을 작성하며, 골 설정·우선순위 판정(RICE Score)·착수 판단은 인간의 몫으로 남겨둡니다. 에이전트에게 맡긴 것은 「무엇에 주목해야 하는지에 대한 제안」까지이며, 「무엇을 할 것인가에 대한 결정」은 맡기지 않았습니다. 이 선긋기가 팀에 받아들여진 가장 큰 이유라고 생각합니다.
(d) 티켓 제로(Zero)를 명시적으로 허용하기
시책 수의 기준: 최근 업데이트 중 명확하게 가치가 있어 보이는 것을 3~10건 정도. 무리하게 부풀리지 않는다. 정말로 해당되는 업데이트가 없는 주는 제로여도 좋다. 질을 우선한다.
LLM은 「무언가 출력해야 한다」는 압박에 약하기 때문에, 「제로여도 좋다」를 프롬프트에 적는 것은 노이즈 대책으로서 상상 이상으로 효과적입니다. 실제로 조용한 주는 티켓이 생성되지 않습니다.
5. 배포 제약을 제1의 트리아지(Triage)로 삼기
Capability Discovery 측에서는 후보 모델의 evaluation(평가) 시 기술적인 스펙뿐만 아니라 채택 여부를 좌우하는 현실적인 제약을 반드시 쓰게 하고 있습니다. 기표된 티켓의 실제 사례(WhisperLiveKit의 PoC 검증 티켓)에서:
상세(링크/제약)
- GitHub: QuentinFuxa/WhisperLiveKit (10,400 stars, v0.2.20, 28개 릴리스, 성숙도 높음)
개발원/국가: 실체 ASR 모델은 Whisper (OpenAI/미국)이며 일미(日米) 오리진
라이선스: Apache 2.0 ✅ (상업적 이용 가능)
규모/VRAM 추정: 사용 Whisper 모델에 의존 (large-v3 ≈ 6GB) → VRAM 8GB floor 내 ✅
배포 적합성: CUDA 12.8+ 호환 ✅, NVIDIA GPU 전용 ✅, Windows 동작 실적 ✅
온프레미스(On-premise) 제품이므로 「Windows에서 돌아가는가」, 「VRAM 8GB에 들어오는가」, 「라이선스와 개발원은 어디인가」가 기술적인 신규성만큼이나 중요합니다. 이 제약 세트는 Product Capability Profile에 적혀 있으며, 에이전트는 후보마다 이를 대조합니다. 이 부분을 자동화 범위 밖으로 두면, 결국 인간이 모든 후보를 재심사하게 되어 자동화의 의미가 없어집니다.
빠지기 쉬운 함정 (클라우드 실행 특유의 문제)
GitHub API의 rate limit ── API를 사용하지 않는 설계로 전환
초기 버전은 GitHub REST API를 통해 commit/release 정보를 가져왔으나, 클라우드 실행 환경의 IP는 인증되지 않은 GitHub API의 rate limit(60req/h)을 다른 작업들과 공유하고 있어, 실행 시점에 이미 할당량이 소진되어 있는 경우가 빈번했습니다.
대책은 "API를 호출하지 않는 것"입니다. sources에서 모니터링 대상 repo를 clone한 뒤, local git으로 이력을 읽는 설계로 변경했습니다. digest routine의 프롬프트에는 다음과 같이 적혀 있습니다 (원문 그대로):
Do NOT call the GitHub commits/releases API for these repos. Use local git. The cloud IP shares an unauthenticated GitHub rate-limit pool (60/h) that is frequently already exhausted at run time — avoiding that dependency is the entire point of this design.
git log --since='7 days ago'는 rate limit과 무관하며 속도도 빠릅니다. 클라우드 에이전트 설계에서는 "외부 API에 대한 의존성을 하나 제거할 때마다 안정성이 한 단계 올라간다"는 것을 체감할 수 있습니다.
HuggingFace API는 데이터 센터 IP로부터의 미인증 액세스를 403으로 차단
Capability Discovery 측은 HF Hub API를 통해 새로운 모델을 탐색하지만, HF의 WAF(Web Application Firewall)는 데이터 센터 IP로부터의 미인증 요청에 403 에러를 반환합니다. 로컬에서 잘 작동하던 프롬프트가 클라우드에서 완전히 실패하는 전형적인 패턴이었습니다.
대책은 READ 토큰을 환경 변수로 전달한 뒤, 실행 초기에 토큰의 생존 여부를 확인하고, 만약 유효하지 않다면 HF 섹션 전체를 건너뛰고 "건너뛰었다"고 보고하도록 하는 것입니다:
curl -sS -H "Authorization: Bearer $HF_TOKEN" -o /dev/null -w "%{http_code}\n" \ "https://huggingface.co/api/whoami-v2" # expect 200 If HF_TOKEN is empty or the check is not 200: SKIP the entire HF section, still run the GitHub discovery below, and record 「HF discovery skipped: HF_TOKEN missing/invalid」 in the final report.
부분적 장애를 전제로, 무엇이 결여되었는지를 결과물에 기록하게 만드는 것입니다. 무인 실행되는 에이전트에게 가장 무서운 것은 "말없이 성능이 저하되는 것"이기에, 저하 사실을 신고하도록 하는 문구를 반드시 포함하고 있습니다.
Notion이 다운되었을 경우의 fallback
Profile 페이지 로딩에 실패할 경우를 대비하여, 프롬프트 끝부분에 Profile의 스냅샷을 포함해 두었으며, "Notion에서 읽을 수 없다면 임베디드 버전을 사용하여 진행하고, 그 내용을 digest 헤더에 작성하라"고 지시했습니다. 여기서도 원칙은 동일합니다. 중단하는 것이 아니라 저하 모드(degraded mode)로 완주하게 하고, 저하되었다는 사실을 기록하게 하는 것입니다.
실제 생성물
기표된 티켓(거의 실제 사례)입니다.

"목적"에는 다음과 같이 적혀 있습니다 (에이전트가 작성한 원문에서 발췌):
개요: whisper PR #136에서 VAD 파라미터에 min_silence_at_max_speech와 use_max_poss_sil_at_max_speech가 추가되었다. 이는 max_speech_duration_s로 음성을 강제 절단할 때 발생하는 갑작스러운 컷을 방지하고, 장문 발화의 세그먼트 경계 품질을 향상시키는 개선이다.
대상: app/whisper.py:368
── 배치(batch) 시의 vad_parameters={"min_silence_duration_ms": 5000}
(기타, 실시간 시 및 wrapper repo의 해당 라인)
일본어 회의에서는 "에에~", "아노~"와 같은 긴 filled-pause를 포함하는 발화가 강제 절단되어, 구두점이 앞뒤 발화에 혼입되는 현상이 발생한다. (이하 생략)
주목해야 할 점은, 상류(Upstream) PR의 소개가 아니라, 자사 코드의 파일 및 행 번호와 현재 설정값을 특정한 상태에서 "무엇을 어떻게 바꿀 것인가"가 적혀 있다는 것입니다. 이는 티켓 생성 루틴(routine)이 자사 레포지토리(repo)를 클론(clone)한 상태에서 동작하며, 다이제스트(digest) 정보와 grep 결과를 대조하고 있기 때문에 작성 가능한 내용으로, 사람이 직접 한다면 건당 30분은 걸릴 작업입니다.
다음 단계: 티켓 생성 그 너머, "검증"도 자동화하기
지금까지 구현한 것은, 검증해야 할 가설이 근거 및 대상 코드와 함께 매주 Backlog에 안정적으로 공급되는 상태입니다. 우선순위를 정해 검증에 착수하는 것은 인간의 업무로 남아 있습니다.
현재 진행 중인 작업은 그 다음 단계입니다. 이렇게 추출된 티켓에 대해:
- 대상 레포지토리(repo)·모델·평가 데이터셋·평가 지표를
사전에 설정해 두고 - - 에이전트(Agent)가 티켓의 "목적"을 읽고
검증(실험)을 자동 실행하며 - - 결과를 티켓의 "보고" 섹션에
다시 기록
하는 것까지 자동화하려고 합니다. 티켓 생성 시점에 "개요 / 근거 PR / 기대 효과"를 구조화하는 것은 사람이 읽기 편하기 위해서뿐만 아니라, 후속 검증 에이전트에게 전달할 인터페이스로 만들기 위함이기도 합니다. 가설 공급부터 검증 결과 보고까지 한 사이클이 연결되면, 그 내용도 기사로 작성할 예정입니다.
운용 비용과 재현 절차
- 인프라: 제로(Zero). 루틴(routine)은 Claude Code의 기능이며, 서버나 CI를 추가하지 않았습니다.
- 유지보수: 프롬프트(Prompt) 조정만 필요합니다. 스키마(Schema) 변경이나 페이지 이동에는 (매번 다시 읽도록 설계되었으므로) 자동으로 대응합니다.
- 만드는 법: Claude Code에서
/schedule이라고 입력하면 대화를 통해 만들 수 있습니다. cron, sources, MCP 커넥터, 프롬프트를 차례로 질문받을 뿐입니다. 프롬프트는 본 기사의 발췌본을 골격으로 삼으면 대부분 재현할 수 있을 것입니다.
최소 구성부터 시작한다면 3계층은 필요하지 않습니다. "상류 레포지토리(repo)를 sources로 클론(clone) → 로컬 git으로 7일 치를 읽음 → 자사 레포지토리(repo)도 클론(clone)하여 대조 → Notion에 1페이지 작성"하는 단일 프로세스부터 시작하여, 노이즈가 신경 쓰인다면 Profile 계층과 가드레일(Guardrail)을 추가하는 것이 좋은 순서라고 생각합니다.
요약
- OSS 모니터링의 본질은 정보 수집이 아니라 "외부의 업데이트 × 자사 컨텍스트(Context)"의 대조이며, 이 부분은 에이전트(Agent)의 특기 분야입니다.
- Notion 페이지를 공유 메모리로 활용한 3계층 파이프라인(Profile / Digest / Ticketing)을 통해 각 에이전트(Agent)의 책임을 한정합니다.
- 품질은 가드레일(Guardrail)로 구축합니다: 스키마(Schema)를 매번 읽기 · 중복 체크 · 쓰기 범위 제한 · 무의미한 티켓 생성 방지.
- 클라우드 실행은 외부 API 의존성을 제거합니다 (GitHub는 clone + local git, HF는 토큰 + 신고 기반 스킵).
- 인간에게 남은 역할은 우선순위 판정과 착수 판단입니다. 에이전트(Agent)의 업무는 검증해야 할 가설의 안정적인 공급입니다.
마치며
Nishika 엔지니어 팀은 Nishika의 유래인 우리 "자신들만이(Nishika)" 할 수 있는 일은 무엇인지, 사용자에게 제공할 수 있는 가치는 무엇인지를 고민하며 AI의 미래, 엔지니어링의 미래를 생각하고 있습니다.
이러한 미래를 함께 고민하고 만들어갈 동료를 모집하고 있습니다. 관심이 있으신 분은 꼭 연락해 주시기 바랍니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기