파이프라인과 자동화
파이프라인은 Control Center의 결정적 절반입니다. 에이전트는 무엇을 말할지 결정하고, 파이프라인은 다음에 무슨 일이 일어날지 매번 같은 방식으로 결정합니다. 파이프라인은 단계의 DAG로, 에이전트를 디스패치하고, 스크립트를 실행하고, 조건에 따라 분기하고, 컬렉션에 팬아웃하며 단계 사이로 데이터를 전달할 수 있습니다. 영속적이고, 재개할 수 있으며, 비용이 집계됩니다.
파이프라인이 존재하는 이유는 세 가지입니다. 반복적인 다단계 프로세스를 연결하고, 여러 에이전트를 순차 또는 병렬로 조율하며, 사람이 없어도 일어난 일에 반응하기 위해서입니다.
템플릿과 실행
섹션 제목: “템플릿과 실행”템플릿(PipelineDefinition)은 선언적 DAG로, 단계와 선언된 입력, 구성으로
이루어집니다. 템플릿은 워크스페이스 자체 데이터베이스에 있습니다.
실행(PipelineRun)은 그 템플릿의 한 번의 실행이며, 변경 가능한 상태 백과
비용·토큰 합계, 단계별 상태를 지닙니다.
하나의 템플릿에는 여러 실행이 있습니다. 실행은 재시작을 견딥니다. 엔진이 진행 중인 실행을 다시 불러와 멈춘 지점부터 이어서 처리합니다.
두 가지 백스톱은 단계를 재개하는 대신 전체 실행을 의도적으로 실패시킵니다. 재개하는 것이 중단하는 것보다 나쁘기 때문입니다.
suspendedStepTimeout(기본값 24시간)보다 오래suspended상태로 남은 단계는 종료 상태에 절대 도달하지 못할 티켓을 기다리고 있으므로, 실행을 풀어 주기 위해 실패 처리됩니다. 예외는extras['awaitApproval'] == true이며, 이는orchestration.awaitApproval부분 승인 게이트입니다.human.gate는 예외가 아닙니다.- 서버가 중단될 때 진행 중이던
extras: {'idempotent': false}로 선언된 단계는 이미 부수 효과(스쿼시 병합, 워크트리 정리)를 적용했을 수 있습니다. 다시 실행하면 이중 적용될 수 있으므로 엔진은 이 단계를 실패 처리하고 재시도를 여러분에게 맡깁니다.
종류는 스케줄하고, 본문은 일한다
섹션 제목: “종류는 스케줄하고, 본문은 일한다”단계에는 서로 직교하는 두 부분이 있고, 이 둘을 분리해 두는 것이 엔진을 작게 유지해 줍니다.
종류(StepKind)는 단계가 업스트림 단계를 기준으로 언제 실행 가능해지는지
엔진에 알려 줍니다. 스케줄러가 알아야 하는 것은 그것뿐입니다. 종류는 여섯
가지입니다. trigger, listen, join, router, forEach, terminal.
본문(bodyKey)은 단계가 예약된 뒤 수행하는 _작업_입니다. 본문은 서버 시작
시 키로 등록되는 클로저이므로, 종류가 다른 여러 단계가 하나의 본문을 공유할 수
있습니다. 예를 들어 여러 listen 단계가 모두 conversation.promptAgent를
실행하는 식입니다.
스케줄링 의미가 여섯 종류에 들어 있기 때문에, 스케줄러를 건드리지 않고도 동작 카탈로그를 늘릴 수 있습니다. 종류와 본문, 그 구성의 전체 카탈로그는 파이프라인 단계를 참고하십시오.
템플릿을 직접 작성하기 전에 알아 두면 좋은, 레지스트리 설계의 결과 두 가지가 있습니다.
bodyKey가 등록되지 않은 단계는 템플릿 로드 시 경고를 내보낸 뒤 절대 실행되지 않습니다. 런타임에 크게 실패하는 일은 없습니다.trigger와terminal단계는 이 경고에서 제외됩니다. 트리거는 아무 동작도 하지 않는pipeline.trigger본문을 실행해 다운스트림 리스너가 작동하게 하고,terminal단계는 본문이 없으며 스케줄러의 센티널입니다.- 노드의
extras맵에 있는 키는 정확히 일치해야 하며, 그렇지 않으면 조용히 무시됩니다.extras['spaceId']만이 에이전트 단계의 작업을 기존 대화에 넣습니다.extras['mode'](chat/plan/review)는 방을 여는 노드에서 읽으며(messaging.createSpace, 기본값review), 나중에 실행되는 에이전트 단계는 이미 참여한 대화의 권한을 다시 부여할 수 없습니다. 두 키를 다른 방식으로 표기하면 무시됩니다.
상태와 데이터 흐름
섹션 제목: “상태와 데이터 흐름”단계는 서로를 호출하지 않습니다. 단계는 실행의 공유 상태 백을 읽고 씁니다.
단계는 키로 입력을 읽어 실행하고, 자신의 outputKey 아래에 출력을 다시
씁니다. 병렬 분기가 같은 키를 대상으로 할 때 StateReducer가 동시 쓰기를
병합하고, TemplateRenderer가 같은 상태에서 프롬프트와 스크립트의 {{...}}
자리 표시자를 대체합니다.
그래서 파이프라인은 사후에 검사할 수 있습니다. 상태 백이 그 실행의 전부이기 때문입니다.
무엇이 실행을 시작하는가
섹션 제목: “무엇이 실행을 시작하는가”PipelineTrigger 행은 템플릿이 언제 자동 시작되는지를 선언합니다. 종류는 네
가지입니다.
| 트리거 | 다음일 때 실행을 시작합니다 |
|---|---|
| 도메인 이벤트 | 일치하는 도메인 이벤트가 발생할 때 — 예를 들어 PullRequestPublished 또는 TicketAssigned |
| 일정 | cron/간격 표현식이 도래할 때 |
| 수동 | 직접 실행할 때. 활성화된 수동 트리거의 존재가 템플릿을 실행 선택기에 넣습니다 |
| 웹훅 | 외부 시스템이 서버의 HTTP 포트에서 /webhooks/<token>으로 POST할 때 |
이벤트 트리거는 닫힌 집합입니다. 디스패처가 알고 선택기에 제공하는 이벤트
유형은 16가지이며(EventPayloadMapper.knownEventTypes), 그 외에는 아무것도
파이프라인을 시작할 수 없습니다. 16가지 중 14가지에는 페이로드 매핑이 있습니다.
TicketCreated와 TicketStatusChanged 둘은 매핑이 없어서, 둘 중 하나에 건
트리거는 활성화된 채로 절대 발생하지 않습니다. 전체 목록은
도메인 이벤트를 참고하십시오.
웹훅 토큰은 HMAC 시크릿을 겸합니다. 요청의
X-Hub-Signature-256: sha256=<hex> 헤더가 HMAC-SHA256(body, token)과
검증되고, 검증되지 않은 전달은 거부되어 재생할 수 없으며, 중복은 dedupe_key로
제거됩니다. 트리거 행은 (워크스페이스, 이벤트 유형, 템플릿)에 대해 고유하므로,
템플릿은 웹훅 트리거 하나와 도메인 이벤트 유형당 트리거 하나만 가질 수
있습니다.
기본 제공 템플릿은 수동 및 이벤트 트리거가 활성화된 상태로 시드되고, 예약 트리거는 비활성화된 상태로 시드됩니다. 그래서 반복 스윕은 항상 옵트인입니다.
비활성 상태로 제공되는 템플릿
섹션 제목: “비활성 상태로 제공되는 템플릿”모든 워크스페이스에 13개의 파이프라인 템플릿이 시드되며, 그중 8개는 비활성
상태로 제공됩니다. external_pr_welcome, cross_review, ticket_to_pr,
pr_triage, pre_merge_gate, release_notes, dep_audit, pr_digest.
사람들을 놀라게 하는 부분이 바로 이것입니다. 이 템플릿들의 트리거는 활성화된
상태로 시드되지만, PipelineEngine.start는 비활성 템플릿을 거부하고 null을
반환합니다. 그래서 트리거는 아무것도 없는 곳을 향해 발생하고 실행은 나타나지
않습니다. 스위치는 트리거가 아니라 템플릿입니다. 이 8개가 무언가를 하길
기대하기 전에 설정 → 워크스페이스 → 파이프라인 템플릿에서 활성화하십시오.
워크스페이스를 다시 시드해도 선택한 내용은 유지됩니다. isEnabled 설정과 기존
트리거 행은 그대로 남습니다. 의도적인 예외가 정확히 하나 있습니다.
pr_merged_cleanup의 일일 일정은 이전에 꺼져 있었더라도 강제로 활성화됩니다.
가비지 컬렉션이기 때문입니다. 이것이 없으면 워크트리 행, 코드 그래프 파티션,
copy-on-write 사본이 쌓여만 가며, 그건 애초에 사용자가 선택할 일이
아니었습니다.
한 가지 더 알아 둘 비대칭이 있습니다. pr_review 기본 제공은 의도적으로 더
이상 GitHub에 게시하지 않습니다. 리뷰 게시는 별도의 사용자 승인 단계이고,
직접 게시하는 파이프라인은 이중 게시가 되기 때문입니다. cross_review,
ticket_to_pr, pr_triage는 실행될 때 여전히 GitHub에 곧바로 댓글을
게시합니다.
엔진이 아는 것
섹션 제목: “엔진이 아는 것”PipelineEngine은 실행 레코드를 만들고, 실행의 이벤트 유형에 맞는 시작 노드를
예약한 다음 DAG를 순회합니다. 단계가 완료되면 다운스트림 트리거를 평가하고,
라우터 분기를 해석하고, 조인을 기다리고, 재시도 정책과 continue-on-fail을
적용하며, 모든 단계에서 상태와 비용, 오류를 영속화합니다. 다른 시작 노드에서
나가는 엣지는 해당 실행에서 무시되므로, 일정에 의한 발화는 수동 전용 조건을
기다리지 않습니다.
엔진이 모르는 것은 티켓팅, 디스패치, GitHub, 메시징에 관한 그 어떤 것입니다.
엔진의 유일한 확장 지점은 PipelineBodyRegistry입니다. 여기 등록된 본문이
AgentDispatchPort, MessagingPort와 그 형제 포트들을 보유합니다. 그래서
파이프라인에 기능을 추가할 때 스케줄러를 바꿀 일이 없습니다.
오류 처리
섹션 제목: “오류 처리”실패한 단계는 오류 메시지를 기록하고 failed로 이동합니다. 단계가
continueOnFail을 선언하면 다운스트림 단계가 계속 진행되고 오류는 실행 상태에
저장됩니다. 그렇지 않으면 실행이 실패합니다. StepRetryPolicy가 있는 단계는
그 두 경우 중 어느 것이든 적용되기 전에 선형 또는 지수 백오프로 먼저
재시도됩니다.
함께 보기
섹션 제목: “함께 보기”- 도메인 이벤트: 이벤트 트리거가 수신하는 대상
- 오케스트레이션: 승인한 계획을 이 파이프라인 중 하나로 컴파일합니다
- 티켓과 위임: 파이프라인 단계가 만들고 완료하는 것
- 파이프라인 단계: 종류와 본문, 구성의 전체 카탈로그
- 첫 파이프라인 만들기
- 파이프라인 템플릿 만들기
- 파이프라인 수동 실행
- 파이프라인 실행 모니터링
- 파이프라인 트리거 설정