이슈 하나당 에이전트 하나. 사람은 결과만 리뷰. OpenAI 내부팀 PR 500% 증가. 오픈소스로 공개됐습니다.
[핵심 요약]
→ 출시: 2026년 4월 27일 (OpenAI 오픈소스)
→ 라이센스: Apache 2.0
→ GitHub: github.com/openai/symphony
→ 정체: 이슈 트래커(Linear) → 코딩 에이전트 자동 오케스트레이터
→ 핵심: 이슈 하나 = 에이전트 하나 = 독립 워크스페이스 = PR 하나
→ 효과: OpenAI 내부 팀 PR 3주 만에 500% 증가
→ 구현: Elixir 레퍼런스 구현 포함 (다른 언어 포팅 가능)
→ 주의: Claude Code + GitHub Issues 포트 버전도 이미 등장
→ 한계: 복잡한 판단이 필요한 작업 → 대화형 세션이 여전히 적합
왜 Symphony가 나왔나
기존 코딩 에이전트 사용 방식:
→ 엔지니어가 Codex 세션 열기
→ 태스크 직접 지시
→ 결과 확인 후 다음 태스크 지시
→ 동시에 3~5개 세션이 한계 (컨텍스트 전환 과부하)
→ 에이전트 속도가 빨라져도 사람이 병목
OpenAI가 발견한 문제:
"에이전트를 더 빠르게 만들었더니
이번엔 사람이 세션을 관리하는 게 병목이었다"
Symphony의 해결책:
→ 세션 관리 → 태스크 관리로 전환
→ Linear 이슈 트래커 = 에이전트 컨트롤 플레인
→ 이슈 열리면 → 에이전트 자동 배정
→ 에이전트가 크래시 → 자동 재시작
→ PR 완료 → 사람 리뷰 요청
→ 사람 역할: 태스크 정의 + 결과 리뷰만
[500% PR 증가의 의미]
→ 3주 만에 일부 팀 PR 5배 증가
→ 엔지니어가 더 열심히 일한 게 아님
→ 에이전트가 24시간 이슈 큐를 소화
→ 사람은 리뷰 + 더 복잡한 문제에 집중
주의: "PR 수 = 품질" 아님
→ 검증 부담도 함께 증가
→ 자동화 테스트/가드레일 필수
Symphony 동작 원리
[Symphony 아키텍처]
Linear 이슈 트래커
↓ (주기적 폴링)
Symphony 오케스트레이터
↓ (이슈 상태 확인)
├─ Todo 이슈 발견
│ ↓
│ 독립 워크스페이스 생성
│ ↓
│ 코딩 에이전트 실행 (Codex/Claude Code)
│ ↓
│ CI 모니터링 + 충돌 해결
│ ↓
│ PR 생성 → Linear 상태 변경 (Human Review)
│
├─ 에이전트 크래시 → 자동 재시작
└─ 새 이슈 추가 → 자동 픽업
사람:
→ 이슈 작성 (태스크 정의)
→ PR 리뷰 (결과 검증)
→ 머지 또는 피드백
[이슈 상태 머신]
Todo → In Progress → Human Review → Done
↑ |
└──── 실패 시 재시작 ───┘
Symphony가 관리:
→ Todo 감지 → In Progress 전환
→ PR 생성 → Human Review 전환
→ 크래시 → 다시 In Progress
→ 머지 → Done
실전 1 — 설치 및 환경 설정
# 필요 조건
# - Elixir 1.17+
# - Linear API 키
# - Codex API 키 (또는 다른 에이전트)
# - GitHub 연동
# 레포지토리 클론
git clone https://github.com/openai/symphony
cd symphony
# Elixir 설치 (macOS)
brew install elixir
# 의존성 설치
cd elixir
mix deps.get
# 환경 변수 설정
export LINEAR_API_KEY="lin_api_..." # Linear API 키
export OPENAI_API_KEY="sk-..." # Codex/GPT API 키
export GITHUB_TOKEN="ghp_..." # GitHub 토큰
export LINEAR_TEAM_ID="your-team-id" # Linear 팀 ID
export LINEAR_WORKFLOW_STATE_TODO="..." # Todo 상태 ID
export LINEAR_WORKFLOW_STATE_IN_PROGRESS="..."
export LINEAR_WORKFLOW_STATE_IN_REVIEW="..."
# Symphony 실행
mix run --no-halt
[Linear 설정 (필수)]
1. Linear 워크스페이스 → Settings → API → API Keys 생성
2. Linear 팀 → Settings → Workflow 확인
→ 최소 상태: Todo / In Progress / In Review / Done
3. Linear Settings → Labels → "symphony" 레이블 생성
→ 이 레이블이 붙은 이슈만 Symphony가 픽업
4. GitHub Integration → Linear에서 GitHub 연동
실전 2 — WORKFLOW.md 작성
Symphony의 핵심은 레포지토리 루트의 WORKFLOW.md입니다. 에이전트가 어떻게 일할지 정의합니다.
<!-- WORKFLOW.md (프로젝트 루트) -->
# Symphony Workflow
## 에이전트 행동 지침
### 기본 원칙
- 하나의 이슈 = 하나의 PR
- 변경은 최소화 (이슈 범위만)
- 모든 변경은 테스트 포함
- 커밋 메시지: Conventional Commits 형식
### 코딩 컨벤션
- 언어: TypeScript (strict mode)
- 포맷터: Prettier (자동 실행)
- 린터: ESLint (경고 = 실패)
- 테스트: Jest (커버리지 80%+)
### 작업 순서
1. 이슈 내용 완전히 이해
2. 관련 파일 파악
3. 테스트 먼저 작성 (TDD)
4. 구현
5. 기존 테스트 모두 통과 확인
6. PR 생성 (이슈 번호 포함)
### PR 제목 형식
feat: [이슈 제목] (closes #이슈번호)
### 자동화 불가 판단 기준
다음 상황에서는 PR 대신 코멘트로 사람에게 위임:
- 아키텍처 결정이 필요한 경우
- 이슈 설명이 모호한 경우
- 외부 API 키/비밀이 필요한 경우
- 데이터베이스 마이그레이션이 복잡한 경우
[좋은 WORKFLOW.md 작성 원칙]
→ 구체적으로: 에이전트가 추측하지 않도록
→ 실패 조건 명시: 언제 사람에게 넘길지
→ 테스트 기준: 자동 검증 가능하게
→ 범위 제한: "이슈 범위만" 명시 (무한 확장 방지)
→ 코딩 컨벤션: 린터/포맷터 자동화로 일관성 확보
실전 3 — Linear 이슈 잘 쓰는 법
Symphony는 이슈 내용을 그대로 에이전트에게 전달합니다. 이슈 품질 = 에이전트 품질입니다.
<!-- ❌ 나쁜 이슈 -->
제목: 로그인 버그 수정
내용: 로그인이 안 됨
<!-- ✅ 좋은 이슈 -->
제목: feat: JWT 토큰 만료 후 자동 갱신 구현
## 문제
만료된 JWT 토큰으로 API 호출 시 401 반환되지만
자동 갱신 없이 사용자가 로그아웃됨
## 기대 동작
- 액세스 토큰 만료 시 리프레시 토큰으로 자동 갱신
- 갱신 실패 시 /login 리다이렉트
## 영향 파일
- src/api/client.ts (인터셉터)
- src/auth/token.ts (토큰 관리)
- src/hooks/useAuth.ts
## 완료 기준
- [ ] 401 응답 시 자동 갱신 인터셉터 동작
- [ ] 갱신 실패 시 로그아웃 처리
- [ ] 단위 테스트 추가 (토큰 갱신 성공/실패)
- [ ] 기존 테스트 전부 통과
## 참고
관련 코드: src/api/client.ts:45-67
[Symphony에 적합한 이슈 특성]
✅ 적합:
→ 명확한 완료 기준이 있는 작업
→ 코드베이스 이해로 해결 가능한 버그
→ 패턴 반복 작업 (타입 힌트 추가, 테스트 작성)
→ 문서화, 리팩토링
→ 잘 정의된 신규 기능
❌ 부적합:
→ "더 좋게 만들어줘"
→ 아키텍처 결정이 필요한 작업
→ 외부 서비스 통합 (API 키 필요)
→ 복잡한 DB 마이그레이션
→ UI/UX 주관적 판단이 필요한 작업
실전 4 — Claude Code + GitHub Issues 포트 (Claude Code 사용자용)
OpenAI Symphony가 Codex + Linear 조합이라면, 커뮤니티에서 Claude Code + GitHub Issues 버전을 만들었습니다.
# .github/workflows/symphony-claude.yml
name: Symphony - Claude Code Orchestrator
on:
issues:
types: [labeled] # "symphony" 레이블 추가 시 트리거
jobs:
run-agent:
if: contains(github.event.label.name, 'symphony')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Run Claude Code Agent
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# 이슈 내용 가져오기
ISSUE_BODY="${{ github.event.issue.body }}"
ISSUE_TITLE="${{ github.event.issue.title }}"
ISSUE_NUMBER="${{ github.event.issue.number }}"
# Claude Code로 태스크 실행
claude --no-interactive -p "
다음 GitHub 이슈를 해결해주세요:
제목: $ISSUE_TITLE
내용: $ISSUE_BODY
완료 후:
1. 변경사항 커밋 (feat/fix: $ISSUE_TITLE)
2. PR 생성 (closes #$ISSUE_NUMBER)
3. PR 링크를 이슈 코멘트로 남기기
WORKFLOW.md의 지침을 반드시 따르세요.
"
- name: Comment on failure
if: failure()
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: ${{ github.event.issue.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: '❌ Symphony 에이전트가 이 이슈를 자동 처리할 수 없습니다. 수동 처리가 필요합니다.'
})
# Python으로 구현한 간단한 Symphony 스타일 오케스트레이터
import anthropic
import subprocess
import time
from github import Github # pip install PyGithub
class SimpleSymphony:
"""Symphony 스타일 에이전트 오케스트레이터"""
def __init__(
self,
github_token: str,
repo_name: str, # "owner/repo"
label: str = "symphony",
poll_interval: int = 60 # 초
):
self.gh = Github(github_token)
self.repo = self.gh.get_repo(repo_name)
self.label = label
self.poll_interval = poll_interval
self.active_issues = set()
def run(self):
"""메인 오케스트레이션 루프"""
print(f"Symphony 시작: {self.repo.full_name}")
while True:
try:
self._process_pending_issues()
except Exception as e:
print(f"오케스트레이터 오류: {e}")
time.sleep(self.poll_interval)
def _process_pending_issues(self):
"""대기 중인 이슈 처리"""
issues = self.repo.get_issues(
state="open",
labels=[self.label]
)
for issue in issues:
if issue.number not in self.active_issues:
print(f"새 이슈 발견: #{issue.number} {issue.title}")
self._dispatch_agent(issue)
def _dispatch_agent(self, issue):
"""이슈에 에이전트 배정"""
self.active_issues.add(issue.number)
# 이슈 코멘트로 시작 알림
issue.create_comment("🤖 Symphony 에이전트가 작업을 시작합니다...")
try:
# 독립 워크스페이스 생성 (새 브랜치)
branch_name = f"symphony/issue-{issue.number}"
prompt = f"""
GitHub 이슈를 해결해주세요:
제목: {issue.title}
내용:
{issue.body}
작업 지침:
1. '{branch_name}' 브랜치에서 작업
2. WORKFLOW.md 지침 준수
3. 모든 테스트 통과 확인
4. PR 생성 (closes #{issue.number})
"""
# Claude Code 실행
result = subprocess.run(
["claude", "--no-interactive", "-p", prompt],
capture_output=True,
text=True,
cwd="."
)
if result.returncode == 0:
issue.create_comment("✅ PR 생성 완료. 리뷰를 요청합니다.")
else:
issue.create_comment(
f"❌ 자동 처리 실패. 수동 처리가 필요합니다.\n"
f"오류: {result.stderr[:500]}"
)
self.active_issues.discard(issue.number)
except Exception as e:
issue.create_comment(f"❌ 에러: {str(e)}")
self.active_issues.discard(issue.number)
실전 5 — 코드베이스 Symphony 준비 체크리스트
Symphony가 효과적으로 작동하려면 코드베이스가 에이전트 친화적이어야 합니다.
[에이전트 친화적 코드베이스 체크리스트]
✅ 자동화 테스트
□ 단위 테스트 커버리지 70%+
□ 테스트 실행: 한 줄 명령 (npm test / pytest)
□ CI 파이프라인: PR 시 자동 실행
□ 실패 시 명확한 에러 메시지
✅ 코드 품질 자동화
□ 린터: 자동 실행 + 실패 시 PR 차단
□ 포맷터: 자동 적용 (Prettier/Black)
□ 타입 체커: TypeScript/mypy
□ pre-commit 훅 설정
✅ 명확한 구조
□ 파일/폴더 명명 규칙 문서화
□ 새 기능 추가 위치 명확 (어디에 뭘 놓는지)
□ 의존성 관리 명확 (package.json / requirements.txt)
✅ WORKFLOW.md
□ 코딩 컨벤션 명시
□ 완료 기준 (어떻게 하면 done인지)
□ 자동화 불가 판단 기준
□ PR 형식 규칙
✅ 이슈 템플릿 (.github/ISSUE_TEMPLATE/)
□ symphony용 이슈 템플릿 생성
□ 완료 기준 체크리스트 포함
□ 영향 파일 섹션 포함
Symphony vs 기존 방식 비교
기존 대화형 에이전트 Symphony
작업 방식: 세션 단위 이슈 단위
사람 역할: 매 단계 지시 태스크 정의 + 결과 리뷰
병렬 처리: 3~5개 세션 한계 이슈 수만큼 병렬
에이전트 복구: 수동 재시작 자동 재시작
상태 추적: 세션 내부 이슈 트래커 (가시적)
적합한 작업: 복잡한 판단 필요 명확히 정의된 태스크
비용: 세션당 이슈당 (토큰 많이 씀)
[Symphony 실전 사용 팁]
→ 이슈를 작게 쪼개라: 큰 이슈는 에이전트가 방황
→ WORKFLOW.md에 실패 기준 명시: 언제 멈출지 알아야 함
→ 자동 테스트 먼저: 테스트 없으면 에이전트 검증 불가
→ 비용 모니터링: 연속 실행은 토큰 많이 씀 (Dan McAteer: "주당 수십 이슈")
→ 처음엔 소규모로: 3~5개 이슈로 시작해서 패턴 확인 후 확장
마무리
✅ Symphony 도입해야 할 때
→ 코딩 에이전트를 이미 쓰고 있고 세션 관리가 병목일 때
→ 잘 정의된 반복 태스크가 많을 때 (버그 수정, 테스트 추가)
→ 자동화 테스트 커버리지가 충분한 코드베이스
→ Linear 사용 팀 (다른 트래커는 포팅 필요)
→ 24시간 에이전트 큐 소화가 필요한 팀
❌ 아직 이른 경우
→ 자동화 테스트가 부족한 코드베이스 (에이전트 검증 불가)
→ 이슈 품질이 낮은 팀 (모호한 이슈 = 모호한 PR)
→ 아키텍처 결정이 많은 초기 단계 프로젝트
→ Elixir 낯선 팀 (레퍼런스 구현 기반, 포팅 필요)
→ 토큰 비용 민감한 소규모 팀
관련 글:
https://cell-devlog.tistory.com/89
Claude Code Agent Teams 실전 가이드 — 병렬 에이전트 설정부터 실전 시나리오까지
2026년 2월, Claude Opus 4.6과 함께 Agent Teams가 출시됐어요.기존:Claude Code 1개 → 순서대로 처리API 레이어 → DB 레이어 → 테스트 → 문서화(순차 실행)Agent Teams:Claude Code 여러 개 → 동시에 처리Agent 1: A
cell-devlog.tistory.com
https://cell-devlog.tistory.com/25
AI 에이전트 오케스트레이션 패턴 3가지 — Pipeline, Supervisor, Swarm 실전 비교
여러 에이전트를 만들고 나면 이런 고민이 생겨요."에이전트들을 어떻게 연결하지? 누가 누구한테 일을 시키고, 결과는 어떻게 모으지?"이게 오케스트레이션 패턴 선택의 문제예요. 패턴을 잘못
cell-devlog.tistory.com
'AI Development' 카테고리의 다른 글
| OpenAI × AWS 완전 분석 — GPT-5.5, Codex, Managed Agents가 Amazon Bedrock에 상륙한 이유 (0) | 2026.05.06 |
|---|---|
| OpenAI 저지연 음성 AI 인프라 완전 분석 — WebRTC 아키텍처를 뜯어고친 이유와 개발자 적용 가이드 (0) | 2026.05.06 |
| OpenCode 완전 가이드 — 자체 API 키로 Claude Code 대신 쓰는 오픈소스 터미널 에이전트 (0) | 2026.05.06 |
| Cursor Rules 완전 가이드 — .cursorrules 잘 쓰는 법 (1) | 2026.04.30 |
| Google Stitch vs Claude Design — AI 디자인 툴 2파전, 뭘 써야 하나 (0) | 2026.04.28 |