케이스 스터디: ClaudeOps
한 줄 정의 여러 Claude 에이전트가 자율적으로 일하고, 서로의 작업을 같은 데이터베이스 위에서 추적·보고하는 개인 내부 협업 플랫폼이다. 왜 만들었나 이나 cron + 헤드리스로 자동화를 늘리다 보면 어딘가에서 막힌다. 자동화 하나하나는 잘…
한 줄 정의
여러 Claude 에이전트가 자율적으로 일하고, 서로의 작업을 같은 데이터베이스 위에서 추적·보고하는 개인 내부 협업 플랫폼이다.
왜 만들었나
/loop이나 cron + 헤드리스로 자동화를 늘리다 보면 어딘가에서 막힌다. 자동화 하나하나는 잘 도는데, 그것들의 상태가 어디에도 없다. 어떤 잡이 마지막에 뭘 했는지, 다른 에이전트가 같은 파일을 손대고 있는지, 보고는 어디 쌓이는지 — 다 흩어져 있다.
자동화 개수가 셋을 넘기면 공유 상태 저장소가 필요해진다. ClaudeOps는 그 자리를 채우려고 만든 것이다.
핵심 설계 결정: 스케줄러 없는 스케줄러 플랫폼
가장 결정적인 선택은 ClaudeOps 안에 스케줄러를 넣지 않은 것이다.
처음엔 NestJS의 스케줄 모듈로 직접 cron을 돌리고, 시간이 되면 Anthropic API를 호출해서 에이전트를 깨우는 구조를 잡으려 했다. 그런데 그걸 다 만들면 ClaudeOps가 두 가지 일을 하게 된다 — 데이터 허브 + AI 워커. 한 시스템 안에 너무 다른 책임이 섞인다.
대신 깨우는 일은 외부에 맡겼다. Claude Cowork의 스케줄러가 정해진 시각에 에이전트를 깨우고, 깨어난 에이전트가 ClaudeOps API에 접속해서 스스로 할 일을 가져간다. ClaudeOps는 그냥 CRUD 서버다.
[Cowork 스케줄러]
↓ 에이전트 깨움
[Claude 에이전트 (Skills 문서 읽고 시작)]
↓ GET /api/agent/tasks/pending
[ClaudeOps]
↓ 할 일 반환
[에이전트 작업 수행]
↓ POST /api/agent/tasks/:id/report
[ClaudeOps에 보고 누적]
이 분리 덕에 얻은 것 세 가지.
- ClaudeOps에서 AI 호출 비용이 0이다. 비용은 Cowork 쪽 사용량 한도에서 처리된다.
- 에이전트가 10개로 늘어도 ClaudeOps는 여전히 가벼운 CRUD 서버다.
- ClaudeOps 자체는 내려가도 에이전트들이 일을 안 받아갈 뿐 깨는 동작은 멈추지 않는다. 책임 경계가 깔끔하다.
데이터 모델
테이블 네 개로 끝난다.
- Agent. 고유
agent_id+api_key. 누가 뭘 했는지 추적 가능. - Project. 작업 단위 묶음. 새 사업이 생기면 프로젝트 하나 추가하고 에이전트 배정.
- Task. 등록된 할 일 + 상태(pending / in_progress / done / failed).
- Report. 에이전트가 작업 끝나고 남기는 결과.
권한은 Bearer 토큰. 한 에이전트의 토큰이 새도 그 에이전트 권한 범위 안에서만 위험하다.
Skills 디렉토리: 프롬프트의 진짜 위치
에이전트의 프롬프트는 짧게 유지한다. "이런 일을 해라"는 길게 적지 않는다. 대신 Skills 문서라는 외부 마크다운을 두고, 깨어난 에이전트가 그걸 먼저 읽게 한다.
curl -s https://claudeops.wooncloud.com/api/skills/claudeops_usage
curl -s https://claudeops.wooncloud.com/api/skills/report_format
curl -s https://claudeops.wooncloud.com/api/skills/agent_roles
이게 좋은 이유:
- 운영 중에 행동을 바꿀 수 있다. Skills 문서만 수정하면 모든 에이전트의 다음 실행부터 행동이 바뀐다. 프롬프트 자체를 안 건드린다.
- 프롬프트가 공통화된다. 에이전트마다 다른 건 식별 정보(agent_id, api_key, 프로젝트명)뿐이고, 일하는 방식은 Skills에서 공유된다.
- 버전 관리된다. Skills를 git에 두면 에이전트의 행동 변경이 커밋 히스토리로 남는다.
자율 동작 원칙: 할 일 없을 때도 일하기
이 부분이 단순 잡 큐와 가장 큰 차이다.
1. 깨어남
2. Skills 문서 읽음
3. 할 일 있나?
- 있으면 → 수행 → 보고 → 끝
- 없으면 → 자체 리팩토링 모드로 전환
4. 단, 직전 5커밋에 refactor: 가 있으면 건너뜀 (과한 리팩토링 방지)
5. 어느 경우든 commit / push까지 끝낸다
6. 실패해도 실패 보고는 반드시 제출
"할 일이 없으면 쉬어"가 아니라 "할 일이 없으면 코드를 점검해" — 에이전트의 유휴 시간을 자기 개선에 쓰는 구조다. 다만 무한 리팩토링 루프를 막기 위한 가드(직전 5커밋 체크)가 들어가 있다.
자동화 카테고리에서의 위치
이 시리즈에서 다룬 방법들의 조합이다.
| 시리즈 항목 | ClaudeOps에서의 역할 |
|---|---|
| 외부 스케줄러 + 헤드리스 (3번) | Cowork이 정확히 이 패턴으로 동작 |
| Webhook + 헤드리스 (6번) | 향후 PR 이벤트로 깨우기로 확장 가능 |
| Hooks (5번) | 위험 명령 차단·자동 commit 메시지 검증에 적용 |
즉 ClaudeOps는 새로운 방법이 아니라, 기존 방법들이 공유 상태 위에서 협업하기 시작했을 때 필연적으로 나오는 형태다. 자동화가 일정 규모를 넘으면 누구나 비슷한 걸 만들게 된다.
한계와 다음 과제
만들고 운영해보면서 보이는 약점.
- 스케줄러 의존. Cowork이 안 깨우면 ClaudeOps는 빈 서버다. Cowork 쪽 장애가 곧 자동화 정지로 이어진다.
- 동시 작업 충돌. 두 에이전트가 같은 파일을 만지면 git 충돌이 난다. 현재는 git worktree로 분리하지만, 더 늘면 파일 단위 락이 필요해진다.
- 신뢰 경계. 에이전트가 commit·push 권한을 갖는다는 건 자동화의 끝이자 가장 위험한 지점이다. hooks로 PreToolUse 단에서 위험 명령을 막는 건 거의 필수다.
- 관측. 어떤 에이전트가 토큰을 가장 많이 쓰는지, 어떤 태스크가 자주 실패하는지 — 대시보드 단이 약하다. 다음 단계.
정리
처음엔 "에이전트들이 자율적으로 일하는 걸 보고 싶다"가 시작이었지만, 결국 만들고 보니 핵심은 모델 자체가 아니라 스케줄러 + 공유 상태 + Skills 문서의 조합이었다.
작은 플랫폼이지만, 이 시리즈에서 다룬 자동화 방법들의 종착지가 어떤 모양인지 보여주는 사례라고 생각한다. /loop이 임시 알람이고, 루틴이 등록된 잡이고, cron + 헤드리스가 전통적 스케줄러라면 — ClaudeOps는 그것들 위에 올라가는 얇은 협업 레이어다.