Cursor 클라우드 에이전트 병렬 작업의 브랜치·PR 충돌 관리: 같은 기준점 시작, 겹침 검사, 머지 순서

API로 여러 에이전트를 같은 커밋에서 출발시키고, 머지 전에 겹치는 파일과 실제 충돌을 찾아 정리하는 절차

Cursor 에이전트 병렬 PR 충돌 관리 썸네일

핵심 요약

  1. API로 시작할 때 repos[].startingRef에 같은 40자리 SHA를 넣으면 모든 에이전트가 같은 커밋에서 출발한다.
  2. workOnCurrentBranch가 false(기본)면 새 cursor/... 브랜치에 푸시되며, 요청에서 브랜치 이름을 정하는 필드는 없으므로 name으로 작업을 추적한다.
  3. gh pr diff --name-only로 PR끼리 겹치는 파일을 먼저 찾고, git merge-tree --write-tree(Git 2.38 이상)로 실제 충돌 여부를 체크아웃 없이 확인한다.
  4. PR을 하나 머지할 때마다 남은 브랜치의 merge-tree 검사를 다시 돌리고, 공용 파일을 고친 PR부터 머지한다.
  5. 충돌 정리는 POST /v1/agents/{id}/runs 후속 지시로 맡길 수 있고, 실행 중이면 409 agent_busy가 돌아온다.

Cursor 클라우드 에이전트(이전 이름 백그라운드 에이전트)에 작업을 여러 개 동시에 맡기면, 각 에이전트는 따로 브랜치를 만들어 결과를 올린다. 문제는 그 브랜치들이 같은 파일을 고쳐 PR을 합칠 때 충돌이 나는 경우다. 이 글은 에이전트를 같은 기준 커밋에서 출발시키는 방법, 머지 전에 PR끼리 겹치는 파일과 실제 충돌을 찾는 스크립트, 충돌이 난 PR을 에이전트에게 다시 맡기는 순서를 다룬다.

클라우드 에이전트가 브랜치와 PR을 만드는 방식

Cursor Cloud Agents 문서에 따르면 클라우드 에이전트는 클라우드의 격리된 VM에서 저장소를 클론하고, 별도 브랜치에서 작업한 뒤 변경을 푸시한다. 시작 경로는 데스크톱 앱의 에이전트 입력창에서 Cloud 선택, cursor.com/agents 웹, Slack·Linear의 @cursor, GitHub·Bitbucket PR이나 이슈 댓글의 @cursor, 그리고 API다. 문서는 병렬로 돌릴 수 있는 에이전트 수에 숫자 제한을 적어 두지 않았다. 그래서 몇 개를 동시에 돌릴지는 도구가 아니라 팀이 정해야 한다. 이용 가능 플랜은 Premium 이상, Teams, Enterprise, 이전 유료 플랜이다. 처음 쓸 때 지출 한도(spend limit)를 정하라는 안내가 나온다.

에이전트를 어디서 출발시킬지는 두 곳에서 정한다. 팀 설정의 Base branch는 설정 문서에 따르면 에이전트가 PR을 만들 때 갈라져 나오는 브랜치다. 비워 두면 저장소 기본 브랜치를 쓴다. API로 시작하면 요청마다 시작 지점을 지정할 수 있다. 병렬 작업에서 의미가 있는 POST /v1/agents 필드는 API 엔드포인트 문서 기준으로 아래와 같다.

필드문서상 동작병렬 작업에서 정할 것
repos[].startingRef브랜치 이름 또는 40자리 커밋 SHA모든 에이전트에 같은 SHA를 넣어 기준점을 고정
workOnCurrentBranch기본 false, 이때 새 cursor/... 브랜치에 푸시병렬이면 false 유지. 브랜치 이름을 지정하는 필드는 없음
autoCreatePR실행이 끝나면 PR 생성겹침 검사를 PR 단위로 하려면 true
agentIdbc-<uuid> 형식, 생성 요청을 멱등으로 만듦스크립트가 재시도해도 같은 작업이 두 번 생기지 않게 미리 생성
name최대 100자작업 목록과 대조할 식별자
modeagent(기본) 또는 plan수정 범위가 불분명한 작업은 plan으로 먼저 계획만 받기

브랜치 이름을 요청에서 정할 수 없으므로, 어떤 PR이 어떤 작업인지는 name과 PR 제목으로 추적한다. 기준점을 브랜치 이름(main) 대신 SHA로 주는 이유는, 에이전트들이 시작되는 사이에 main이 움직이면 각자 다른 커밋에서 출발하기 때문이다. 같은 SHA에서 출발해야 나중에 겹침 검사 결과를 해석하기 쉽다.

동시에 맡길 작업을 파일 경계로 고르기

충돌은 대부분 여러 작업이 같은 공용 파일을 건드릴 때 생긴다. 작업을 나누기 전에 다음 기준으로 병렬 대상과 순차 대상을 가른다.

  • 프롬프트에 수정해도 되는 디렉터리를 적는다(예: "src/features/search/ 밖의 파일은 수정하지 마").
  • 라우터 테이블, 공용 타입 정의, 디자인 토큰처럼 여러 기능이 함께 고치는 파일의 변경은 별도 작업으로 빼서 먼저 머지한다.
  • package-lock.json·pnpm-lock.yaml 같은 잠금 파일과 코드 생성 산출물은 한 작업만 바꾸게 한다. 의존성 추가가 필요한 작업이 둘 이상이면 순차로 돌린다.
  • DB 마이그레이션처럼 적용 순서가 결과를 바꾸는 작업은 병렬 대상에서 뺀다.

이 기준은 프롬프트에 적는 약속일 뿐이고, 에이전트가 지켰는지는 아래 검사로 확인한다. 로컬에서 여러 에이전트를 돌릴 때의 격리 방법은 Git Worktree로 AI 에이전트 작업을 격리하는 방법에서 따로 다룬다.

API로 같은 기준점에서 에이전트 여러 개 시작하기

  1. Cursor Dashboard의 API Keys에서 키를 만들어 CURSOR_API_KEY 환경 변수에 넣는다. 문서상 인증은 키를 사용자 이름으로 쓰고 비밀번호를 비운 Basic 인증이다.
  2. 작업 목록 파일을 만든다. 한 줄에 이름|프롬프트 형식으로 쓰고, 프롬프트에는 수정 허용 디렉터리를 넣는다.
  3. 기준 SHA를 한 번 계산해 모든 요청에 같은 값을 넣고, agentId를 스크립트에서 만들어 agents.txt에 기록한다.
#!/usr/bin/env bash
# tasks.txt 예시:
# search-filter|src/features/search/ 안에서만 수정해서 검색 필터에 날짜 범위를 추가해 줘
# login-expiry|src/features/auth/ 안에서만 수정해서 세션 만료 시 로그인 페이지로 보내 줘
set -euo pipefail
REPO="https://github.com/your-org/your-repo"
git fetch origin main
BASE_SHA=$(git rev-parse origin/main)   # 40자리 SHA

while IFS='|' read -r name prompt; do
  id="bc-$(uuidgen | tr 'A-Z' 'a-z')"
  printf '%s\t%s\n' "$id" "$name" >> agents.txt
  jq -n --arg id "$id" --arg name "$name" --arg text "$prompt" \
        --arg repo "$REPO" --arg ref "$BASE_SHA" '{
    agentId: $id,
    name: $name,
    prompt: { text: $text },
    repos: [ { url: $repo, startingRef: $ref } ],
    autoCreatePR: true
  }' | curl -sS -u "$CURSOR_API_KEY:" \
         -H 'Content-Type: application/json' \
         --data @- https://api.cursor.com/v1/agents
  echo
done < tasks.txt

진행 상태는 GET /v1/agents/{id}로 본다. 문서에 따르면 에이전트 응답에는 ACTIVE·IDLE·ARCHIVED 상태와 latestRunId가 있고, 실제 진행 상황은 실행(run) 단위로 GET /v1/agents/{id}/runs/{runId}를 조회해야 한다. 실행 상태는 CREATING, RUNNING, FINISHED, ERROR, CANCELLED, EXPIRED 등으로 나뉜다. 모든 실행이 FINISHED가 된 뒤에 다음 검사로 넘어간다.

while IFS=$'\t' read -r id name; do
  echo "== $name"
  curl -sS -u "$CURSOR_API_KEY:" "https://api.cursor.com/v1/agents/$id"
  echo
done < agents.txt

에이전트가 쓰는 의존성 설치·시크릿 같은 실행 환경은 모든 병렬 작업에 공통이다. 문서는 실행 중인 에이전트가 새로 추가한 시크릿을 읽지 않는다고 적고 있으므로, 시크릿을 바꿨다면 에이전트를 새로 시작해야 한다. 환경을 코드로 맞추는 방법은 클라우드 코딩 에이전트 실행 환경 만들기를 참고한다.

머지 전에 PR끼리 겹치는 파일 찾기

에이전트가 만든 PR이 모이면, 머지 순서를 정하기 전에 PR끼리 수정 파일이 겹치는지부터 본다. gh pr diff의 --name-only 옵션은 변경된 파일 이름만 출력한다. 아래 스크립트는 cursor/로 시작하는 브랜치의 열린 PR을 모아 두 개씩 비교한다.

#!/usr/bin/env bash
set -euo pipefail
prs=$(gh pr list --state open --json number,headRefName \
  --jq '.[] | select(.headRefName | startswith("cursor/")) | .number')
tmp=$(mktemp -d)
for n in $prs; do
  gh pr diff "$n" --name-only | sort > "$tmp/$n"
done
for a in $prs; do
  for b in $prs; do
    [ "$a" -lt "$b" ] || continue
    common=$(comm -12 "$tmp/$a" "$tmp/$b")
    if [ -n "$common" ]; then
      printf '#%s <-> #%s\n%s\n\n' "$a" "$b" "$common"
    fi
  done
done

출력이 비어 있으면 PR들이 서로 다른 파일만 고쳤다는 뜻이다. 겹치는 파일이 나오면 그 파일이 앞에서 정한 공용 파일인지 확인한다. 공용 파일이라면 프롬프트의 수정 범위가 지켜지지 않은 것이므로, 해당 PR을 리뷰할 때 그 부분을 먼저 본다.

실제 충돌 여부를 체크아웃 없이 확인하기

같은 파일을 고쳤다고 해서 항상 충돌하는 것은 아니다. 서로 다른 줄을 고쳤다면 Git이 자동으로 합친다. 실제 충돌은 git merge-tree의 --write-tree 모드로 확인할 수 있다. 문서에 따르면 이 모드는 작업 트리와 인덱스를 건드리지 않고 병합 결과를 계산한다. 충돌이 없으면 종료 코드 0, 충돌이 있으면 1, 병합 자체를 못 하면 그 밖의 값을 돌려준다. --name-only를 붙이면 충돌 파일 이름만 나온다. 이 모드는 Git 2.38부터 쓸 수 있으므로 git --version을 먼저 확인한다.

git fetch origin
for br in $(git branch -r --list 'origin/cursor/*'); do
  if out=$(git merge-tree --write-tree --name-only origin/main "$br"); then
    echo "OK        $br"
  else
    echo "CONFLICT  $br"
    echo "$out" | sed -n '2,/^$/p'   # 첫 줄(트리 ID) 다음부터 빈 줄까지가 충돌 파일
  fi
done

PR 하나를 머지하면 origin/main이 바뀌므로, 남은 브랜치에 대해 이 검사를 다시 돌린다. 머지 순서는 공용 파일을 고친 PR, 다른 PR이 의존하는 PR, 변경이 작은 PR 순으로 정한다. 그러면 뒤에 오는 PR이 앞선 변경 위에서 한 번만 정리하면 된다. 큰 변경을 리뷰 단위로 쪼개는 방법은 큰 AI 생성 PR을 스택 PR로 나누기에서 다룬다.

충돌이 난 PR을 에이전트에게 다시 맡기기

충돌한 브랜치를 사람이 직접 고칠 수도 있지만, 그 PR을 만든 에이전트에게 후속 지시를 보내 같은 브랜치에서 정리하게 할 수도 있다. 후속 지시는 POST /v1/agents/{id}/runs로 보낸다. 문서에 따르면 이미 실행 중인 run이 있을 때 이 요청을 보내면 409 agent_busy가 돌아온다. 진행 중인 실행에 지시를 덧붙이려면 delivery를 "steer"로 지정한다.

curl -sS -u "$CURSOR_API_KEY:" \
  -H 'Content-Type: application/json' \
  --data '{"prompt":{"text":"origin/main 최신 커밋 위로 이 브랜치를 리베이스하고 src/app/routes.ts 충돌을 해결한 뒤 테스트를 다시 실행하고 같은 브랜치에 푸시해 줘. routes.ts에서는 이 작업의 경로 한 줄만 추가하고 다른 줄은 바꾸지 마."}}' \
  "https://api.cursor.com/v1/agents/$AGENT_ID/runs"

지시에는 충돌 파일 이름과 남겨야 할 변경 범위를 함께 적는다. "충돌 해결해 줘"만 보내면 에이전트가 앞서 머지된 변경을 되돌리는 쪽으로 정리할 수도 있다. 다시 푸시된 뒤에는 위의 merge-tree 검사를 한 번 더 돌린다. 팀원이 만든 에이전트에 후속 지시를 보내려면 관리자가 Team follow-ups 설정을 켜 두어야 한다. 관리자가 켜기 전에는 에이전트를 만든 사람만 지시를 보낼 수 있고, 값은 Disabled·Service accounts only·All 중에서 고른다.

병렬 실행을 늘리기 전에 저장소에 남겨 둘 것

  • 병렬 작업 목록과 각 작업의 수정 허용 디렉터리를 tasks.txt 같은 파일로 저장소 안에 기록해 리뷰어가 볼 수 있게 한다.
  • 겹침 검사와 merge-tree 검사 스크립트를 scripts/에 두고, 머지 담당자가 PR을 합칠 때마다 실행한다.
  • 저장소 단위 훅이 필요하면 .cursor/hooks.json에 둔다. 문서에 따르면 클라우드 에이전트는 저장소의 명령형 훅을 실행하지만 사용자 홈의 ~/.cursor/hooks.json은 실행하지 않는다.

사내 네트워크나 자체 머신에서 에이전트 도구를 실행해야 하는 조직이라면 Cursor 클라우드 에이전트를 사내 머신에서 실행하기에서 워커 등록 절차를 이어서 확인한다.

초보자가 자주 실수하는 포인트

  • startingRef에 main 같은 브랜치 이름만 넣어, 에이전트가 시작되는 사이 main이 바뀌면서 서로 다른 커밋에서 출발하는 경우
  • 잠금 파일이나 공용 라우터 파일을 여러 작업이 동시에 고치게 둬서 거의 모든 PR이 같은 파일에서 충돌하는 경우
  • PR 하나를 머지한 뒤 남은 브랜치의 충돌 검사를 다시 하지 않아, 앞선 머지로 새로 생긴 충돌을 놓치는 경우
  • 후속 지시에 "충돌 해결해 줘"만 적어 에이전트가 이미 머지된 변경을 되돌리는 방향으로 정리하는 경우

체크리스트

  • 병렬로 돌릴 작업마다 수정 허용 디렉터리를 프롬프트에 적었는가
  • 모든 생성 요청의 startingRef가 같은 SHA인가
  • 잠금 파일·마이그레이션을 바꾸는 작업을 순차로 돌리도록 뺐는가
  • git --version이 2.38 이상이라 merge-tree --write-tree를 쓸 수 있는가
  • 머지할 때마다 남은 cursor/ 브랜치에 merge-tree 검사를 다시 실행하는가
  • 팀원 에이전트에 후속 지시를 보내야 한다면 Team follow-ups 설정을 확인했는가

자주 묻는 질문

에이전트가 만든 브랜치 이름을 feat/ 같은 팀 규칙으로 바꿀 수 있나요?

API 문서 기준으로 생성 요청에는 브랜치 이름 필드가 없고, workOnCurrentBranch가 false면 cursor/로 시작하는 새 브랜치에 푸시된다. 팀 규칙 이름이 필요하면 PR이 만들어진 뒤 사람이 브랜치를 옮기거나, PR 제목과 라벨로 분류하는 방식을 쓴다.

이미 열려 있는 사람의 PR 위에서 에이전트를 시작할 수 있나요?

API의 repos[].prUrl에 PR 주소를 넣으면 그 PR을 기준으로 시작하며, 이때 startingRef는 무시된다. 같은 PR에 여러 에이전트를 붙이면 같은 파일을 고칠 가능성이 높으므로 한 번에 하나만 붙이는 것이 충돌 관리에 유리하다.

참고 자료 · 검증 기준

위 자료와 내용을 대조한 날짜: . 도구·서비스 정책은 이후 바뀔 수 있으므로 적용 전 공식 문서를 다시 확인하세요.

이 글은 실제 실무 환경 테스트 및 검증된 기술 자료를 바탕으로 작성되었으며, 환경 변화에 따라 지속적으로 갱신됩니다.