AI

맥북 한 대로 AI 개발팀 굴리기 (1) — 설계와 작업 흐름

mingoon.com 2026. 10. 28. 11:09
반응형

시리즈: 멀티 에이전트 하네스 구축기
1편: 설계와 작업 흐름 (이 글)
2편: 사용량 관리와 모델 배치
3편: Agent Office와 삽질 모음

 

약 2주 동안 집에 있는 M4 맥북에 "AI 개발팀"을 하나 꾸렸다. 텔레그램으로 일을 던지면 에이전트들이 나눠서 개발하고, 서로 리뷰하고, 결과를 보고한다. 그 과정은 픽셀 사무실 화면으로 지켜본다.

처음에는 "여러 LLM을 묶어서 일을 시켜 보자" 정도의 가벼운 생각이었다. 그런데 쓰다 보니 사용량 관리, 작업 격리, 리뷰, 원격 조작, 모니터링까지 하나씩 붙었다. 지금은 하네스 저장소 커밋만 50개가 넘고, 파이썬과 HTML 코드가 7천 줄쯤 된다.

글이 길어져서 세 편으로 나눴다. 1편에서는 무엇을 왜 이렇게 만들었는지, 작업 하나가 어떻게 흘러가는지를 정리한다.


1. 무엇을 만들고 싶었나

처음에 세운 요구사항은 이렇다.

  • Codex(ChatGPT 구독)를 주력으로 쓰고, 무료 LLM을 섞는다. 로컬 LLM은 돌리지 않는다. 노트북 한 대에서 모델까지 돌리면 정작 다른 일을 할 수가 없다.
  • LLM별 사용량이 차면 자동으로 다른 LLM으로 넘긴다. 사람이 손으로 모델을 바꾸지 않는다.
  • 에이전트끼리 서로 검증하고 보완한다. 구현한 모델과 다른 계열의 모델이 리뷰한다.
  • Docker는 쓰지 않는다. 맥에 바로 설치해서 가볍게 돌린다.
  • Claude는 하네스에서 쓰지 않는다. 구독 로그인 정보를 서드파티 도구에 넣지 않기로 했다.

여기에 실제로 쓰면서 두 가지가 더 붙었다.

  • 밖에서도 일을 시키고 결과를 받아야 한다 → 텔레그램 봇
  • 에이전트들이 지금 뭘 하는지 한눈에 보고 싶다 → Agent Office(픽셀 사무실 대시보드)

2. 도구 고르기: LiteLLM은 빼고 OmO로

처음 계획은 OpenCode + LiteLLM이었다. LiteLLM 프록시를 앞에 두고 모델 라우팅과 폴백을 맡길 생각이었다.

그런데 oh-my-openagent(OmO, 예전 이름 oh-my-opencode) 를 보고 방향을 바꿨다. OmO는 OpenCode 플러그인이다. 역할이 정해진 에이전트 팀을 통째로 넣어 준다.

  • sisyphus: 팀장. 일을 받아 쪼개서 맡긴다.
  • prometheus · metis · momus: 계획을 세우고, 빈틈을 찾고, 비판한다.
  • atlas · sisyphus-junior · hephaestus: 계획을 실행하고 코드를 짠다.
  • oracle · explore · librarian: 설계 자문, 코드 검색, 문서 조사를 맡는다.

에이전트마다 모델 순서(폴백 체인)를 지정할 수 있다. 429나 5xx가 나면 다음 모델로 자동으로 넘어간다. 이러면 LiteLLM이 할 일이 거의 없다. 그래서 LiteLLM은 빼고, 무료 provider를 OpenCode에 직접 연결했다.

참고로 여러 에이전트를 worktree별로 나란히 띄우는 데스크톱 앱 Orca도 비교해 봤다. Orca는 사람이 결과를 비교하는 "바깥 작업 공간"이다. OmO는 AI가 알아서 분업하고 검증하는 "안쪽 오케스트레이션"이다. 층이 달라서 대체재가 아니었다. 자동 교차 검증과 모델 라우팅이 핵심인 내 요구사항에는 OmO가 맞았다.

3. 무료 LLM 고르기: "에이전트로 쓸 수 있는가"를 직접 잰다

무료 모델은 많지만, 에이전트로 쓸 수 있는 모델은 생각보다 적다. 그래서 free_llm_check.py라는 검사 스크립트를 만들었다. 모델마다 세 가지를 본다.

  1. basic: 짧은 질문에 10초 안에 답하는가
  2. tools: 도구 호출(function calling)을 하는가. 에이전트로 쓰려면 필수다.
  3. heavy: 5만 토큰짜리 입력을 받아 주는가. OmO는 요청마다 시스템 프롬프트와 도구 정의로 약 5만 토큰을 보낸다. 이걸 못 받으면 아무리 똑똑해도 쓸 수 없다.

NVIDIA, Google(Gemini), OpenRouter, Groq를 돌려 보고, 세 단계를 통과한 모델만 OmO 설정에 넣었다. 검색이나 잡무 같은 가벼운 역할은 NVIDIA Nemotron Lightning이나 Gemini Flash Lite가 맡게 했다.

무료 LLM 검사 결과 — 99개 중 8개만 에이전트로 쓸 수 있었다

4. 전체 구조

하네스 전체 구조

전부 tmux 세션 하나(harness) 안에서 창(opencode, dispatch, office)으로 돈다. launchd가 5분마다 상태를 확인하면서 프로필 전환과 원격 재시작 요청을 처리한다.

작업 하나가 흘러가는 순서

작업 하나가 흘러가는 순서

  1. 텔레그램으로 "버튼 다 없애고 지정된 URL 이미지만 보여줘"라고 보낸다. 음성 메시지도 된다. STT로 받아 적는다.
  2. 봇이 tasks/inbox/에 작업 파일을 만든다.
  3. 디스패처가 작업을 집어서, 해당 레포에 작업 전용 git worktree와 agent/<작업ID> 브랜치를 만든다. 작업끼리 서로의 파일을 건드릴 일이 없다.
  4. OpenCode 세션을 열고 지시를 보낸다. 지시에는 하네스 규칙이 붙는다. "구현이 끝나면 cross-reviewer에게 git diff main...HEAD 리뷰를 받아라", "마지막 줄에 STATUS를 적어라" 같은 것들이다.
  5. 끝나면 결과를 텔레그램으로 보낸다. 사람이 🔀 합치기를 눌러야 main에 들어간다.
  6. push는 사람만 한다. 에이전트는 push 명령이 막혀 있다.

작업 기록 패널 — 완료 보고(STATUS·증거)와 텔레그램에서 누른 합치기 버튼까지 시간순으로 남는다

"말만 하고 멈추는" 에이전트 잡기

LLM 에이전트는 "이제 테스트를 실행하겠습니다"라고 말해 놓고 그냥 멈추는 일이 잦다. 그래서 완료 판정을 깐깐하게 했다.

  • 최종 보고에 STATUS: 줄이 없으면 완료로 치지 않는다. 한 번 "말로만 하지 말고 실제로 실행해서 끝내라"고 다시 보낸다.
  • 그래도 없으면 ⚠️ 멈춤으로 알리고, ▶ 계속 진행 버튼을 준다.
  • 이번 실행에서 실제로 생긴 커밋, 바뀐 파일, 캡처를 "증거" 줄로 함께 보여 준다. 말과 실제가 다르면 바로 보인다.

완료 판정 흐름 — STATUS 줄이 없으면 완료로 치지 않는다

5. 텔레그램 봇: 밖에서도 일 시키기

자주 쓰는 명령은 이 정도다.

명령 하는 일
/new 레포 [codex] 새 레포 만들기. codex를 붙이면 개인 데이터용(허용 모델 제한) 템플릿
/clone URL GitHub 레포 가져오기 (빈 저장소면 초기 커밋을 만들어 줌)
/status 진행 중·대기·질문·완료 목록 (레포·제목 함께)
/pending 안 합친 브랜치, 커밋 안 한 변경, push 안 한 커밋
/restart office·dispatch·opencode 원격 재시작 (launchd가 처리)
/office flow 사무실 업무 흐름도를 캡처해서 보내기

 

자잘하지만 효과가 컸던 것들도 있다.

  • 실행형 버튼은 한 번 누르면 사라진다. 합치기를 두 번 눌러 사고 나는 일을 막는다.
  • 알림에 답장하면 그대로 추가 지시가 된다. 같은 세션에서 이어서 일한다.
  • 같은 브랜치에서 다른 작업이 아직 돌고 있으면 합치기를 거절한다.

6. 개인 데이터가 든 레포 지키기

여행 기록 앱처럼 실제 위치 정보가 들어가는 레포는 따로 다룬다.

  • 레포 자체 opencode.jsonc에서 허용 provider를 OpenAI와 Go DeepSeek(ZDR 모델 2개)로 좁힌다. 무료 모델이나 학습에 데이터를 쓰는 모델은 아예 못 고른다.
  • 결과 캡처 같은 미디어를 텔레그램으로 자동 전송하지 않는다. 사람이 버튼을 눌렀을 때만 보낸다.
  • .env 파일은 에이전트가 읽지 못하게 막았다. 작업 폴더 밖 경로 접근(external_directory)도 기본 거부다.

여기까지가 뼈대다. 다음 편에서는 이 하네스에서 가장 많이 갈아엎은 부분, 사용량 관리와 모델 배치를 다룬다. Codex 5시간 한도가 재시도 세 번에 증발한 사건부터 시작한다.

 

다음 글: (2) 사용량 관리와 모델 배치

 

 

※ 이 글은 AI의 도움을 받아 작성했고, 작성자가 내용을 직접 검토한 뒤 올렸다.