핵심 요약: AI 에이전트로 실패한 CI를 수정하려면, CI 실패 이벤트를 웹훅으로 전송하고, 코딩 에이전트가 처리 가능한 문제인지 확인한 뒤 깨끗한 워크트리(worktree)에서 로컬로 재현하여 브랜치에 드래프트 풀 리퀘스트(Draft PR)로 푸시하도록 구성합니다. 이후 사람이 직접 검토하고 병합(merge)합니다. 로컬에서 재현되지 않는다면 절대 푸시하지 않습니다.
오후 4시에 발생한 빌드 실패(red build)는 단순히 문제를 수정하는 것 이상의 비용을 초래합니다. 하던 일을 멈추고, 로그를 열고, 900줄에 달하는 빌드 설정 출력을 스크롤한 끝에 린트(lint) 오류나 만료된 스냅샷 문제를 찾아냅니다. 수정 자체는 2분이면 끝나지만, 컨텍스트 스위칭(맥락 전환)에는 20분이 걸립니다.
바로 이 간극에서 코딩 에이전트가 제 몫을 톡톡히 해냅니다. 이미 로컬 환경에서 Claude Code, Codex 또는 다른 에이전트를 사용하고 계실 것입니다. 여기서 빠진 퍼즐 조각은 바로 '연결 파이프라인(wiring)'입니다. 즉, 실패를 감지하고, 적절한 컨텍스트와 함께 에이전트에 전달하며, 에이전트가 어림짐작으로 만든 코드를 저장소에 함부로 푸시하지 못하도록 방지하는 장치입니다. 이 가이드에서는 GitHub Actions와 Sharkly 자동화(Automation)를 활용해 이 연결 파이프라인을 구축하는 방법을 다룹니다. 동일한 구조는 HTTP 요청을 보낼 수 있는 모든 CI 시스템에 적용할 수 있습니다.
AI 에이전트가 잘 해결하는 CI 문제와 그렇지 못한 문제
에이전트는 로컬 노트북 환경에서 재현 가능하고 검증하기 쉬운 작은 규모의 오류를 가장 잘 해결합니다. 반면 인프라, 자격 증명(인증), 외부 서비스와 관련된 오류에는 취약합니다. 따라서 자동화하기 전에 먼저 문제 유형을 분류해야 합니다.
| 실패 유형 | 에이전트 적합도 | 이유 |
|---|---|---|
| 린트 및 포맷 오류 | 매우 적합 | 결정론적이며, 린터가 수정 여부를 명확히 검증함 |
| 타입 오류 | 매우 적합 | 컴파일러가 수정 여부를 명확히 검증함 |
| 의도적인 UI 변경 후 깨진 스냅샷 | 적합 | 재현하기 쉽지만, 의도된 변경인지 사람이 확인해야 함 |
| 플래키 테스트 (간헐적 실패 테스트) | 보통 | 재현을 위해 반복 실행이 필요하며, 수정 대상이 실제 레이스 컨디션(경쟁 상태)인 경우가 많음 |
| 로직 변경 후 실패하는 단위 테스트 | 보통 | 테스트가 맞고 코드가 틀렸을 가능성이 있음 |
| 러너(Runner) 디스크 공간 부족, 네트워크 타임아웃 | 부적합 | 저장소 코드 레벨에서 수정할 것이 없음 |
| 누락되거나 만료된 시크릿, 권한 오류 | 적용 불가 | 에이전트가 자격 증명에 접근해서는 안 됨 |
이 표에서 도출할 수 있는 핵심 원칙은 다음과 같습니다. 에이전트는 자체 Computer 환경에서 실패(red)를 확인한 후 성공(green)으로 바뀌는 것을 직접 검증한 수정 사항만 제출해야 한다는 것입니다. DeepSeek Harness 팀이 X에 게시한 설계 에세이에서는 이 패턴을 '조용히 재현하고 수정하기(silently reproduce and fix)'라고 부릅니다. 트리거가 이벤트를 모니터링하면서 기본적으로는 조용히 대기하다가, 검증된 단순 수정 사항만 드러내는 방식입니다. 해당 에세이는 출시된 제품이 아닌 프로토타입 설계를 설명한 것이지만, 직접 시스템을 구축할 때도 이 원칙은 유효합니다.
CI 수정 루프의 작동 원리
이 루프는 실패 이벤트, 서명된 웹훅, 저비용 필터, 격리된 재현, 사람의 검토 게이트라는 다섯 가지 요소로 구성됩니다.

- CI 실행이 실패로 끝납니다.
- 간단한 워크플로가 서명된 JSON 바디를 웹훅 URL로 전송합니다.
- 에이전트가 요청 바디를 확인하고 대상이 아닌 저장소나 릴리스 브랜치의 실패 등 작업 범위를 벗어난 이벤트를 걸러냅니다.
- 에이전트가 태스크를 등록하고, 새로운 워크트리를 체크아웃한 뒤, 오류를 재현하고 수정합니다.
- 브랜치에 푸시하고 드래프트 풀 리퀘스트를 생성합니다. 담당자가 이를 확인하고 병합하거나 닫습니다.
3단계와 4단계는 Sharkly 자동화(Automation)로 실행됩니다. Automation은 저장된 지침(Instructions) 세트와 이를 실행하는 Agent 또는 Crew의 조합으로, 스케줄, 태스크 상태 변경, 특정 댓글 문구, 웹훅 등의 트리거로 시작됩니다.
1단계: CI 실패 이벤트를 웹훅으로 전송하기
GitHub Actions에는 다른 워크플로가 완료되었을 때 실행되는 workflow_run 이벤트가 있습니다. 이 이벤트는 모든 완료 결과(conclusion)에 대해 발생하므로, 작업 조건(job condition)을 사용해 failure만 필터링해야 합니다. GitHub 문서에서 주의할 점이 하나 있는데, 이 워크플로 파일이 기본 브랜치(default branch)에 존재해야만 트리거된다는 점입니다.
이 워크플로는 CI라는 이름의 워크플로를 감지하고, 간단한 JSON 바디를 생성하여 서명한 뒤 전송합니다:
name: Report CI failure
on:
workflow_run:
workflows: [CI]
types: [completed]
jobs:
notify:
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
runs-on: ubuntu-latest
steps:
- name: Send signed webhook
env:
WEBHOOK_URL: ${{ secrets.SHARKLY_WEBHOOK_URL }}
SIGNING_SECRET: ${{ secrets.SHARKLY_SIGNING_SECRET }}
REPO: ${{ github.repository }}
RUN_ID: ${{ github.event.workflow_run.id }}
RUN_URL: ${{ github.event.workflow_run.html_url }}
BRANCH: ${{ github.event.workflow_run.head_branch }}
SHA: ${{ github.event.workflow_run.head_sha }}
run: |
BODY=$(jq -nc --arg repo "$REPO" --arg run_id "$RUN_ID" \
--arg url "$RUN_URL" --arg branch "$BRANCH" --arg sha "$SHA" \
'{event:"ci_failure",repo:$repo,run_id:$run_id,run_url:$url,branch:$branch,sha:$sha}')
TS=$(date +%s)
SIG=$(printf '%s\n%s' "$TS" "$BODY" \
| openssl dgst -sha256 -hmac "$SIGNING_SECRET" -binary | base64)
curl -fsS -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-H "X-Webhook-Timestamp: $TS" \
-H "X-Webhook-Signature: v1=$SIG" \
--data-raw "$BODY"
브랜치 이름은 기여자가 직접 입력하므로, 워크플로 셸 스크립트에 바로 삽입하지 않고 env와 jq를 거쳐 전달합니다. 두 값은 절대 파일에 직접 적지 말고 암호화된 리포지토리 시크릿(secrets)으로 저장하세요.
2단계: 자동화 및 웹훅 트리거 생성하기
Space에서 Automation을 생성하고, 수정을 담당할 Agent를 할당한 뒤 Webhook 트리거를 추가합니다. Sharkly는 트리거를 처음 생성하거나 재생성할 때 전체 URL을 한 번만 표시하므로, 즉시 복사하여 GitHub 시크릿에 등록하세요.

서명 시크릿(signing secret)을 활성화하세요. 서명 시크릿이 없으면 URL 자체가 일종의 베어러(bearer) 토큰처럼 동작하여 URL을 아는 누구나 실행을 시작할 수 있습니다. Automations 문서에 설명된 대로 서명 시크릿을 설정하면, 모든 요청은 whsec_ 시크릿 키를 기반으로 타임스탬프, 줄바꿈, 원본 본문(raw body)을 HMAC-SHA256으로 해싱한 Base64 값 앞에 v1=을 붙여 X-Webhook-Signature 헤더로 전송해야 합니다. Sharkly는 300초 이상 차이 나는 타임스탬프를 거부하고, 동일한 서명은 10분 이내에 한 번만 허용하므로 패킷 캡처를 통한 리플레이 공격을 방지할 수 있습니다.
유효한 요청이 전달되었을 때 실행이 시작되려면 트리거가 활성화(enabled)되어 있어야 하고 Automation 상태가 Active여야 합니다. 먼저 'Run now' 기능으로 테스트해 보세요.
3단계: 필터링을 먼저, 수정을 나중에 수행하는 지침 작성하기
웹훅으로 실행된 Automation은 자동으로 태스크를 생성하지 않습니다. 실행 시 연결된 태스크가 없으므로 지침에 태스크 생성 단계를 포함해야 합니다. 이렇게 하면 실패 건마다 이력이 남고 질문을 남길 수 있는 스레드가 생기며, 팀원들이 진행 상태를 확인할 수 있습니다. 비용이 적게 드는 검사 항목을 상단에 배치하여 대다수의 무관한 이벤트는 수 초 내에 종료되도록 구성하세요:
You receive a CI failure webhook. The trigger payload is JSON with
event, repo, run_id, run_url, branch, sha.
1. Stop with no output unless event == "ci_failure" and repo is
acme/web. Stop if branch starts with "release/".
2. Search open tasks for run_id. If one exists, stop.
3. File a task titled "CI fix: <repo> run <run_id>" with run_url in
the body. Do all further work under that task.
4. Read the failed steps: gh run view <run_id> --log-failed
5. If the cause is a secret, permission, runner, or network problem,
comment the diagnosis on the task and stop. Change nothing.
6. Check out sha in a fresh worktree. Run the failing command and
confirm it fails the same way. If it does not reproduce, comment
what you tried and stop. Never push an unreproduced fix.
7. Make the smallest change that fixes it. Do not edit CI config,
lockfiles, or tests you were not asked to fix. Rerun the command
and the nearest test suite.
8. Push to branch ci-fix/<TASK-ID> and open a draft PR with
gh pr create --draft, task ID in the title. Comment the PR link
on the task and hand it to a human for review.
여기서 중요한 세부 사항이 두 가지 있습니다. 현재 상태 및 댓글 트리거는 조직 전체를 대상으로 매칭되기 때문에, 문서에서도 지침 내부에서 입력을 검증하라고 안내합니다. 웹훅은 고유 URL로 한정되지만 1단계 검사는 잘못 라우팅된 요청을 차단하는 안전장치 역할을 합니다. 또한 브랜치 이름의 태스크 ID는 매우 유용합니다. GitHub 연동이 설정되어 있으면 브랜치명, PR 제목 또는 PR 본문에 포함된 태스크 ID를 통해 풀 리퀘스트가 해당 태스크와 자동으로 연결됩니다.
4단계: 격리된 워크트리의 Computer 환경에서 실행하기
Computer는 자체 런타임, 파일, Git 자격 증명을 갖추고 Agent가 실행되는 연결된 호스트입니다. 각 실행마다 별도의 태스크 디렉터리와 독립된 워크트리가 할당되도록 Agent의 리포지토리를 임시 모드(Temporary mode)로 설정하세요. 이렇게 하면 1분 간격으로 두 개의 실패 이벤트가 발생하더라도 서로의 파일을 덮어쓰거나 간섭하지 않습니다. 구체적인 동작 방식은 격리된 워크트리에서의 병렬 에이전트 실행 및 git worktree 공식 문서를 참고하세요.
Git 접근 권한은 GitHub App이 아닌 Computer 자체에서 제공됩니다. 연동 기능은 풀 리퀘스트를 연결하고 이슈를 동기화할 뿐이며, 클론(clone)과 푸시(push)는 여전히 해당 호스트의 SSH 키, HTTPS 토큰 또는 gh 로그인을 사용합니다. 이 자격 증명에는 브랜치 푸시 권한만 부여하고, 병합 시 반드시 코드 리뷰를 거치도록 기본 브랜치를 보호(branch protection)하세요.
비용 및 안전장치(가드레일)
각 실행 비용은 해당 런타임의 자체 요금제에 따라 청구됩니다. Sharkly는 토큰을 직접 판매하지 않으므로, CI 수정 실행에 드는 비용은 현재 해당 시간 동안 사용하는 Claude Code 또는 Codex 세션 비용과 동일합니다. 1단계의 빠른 필터링(fast-path filter)은 비용을 제어하는 핵심 수단입니다. 1단계에서 걸러지는 이벤트는 전체 재현 과정을 거치지 않고 수백 개의 토큰만 소비하고 종료됩니다.

동시성 제어는 두 번째 안전장치입니다. 모든 Computer에는 동시 태스크 한도가 설정되어 있으며, 임시 디렉터리에서의 실행은 기본적으로 이 한도의 절반으로 제한됩니다. 처리 용량이 가득 차면 추가 실행은 단일 노트북에 무리하게 쌓이지 않고 대기열에 등록됩니다. 아침에 30개의 빌드 실패가 한꺼번에 발생하더라도 시스템 장애로 이어지지 않고 순차적으로 대기열에서 처리됩니다.
나머지는 한 번만 작성해 두면 되는 규칙들입니다:
- 드래프트 PR만 허용: 에이전트는 절대 직접 병합하지 않습니다. 검토 게이트를 어디에 배치해야 하는지는 인간 참여형(human-in-the-loop) 코딩 에이전트를 참고하세요.
- 실행당 1회만 시도: 첫 번째 수정 후 재실행에서도 실패하면 에이전트는 댓글을 남기고 작업을 중단합니다.
- 수정 금지 목록(Deny list) 설정: CI 설정 파일, 시크릿, 락파일(lockfile), 마이그레이션 파일 등.
- 지침 변경 시 일시 정지: 지침을 수정할 때는 해당 페이지에서 Automation을 일시 정지하고, 'Run now' 테스트를 거친 후 다시 활성화하세요.
신뢰하기 전에 먼저 검증하세요. 여기에는 계획, 관찰, 검증 루프(plan, observe, verify loop)가 적용됩니다. 적용 대상 저장소를 넓히기 전에 최소 일주일간의 실행 이력을 확인해 보세요.
다른 대안들
웹훅 기반 Automation 대신 실패 건마다 태스크를 직접 등록하는 방법도 있습니다. 워크플로에서 sharkly task create를 호출하는 스크립트를 실행한 다음, 할당된 Agent가 이를 가져가 처리하도록 만드는 방식입니다. 이 경우 에이전트가 무시해야 할 빌드 실패를 포함해 모든 실패마다 태스크가 생성되므로, 빌드 빈도가 낮은 저장소에 적합합니다. 이미 GitHub을 통해 이슈를 관리하고 있는 팀이라면 GitHub 이슈를 AI 에이전트에 할당하기부터 시작해 볼 수도 있습니다.
단일 저장소부터 시작하기
린트 및 타입 오류가 가장 자주 발생하는 저장소를 하나 골라 위의 워크플로를 연결하고, 웹훅을 자동으로 트리거하기 전에 Automation을 수동으로 세 번 정도 실행해 보세요. 단일 에이전트를 넘어 규모를 확장할 준비가 되었다면 10개의 AI 코딩 에이전트를 동시에 실행하는 방법을 참고하시기 바랍니다. Sharkly는 무료로 시작할 수 있습니다. 지금 Computer를 연결하고 기존 에이전트에게 다음 빌드 실패 처리를 맡겨 보세요.
자주 묻는 질문 (FAQ)
AI 에이전트가 실패한 CI 빌드를 스스로 수정할 수 있나요?
로컬에서 재현 가능한 린트, 타입, 스냅샷 오류는 스스로 수정할 수 있습니다. 다만 자동으로 병합해서는 안 됩니다. 결과물은 드래프트 PR로 유지하고, 사람이 직접 검토한 후 승인하도록 구성해야 합니다.
GitHub Actions 실패 시 AI 에이전트를 어떻게 트리거하나요?
types: [completed]인 workflow_run 이벤트를 수신하고, 작업 조건으로 conclusion == 'failure'를 지정한 워크플로를 추가합니다. 해당 작업(job)에서 에이전트의 웹훅 URL로 서명된 요청을 전송하게 됩니다.
에이전트가 잘못된 수정 사항을 푸시하지 못하도록 막으려면 어떻게 해야 하나요?
'로컬 재현 원칙'을 적용하면 됩니다. 에이전트는 로컬에서 오류가 발생하는 것을 직접 확인하고, 코드를 수정한 뒤, 동일한 명령어가 성공하는 것을 반드시 확인해야 합니다. 로컬에서 재현되지 않는다면 태스크에 코멘트만 남기고 푸시는 일절 진행하지 않습니다.
Sharkly의 GitHub 연동 기능이 풀 리퀘스트를 직접 생성하나요?
아닙니다. 연동 기능은 풀 리퀘스트를 태스크에 연결하고 이슈를 동기화하는 역할만 합니다. PR 생성은 에이전트가 Computer에 설정된 Git 및 gh 자격 증명을 사용하여 직접 수행합니다.
간헐적으로 실패하는 플래키 테스트(Flaky test)는 어떻게 처리하나요?
에이전트가 판단을 내리기 전에 실패한 테스트를 여러 번 다시 실행하도록 설정하세요. 어떤 실행에서는 통과하고 다른 실행에서는 실패한다면 임시방편으로 패치하는 대신 태스크에 플래키 테스트 현상을 보고해야 합니다.
CI 수정 작업 1회당 비용은 얼마나 드나요?
해당 세션 동안 런타임이 소비한 토큰만큼 청구됩니다. Sharkly 실행 비용은 사용 중인 Claude Code, Codex 또는 API 요금제에서 직접 차감됩니다.



