| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 |
- transformer
- openAI
- tensor-parallel
- Lora
- llama-4-scout-17b-16e-instruct
- nccl
- sfttrainer
- CPT
- prompt
- multi-gpu
- instruction tuning
- Fine-tuning
- Text-to-Image
- langchain
- backbone
- torch._C._cuda_getDeviceCount()
- llm
- Python
- diffusion
- vLLM
- ubuntu
- glibcxx
- Mac
- Gemma
- gemma-3-27b-it
- PEFT
- ViT
- llama-4
- gemma-3
- aimv2
- Today
- Total
꾸준하게
[논문리뷰] Agent Lightning v1.0: Towards Harnessed Agentic RL 본문
| 항목 | 내용 |
|---|---|
| 논문 제목 | Agent Lightning v1.0: Towards Harnessed Agentic RL |
| 저자 | Zhiyuan He, Siwei Zhang, Zhiwen Zhou, Yuqing Yang, Yu Kang, Yuge Zhang, Luna K. Qiu, Tin Yan Tsui, Jiahang Xu, Chong Luo |
| 소속 | Microsoft / Fudan University / Zhejiang University / University of Edinburgh |
| 공개일 | 2026년 8월 18일 (arXiv v1) |
| 분야 | cs.AI (인공지능), cs.SE (소프트웨어공학) |
| 원문 | arXiv:2608.17528 · PDF · HTML |
| 공식 코드 | microsoft/agent-lightning (MIT) |
| 인용 수 | 집계 전 (공개 직후, 2026. 8.) |
| 한 줄 요약 | 배포용 agent harness를 그대로 둔 채 RL을 돌리는 harnessed agentic RL에서 발생하는 시스템적 함정(retokenization, advantage, loss normalization, 백엔드 스케줄링)을 처음으로 체계화하고, 약 3,500줄짜리 경량 프레임워크로 SWE-bench Verified 41.8% → 56.4%를 재현 가능한 형태로 공개한 논문 |
TL;DR
- 요즘 에이전트는 LLM 단독이 아니라 tool·context·control flow를 관리하는 harness 위에서 돈다. 그런데 harness를 그대로 두고 RL을 돌리면 학습 엔진은 rollout 전체가 아니라 LLM 요청–응답 쌍의 나열만 보게 되고, 기존 프레임워크들은 이걸 어떻게 학습 샘플로 조립할지 제각각으로 처리하고 있었다.
- 저자들은 이 패러다임을 harnessed agentic RL로 명명하고, 네 가지 난제(retokenization/sample merging, advantage 계산, loss normalization, 백엔드 스케줄링)를 수식 수준으로 정리한 뒤 “sample이 아니라 rollout 단위로 통계를 잡아라”는 일관된 답을 제시한다.
- 약 3,500줄짜리 Agent Lightning v1.0으로 search / instruction-following / coding 에이전트를 학습시켰고, 특히 coding agent는 6K 샘플 + 소규모 자원만으로 SWE-bench Verified를 41.8% → 56.4% (+14.6%p) 끌어올렸다. 데이터 정제 파이프라인과 reward hacking 방어까지 전부 공개했다.
0. 왜 지금 이 논문인가
2025년의 agentic RL은 대체로 이런 모양이었다. verl, AReaL, slime 같은 학습 프레임워크 안에 에이전트 루프를 직접 구현하고, 학습 엔진이 환경과의 상호작용을 소유한다. 이 구조에서는 rollout 하나가 곧 토큰 시퀀스 하나이고, 그 시퀀스가 곧 학습 샘플 하나다. 깔끔하다. 대신 mini-SWE-agent, OpenHands, Claude Code, Codex 같은 실제로 쓰이는 harness를 가져다 쓸 수가 없다. 각각 의존성과 구현이 복잡해서, 학습 스택 안에 통째로 재구현해야 하기 때문이다.
원조 Agent Lightning(arXiv:2508.03680)이 제안한 해법이 이 지점을 찔렀다. 학습과 에이전트 실행을 분리하고, 에이전트는 LLM 엔드포인트(프록시)만 갈아끼우면 그대로 학습 대상이 된다는 것이다. 이 proxy 기반 접근은 이후 verl Uni-Agent, AReaL 2.0, slime v0.3.0, Polar가 모두 따라오면서 사실상 표준이 됐다.
이 논문은 그 다음 질문을 던진다. “그래서 프록시 너머에서 관찰되는 요청–응답 나열을, 도대체 어떻게 학습 샘플로 조립해야 하는가?” 저자들은 이 패러다임에 harnessed agentic RL이라는 이름을 붙이고, 지금까지 각 프레임워크가 말없이 서로 다르게 처리해 온 부분들이 사실은 알고리즘 정확성과 학습 안정성을 직접 좌우한다는 것을 보인다. 프레임워크 논문이라기보다는, agentic RL 인프라의 암묵적 설계 결정을 처음으로 명시화한 문서에 가깝다.

Figure 1. 이 그림에서 읽어야 할 것은 경계선이다. 왼쪽 GPU 클러스터(Trainer + 추론 엔진)와 오른쪽 에이전트 실행 클러스터가 완전히 분리되어 있고, 그 사이를 잇는 유일한 통로가 API Gateway다. 에이전트는 자기 harness를 그대로 유지한 채 LLM 엔드포인트만 이 Gateway로 바꾼다. 학습 엔진이 보는 것은 이 통로를 지나간 요청–응답 기록뿐이며, 이 논문의 모든 난제가 여기서 파생된다.
(출처: He et al., 2026, arXiv:2608.17528 Figure 1)
1. 배경 — 두 종류의 agentic RL은 무엇이 다른가
💡 agent harness (에이전트 하네스)
LLM을 감싸서 실제로 “일하게” 만드는 껍데기다. 어떤 도구를 어떤 프로토콜로 노출할지, 대화 컨텍스트를 어떻게 쌓고 언제 요약할지, 실패하면 어떻게 복구할지, 서브에이전트를 언제 띄울지를 전부 harness가 결정한다. mini-SWE-agent, OpenHands, Claude Code, Codex가 전부 harness다. 같은 모델이라도 harness가 바뀌면 성능이 크게 달라지기 때문에, 저자들은 harness를 “에이전트 능력의 일부”로 본다.
💡 POMDP (부분 관측 마르코프 결정 과정)
정책이 환경의 진짜 상태 $s_t$를 직접 보지 못하고, 그것의 일부 관측만 보고 행동을 결정해야 하는 상황을 다루는 정식화다. 여기서 중요한 건 “무엇이 숨겨진 상태이고 무엇이 관측인가”이며, 이 논문의 핵심 주장이 바로 그 대응 관계가 두 패러다임에서 다르다는 것이다.
1.1 전통적 agentic RL
학습 엔진이 상호작용 루프를 직접 소유한다. 모델이 액션 토큰을 뱉으면 환경이 관측을 돌려주고, 토크나이즈된 관측이 기존 히스토리 뒤에 그대로 이어 붙는다.
$$
p_t = (p_{t-1},, a_{t-1},, o_t). \tag{1}
$$
여기서 $p_t$는 스텝 $t$에서 모델에게 주어지는 토큰 히스토리, $a_{t-1}$은 직전 스텝에서 생성된 액션, $o_t$는 가장 최근의 환경 관측이다. 전체 rollout은 $(p_1, a_1, o_1, a_2, o_2, a_3, \ldots)$라는 하나의 선형 토큰 궤적이 되고, 이것이 그대로 학습 샘플 하나에 대응된다. 잠재 상태는 사실상 환경 상태뿐이다.
1.2 harnessed agentic RL
harness가 루프를 소유하면 그림이 달라진다. 학습 엔진이 볼 수 있는 것은 LLM 엔드포인트를 지나간 호출뿐이다. rollout $\rho$에 대해 기록되는 것은
$$
\mathcal{C}(\rho) = \bigl((p_1, a_1), (p_2, a_2), \ldots, (p_{T_\rho}, a_{T_\rho})\bigr) \tag{2}
$$
이고, $p_i$는 $i$번째 LLM 호출의 프롬프트 토큰, $a_i$는 모델이 실제로 샘플링한 응답 토큰이다. 호출과 호출 사이에서 벌어진 도구 실행과 harness 상태 전이는 전부 보이지 않는다.
정식화하면 잠재 상태는 harness 상태와 환경 상태의 쌍이 된다.
$$
s_t = \bigl(s_t^{\mathrm{harness}},, s_t^{\mathrm{env}}\bigr) \tag{3}
$$
모델은 $s_t$를 직접 보지 못한다. harness가 메시지 수준 컨텍스트를 구성한 뒤, chat template과 tokenizer를 거쳐 실제 프롬프트 토큰으로 렌더링한다.
$$
C_t^{\mathrm{msg}} = \operatorname{Context}_H\bigl(s_t^{\mathrm{harness}}\bigr), \tag{4}
$$
$$
p_t^{\mathrm{tok}} = \operatorname{Tok}\bigl(\operatorname{Template}(C_t^{\mathrm{msg}})\bigr). \tag{5}
$$
$\operatorname{Context}_H$는 harness $H$의 컨텍스트 구성 정책(무엇을 남기고 무엇을 잘라낼지), $\operatorname{Template}$은 모델별 chat template, $\operatorname{Tok}$은 토크나이저다. 그래서 하나의 정책 결정은 호출 단위 전이로 기록된다.
$$
z_t = \bigl(p_t^{\mathrm{tok}},, a_t^{\mathrm{tok}}\bigr), \qquad a_t^{\mathrm{tok}} \sim \pi_\theta\bigl(\cdot \mid p_t^{\mathrm{tok}}\bigr). \tag{6}
$$
핵심은 이것이다. rollout은 이런 전이들의 가변 길이 묶음이고, 연속한 프롬프트 사이에 토큰 접두 관계가 성립한다는 보장이 전혀 없다. 학습을 위해 어떤 시퀀스를 조립하든, 각 액션이 실제로 샘플링될 때 조건이 되었던 그 프롬프트를 보존해야 한다. 이 제약 하나가 이후 모든 논의의 뿌리다.
Figure 2를 표로 재구성:
| Agentic RL | Harnessed Agentic RL | |
|---|---|---|
| 상태 | 환경 | harness + 환경 |
| 모델 입력 | 연속된 토큰 히스토리 | 호출별로 따로 구성된 프롬프트 |
| 에이전트 형태 | 단일 ReAct 에이전트 | 멀티에이전트, 서브에이전트, handoff |
(원문 Figure 2를 마크다운 표로 재구성. 출처: He et al., 2026)
이 표의 세 줄이 곧 다음 장의 네 가지 난제를 낳는다. 특히 두 번째 줄 — 모델 입력이 “이어 붙는 히스토리”가 아니라 “매번 새로 만들어지는 프롬프트”라는 사실이 결정적이다.
2. 핵심 — harnessed agentic RL의 네 가지 난제
2.1 난제 ①: Retokenization과 sample merging
harness는 모델 API와 텍스트로 대화한다. 반면 RL 학습은 토큰 ID로 돌아간다. 이 층위 차이가 문제의 출발점이다.
harness 관점에서 rollout은 턴 단위 호출의 나열이다.
$$
\mathcal{C}^{\mathrm{text}}(\rho) = \bigl((p_1^{\mathrm{text}}, a_1^{\mathrm{text}}), (p_2^{\mathrm{text}}, a_2^{\mathrm{text}}), \ldots\bigr), \tag{7}
$$
일반적인 멀티턴 ReAct 에이전트라면 직전 호출이 다음 프롬프트의 텍스트 수준 접두사가 된다.
$$
(p_i^{\mathrm{text}}, a_i^{\mathrm{text}}) \preceq p_{i+1}^{\mathrm{text}}. \tag{8}
$$
그런데 학습이 요구하는 것은 토큰 수준 접두 조건이다.
$$
\bigl(p_i^{\mathrm{tok}}, a_i^{\mathrm{tok}}\bigr) \preceq p_{i+1}^{\mathrm{tok}}, \tag{9}
$$
여기서 $\preceq$는 정확한 토큰 단위 접두사를 뜻한다. 그리고 식 (8)이 성립해도 식 (9)는 성립하지 않을 수 있다. 저자들이 실제로 관찰한 원인은 세 가지다.
(1) chat template의 비합성성(non-compositionality). 전체 메시지 히스토리를 렌더링한 결과가, 부분들을 각각 렌더링해 이어 붙인 것과 같지 않다.
$$
\operatorname{Template}(A ,|, B) \neq \operatorname{Template}(A) ,|, \operatorname{Template}(B). \tag{10}
$$
템플릿이 메시지 경계에 구분자나 줄바꿈을 끼워 넣거나, 반대로 원래 생성에 있던 마커를 지워버리기 때문이다. 논문은 구체적으로 Qwen의 chat template이 앞선 <think> 마커를 제거해서 토큰 접두 연속성이 깨지는 사례를 짚는다.
(2) decode–retokenize drift. 토큰 디코딩은 단사(injective)가 아니다. 샘플링된 토큰을 텍스트로 바꿨다가 다시 토크나이즈하면 원래 토큰 ID로 돌아오지 않을 수 있다.
$$
\operatorname{Tok}\bigl(\operatorname{Decode}(a_i^{\mathrm{tok}})\bigr) \neq a_i^{\mathrm{tok}}. \tag{11}
$$
Figure 3을 코드블록으로 재구성:
호출 i : ... [ h ][ aving ] ← 모델이 실제로 샘플링한 토큰 경계
호출 i+1 : ... [ hav ][ ing ] ← 같은 텍스트를 다시 토크나이즈한 결과
↑ 텍스트는 동일("having")하지만 토큰 경계가 다름 → 식 (9) 위배 → 병합 불가(원문 Figure 3의 예시를 재구성. 이미지가 필요하면 원문 PDF 3쪽 참고. 출처: He et al., 2026)
(3) 추론 시점의 출력 변환. tool-call 파서나 structured output 핸들러가 응답을 파싱·정규화·복구·재직렬화한 뒤 harness에 돌려준다. 이 과정에서 공백, 구분자, JSON 구조가 바뀌면 텍스트 수준에서조차 원본과 달라진다.
그래서 어떻게 대응하는가 — 세 가지 전략
| 전략 | 방식 | 장점 | 대가 |
|---|---|---|---|
| 호출별 독립 학습 | 각 $(p_i^{\mathrm{tok}}, a_i^{\mathrm{tok}})$를 따로 학습 | 토큰 정확성 보장 | 공유 접두사를 반복 계산 → 비효율 |
| 버퍼 기반 토큰 치환 (AReaL, verl Uni-Agent) | 프록시가 과거 호출의 텍스트·토큰을 버퍼링했다가 새 프롬프트의 해당 구간을 원본 토큰으로 교체 | 병합률 상승, 계산 재사용 | off-policy 오염 위험 |
| best-effort 병합 (Agent Lightning v1.0) | 식 (9)를 만족할 때만 병합, 실패하면 시퀀스를 끊고 새로 시작 | 프롬프트 보존 + 표준 dense causal 커널로 동작 | drift가 잦으면 병합률만 떨어짐 |
| tree-structured 학습 | 공통 접두사를 한 번만 표현하고 branch-aware causal mask 사용 | 재사용률 최대 | 커스텀 커널·파티셔닝·분산 그래디언트 → 백엔드 부담 큼 |
두 번째 전략의 위험을 논문은 수식으로 정확히 짚는다. 실제 다음 프롬프트가 재구성된 응답 $\widehat{a}_i^{\mathrm{tok}}$을 담고 있다고 하자.
$$
p_{i+1}^{\mathrm{tok}} = p_i^{\mathrm{tok}} ,|, \widehat{a}i^{\mathrm{tok}} ,|, \Delta{i+1}. \tag{12}
$$
이 구간을 원래 샘플링된 $a_i^{\mathrm{tok}}$으로 갈아끼우면 다음과 같은 “꿰맨” 프롬프트가 만들어진다.
$$
\widetilde{p}{i+1}^{\mathrm{tok}} = p_i^{\mathrm{tok}} ,|, a_i^{\mathrm{tok}} ,|, \Delta{i+1}, \qquad \widetilde{p}{i+1}^{\mathrm{tok}} \neq p{i+1}^{\mathrm{tok}}. \tag{13}
$$
문제는 $a_{i+1}^{\mathrm{tok}}$이 $\widetilde{p}{i+1}^{\mathrm{tok}}$이 아니라 $p{i+1}^{\mathrm{tok}}$을 조건으로 샘플링됐다는 점이다. 꿰맨 프롬프트로 학습하면 off-policy 불일치가 생긴다. 즉 토큰 접두 겹침은 “rollout 중 실제로 소비된 프롬프트를 보존할 때만” 병합 근거가 될 수 있다. Agent Lightning v1.0이 best-effort 병합을 고른 이유가 이것이다.
💡 off-policy 불일치가 왜 문제인가
정책 경사(policy gradient) 계열 알고리즘은 “이 상태에서 이 행동을 했더니 이만큼 좋았다”를 학습한다. 그런데 학습할 때 쓰는 상태(프롬프트)가 실제로 행동을 뽑을 때의 상태와 다르면, 존재한 적 없는 상태–행동 쌍에 보상을 귀속시키는 셈이 된다. 중요도 샘플링 비율($\pi_\theta / \pi_{\text{old}}$)이 잘못된 분모를 쓰게 되어 그래디언트가 편향된다.
2.2 난제 ②: Advantage를 rollout 단위로 잡을 것인가, sample 단위로 잡을 것인가
병합이 끝나면 rollout $\rho$ 하나가 만들어내는 학습 샘플 수 $N_\rho$는 실행이 끝나고 샘플 조립까지 마쳐야 알 수 있는 값이 된다. retokenization만 원인이 아니다. harness가 서브에이전트를 띄우면 선형 히스토리를 공유하지 않는 분기가 생기고, 컨텍스트를 요약하면 앞선 토큰 접두사가 통째로 교체된다.
이건 예외적 상황이 아니다. 저자들의 coding agent 학습에서 rollout의 평균 36%만이 단일 학습 샘플로 남았고, rollout 하나당 평균 2.4개의 샘플이 나왔다.
보상은 여전히 outcome 기반이고, 해당 rollout에서 나온 모든 샘플에 동일하게 부여된다. 그렇다면 GRPO의 그룹 통계(baseline)는 어느 단위로 잡아야 하는가? 놀랍게도 프레임워크마다 답이 다르다.
| 프레임워크 | advantage 계산 단위 |
|---|---|
| verl Uni-Agent, Polar | rollout 단위 |
| slime, AReaL | sample 단위 |
(원문 §2.2 서술을 표로 재구성. 출처: He et al., 2026)
Figure 4의 예시를 숫자로 재구성. 같은 프롬프트에서 나온 GRPO 그룹에 Rollout 1(보상 1)과 Rollout 2(보상 0)가 있다고 하자.
| 상황 | 샘플 구성 | baseline $\bar{r}$ |
|---|---|---|
| 전통적 RL | Rollout 1 → 1개, Rollout 2 → 1개 | $(1+0)/2 = 1/2$ |
| harnessed, rollout 단위 | Rollout 1 → 3개, Rollout 2 → 1개 | $(1+0)/2 = \mathbf{1/2}$ |
| harnessed, sample 단위 | 동일 | $(1+1+1+0)/4 = \mathbf{3/4}$ |
(원문 Figure 4의 수치 예시를 표로 재구성. 출처: He et al., 2026)
💡 advantage와 baseline
advantage는 “이 행동이 평균보다 얼마나 좋았나”를 나타내는 값이다. GRPO는 별도 value network 없이, 같은 프롬프트에서 뽑은 여러 rollout의 보상 평균을 baseline $\bar{r}$로 삼고 $A = r - \bar{r}$로 계산한다. 그래서 baseline이 흔들리면 모든 샘플의 학습 신호 부호와 크기가 통째로 바뀐다. 위 표에서 sample 단위 계산은 baseline을 1/2에서 3/4로 밀어 올려 버린다.
저자들의 입장은 명확하다. retokenization은 우발적 현상이고, 우연히 rollout이 더 많은 샘플로 쪼개졌다는 이유로 advantage 귀속이 달라져서는 안 된다. 서브에이전트 생성이나 컨텍스트 요약도 마찬가지로 harness의 내부 사정일 뿐, 그룹 전체의 baseline을 바꿀 권한이 없다. 다만 rollout 내부의 샘플들 사이 credit assignment는 여전히 열린 문제로 남겨 둔다.
2.3 난제 ③: Loss normalization
샘플 수가 가변이면 손실 정규화도 자명하지 않다. 배치에 rollout이 $R$개 있고, rollout $\rho$가 $N_\rho$개 샘플을 만들며, 그중 $j$번째 샘플이 $L_{\rho,j}$개의 응답 토큰과 토큰별 손실 $\ell_{\rho,j,t}$를 갖는다고 하자.
(a) token-mean loss (DAPO 계열) — 배치의 모든 토큰 손실을 더하고 전체 응답 토큰 수로 나눈다.
$$
\mathcal{L}{\mathrm{token\text{-}mean}} = \frac{\sum{\rho=1}^{R}\sum_{j=1}^{N_\rho}\sum_{t=1}^{L_{\rho,j}} \ell_{\rho,j,t}}{\sum_{\rho=1}^{R}\sum_{j=1}^{N_\rho} L_{\rho,j}}. \tag{14}
$$
(b) seq-mean-token-mean loss (GRPO 계열) — 샘플 내부에서 먼저 평균 내고, 그 샘플 평균들을 균등 평균한다.
$$
\mathcal{L}{\mathrm{seq\text{-}mean}} = \frac{1}{\sum{\rho=1}^{R} N_\rho} \sum_{\rho=1}^{R}\sum_{j=1}^{N_\rho} \frac{1}{L_{\rho,j}} \sum_{t=1}^{L_{\rho,j}} \ell_{\rho,j,t}. \tag{15}
$$
(c) rollout-level token-mean loss (slime 구현) — rollout의 모든 응답 토큰을 먼저 한데 모아 평균 내고, 그다음 rollout끼리 균등 평균한다.
$$
\mathcal{L}{\mathrm{rollout\text{-}mean}} = \frac{1}{R} \sum{\rho=1}^{R} \frac{\sum_{j=1}^{N_\rho}\sum_{t=1}^{L_{\rho,j}} \ell_{\rho,j,t}}{\sum_{j=1}^{N_\rho} L_{\rho,j}}. \tag{16}
$$
Figure 5의 예시를 표로 재구성. 배치에 rollout A(샘플 2개, 응답 길이 50·100), B(샘플 3개, 각 30), C(샘플 1개, 40)가 있고 $A_1, A_2, \ldots$가 각 샘플의 토큰 손실 합이라 하자.
| 정규화 | 계산식 |
|---|---|
| token-mean | $(A_1{+}A_2{+}B_1{+}B_2{+}B_3{+}C_1)/(50{+}100{+}30{+}30{+}30{+}40)$ |
| seq-mean-token-mean | $\tfrac{1}{6}(A_1/50 + A_2/100 + B_1/30 + B_2/30 + B_3/30 + C_1/40)$ |
| rollout-level token-mean | $\tfrac{1}{3}\bigl((A_1{+}A_2)/150 + (B_1{+}B_2{+}B_3)/90 + C_1/40\bigr)$ |
(원문 Figure 5의 예시를 표로 재구성. 출처: He et al., 2026)
식 (15)의 문제가 표에서 바로 보인다. 분모가 $6$(샘플 수)이므로, 샘플을 3개 만든 rollout B가 1개만 만든 rollout C보다 3배의 최적화 가중치를 가져간다. 그 3이라는 숫자가 retokenization 운에 좌우된다는 게 문제다.
그래서 이론적으로는 식 (14)와 식 (16)이 더 원칙적이다. 다만 저자들은 실무에서 식 (14)의 token-mean이 긴 시퀀스에 민감하다는 점을 발견했다. 길고 부정적인 샘플이 배치에 여럿 들어오면 학습 후반에 불안정해진다는 것이다. 최종 선택은 식 (16)의 rollout-level token-mean이다.
2.4 난제 ④: 학습 백엔드 스케줄링
샘플 수와 길이는 harness 실행 후에야 확정되는데, GPU 수와 data/tensor/pipeline 병렬 설정은 학습 내내 고정이다. 백엔드는 매 이터레이션마다 가변 워크로드를 고정 워커에 매핑해야 한다.
샘플을 물리적 텐서 배치로 평탄화하더라도, 통계적 출처(provenance)는 반드시 보존해야 한다. 모든 시퀀스가 rollout 식별자와 프롬프트 그룹 식별자를 달고 있어야 한다는 뜻이다.
$$
\mathcal{B}{\mathrm{train}} = \bigcup{\rho \in \mathcal{B}{\mathrm{rollout}}} \left{ \bigl(S{\rho,j},, \rho,, g_\rho\bigr) ;\middle|; 1 \leq j \leq N_\rho \right}, \tag{17}
$$
$S_{\rho,j}$는 rollout $\rho$로부터 만든 $j$번째 시퀀스, $g_\rho$는 같은 프롬프트에서 샘플링된 rollout 그룹을 식별한다. 평탄화는 물리적 표현만 바꿔야 하며, 시퀀스를 많이 만들었다는 이유로 특정 rollout이 추가 통계 가중치를 얻어서는 안 된다.
여기에 제약이 하나 더 붙는다. 한 rollout에서 나온 시퀀스들은 같은 optimizer 업데이트 안에 머물러야 한다. 이를 쪼개서 서로 다른 업데이트에 넣으면, 한 rollout의 각 부분이 서로 다른 정책 버전 하에서 평가되는 within-rollout policy skew가 생긴다.
3. 시스템 설계 — 약 3,500줄로 무엇을 만들었나
저자들은 We treat simplicity as a first principle
(“단순함을 제1원칙으로 삼는다”)고 밝히며, 전체 시스템을 약 3,500줄로 구현했다. 구성은 Figure 1의 세 컴포넌트다.
| 컴포넌트 | 역할 |
|---|---|
| API Gateway | rollout·model·event를 저장하는 API 서비스. harness의 LLM 호출을 trainer가 등록한 모델 엔드포인트로 포워딩. 라이프사이클 상태의 single source of truth |
| Rollout Controller | Kubernetes 클러스터(또는 로컬 프로세스 풀) 위에서 에이전트 실행 관리. Gateway에서 rollout을 폴링해 해당 태스크 기동 |
| Customized Trainer | verl 기반. Gateway에 rollout을 등록하고 완료를 기다린 뒤, 기록된 이벤트를 회수해 학습 샘플로 조립 |
설계의 뼈대는 선언적 rollout 추상화 + reconciliation 루프다. Trainer는 rollout을 “선언”만 하고, Controller가 실제 실행 상태를 계속 그 선언에 맞춰 조정한다. 덕분에 Kubernetes는 rollout 추상화의 일부가 아니라 교체 가능한 실행 백엔드가 된다.
3.1 Collocated Async RL — 이 논문의 실용적 하이라이트
동기식 RL은 배치의 모든 rollout이 끝나야 업데이트가 시작되므로, 가장 느린 rollout을 기다리는 동안 GPU가 논다. AReaL이 제안한 비동기 RL은 rollout용 GPU와 업데이트용 GPU를 아예 분리해 이 문제를 푼다. 하지만 저자들은 이 방식이 전체 GPU를 더 많이 요구하고, rollout 큐와 업데이트 큐를 따로 관리해야 해서(두 큐의 진행 속도가 다르다) 복잡하다고 지적한다.
Figure 6을 표로 재구성:
| 방식 | GPU 배치 | 느린 rollout 대기 | 필요 GPU |
|---|---|---|---|
| Sync RL | 단일 풀 | 대기함 (병목) | 적음 |
| Async RL (AReaL) | rollout / update 분리 | 대기 안 함 | 많음 |
| Collocated Async (제안) | 단일 풀 시분할 | 대기 안 함 | 적음 |
(원문 Figure 6의 개념을 표로 재구성. 이미지가 필요하면 원문 PDF 8쪽 참고. 출처: He et al., 2026)
동작 방식은 이렇다. rollout 데이터가 충분히 모이면 업데이트 단계가 시작되고, API Gateway가 동시에 신규 요청 수용을 중단하고 진행 중인 요청만 마무리한다. 그 뒤에 도착한 요청은 rollout 단계로 복귀할 때까지 Gateway가 붙잡아 둔다. 그래서 단계 전환이 harness 입장에서는 완전히 투명하다. 에이전트 코드는 그냥 응답이 조금 늦게 온 것으로만 느낀다.
실험에서 collocated async는 동기식 대비 end-to-end 약 2배 speedup을, 그것도 async RL보다 적은 GPU로 달성했다.
3.2 네트워크 신뢰성
학습 엔진과 에이전트가 분리되면 그 사이 호출이 네트워크를 타고, 당연히 실패한다. 두 가지 대응책을 쓴다.
- Gateway 엔드포인트의 멱등성(idempotency). 모든 rollout API 엔드포인트를 몇 번 호출해도 결과가 같도록 설계했다. 덕분에 호출 측이 상태 오염 걱정 없이 자유롭게 재시도할 수 있다.
- LLM 호출의 중복 제거. LLM 호출은 재시도할 때마다 새 생성이므로 멱등하게 만들 수 없다. 대신 Trainer가 샘플을 조립할 때 동일 프롬프트를 공유하는
model_request이벤트를 중복 제거하고, 가장 마지막(최신) 호출만 남긴다. 앞선 것들은 재시도되었거나 대체된 호출이므로 버린다.
3.3 Kubernetes 통합 — 상용 샌드박스를 쓰지 않는다
rollout 단계에서는 수많은 에이전트를 동시에 돌려야 한다. 기존 프레임워크들은 이 수요를 상용 샌드박스 서비스로 해결한다(verl Uni-Agent는 Modal Sandbox·Volcano veFaas, slime은 E2B). 편하지만 RL 학습 규모에서는 비싸다.
Agent Lightning v1.0은 각 에이전트 실행을 표준 Kubernetes Job으로 스케줄한다. 자체 호스팅·온프레미스 자원만으로 전체 스택을 돌릴 수 있고, 스택 전체가 오픈소스로 남는다. 뒤에 나올 reward hacking 방어(네트워크 정책)도 이 선택 덕분에 가능해진다.
3.4 모니터링
학습 중 에이전트 자체가 reward hacking, 이상 행동, 네트워크 문제를 일으킨다. rollout을 사람이 일일이 들여다보는 건 비현실적이므로, Trainer가 학습·검증 rollout과 Kubernetes pod 로그를 함께 기록한다. 그리고 AI 에이전트를 붙여 이 로그에서 문제를 자동 탐지한다. 실제로 §4.3.2의 reward hacking 사례들이 이 방식으로 발견됐다.
4. 실험
평가는 search, general instruction following, coding 세 가지 설정에서 이뤄진다. 앞의 둘은 각각 Search-R1과 LLM-in-Sandbox의 실험 세팅을 그대로 따랐고, coding agent는 기존 프레임워크에 재현 가능한 예제가 사실상 없다는 이유로 가장 상세히 다룬다.
4.1 Search Agent
(a) 셋업
| 항목 | 값 |
|---|---|
| 정책 모델 | Llama-3.2-3B-Instruct |
| 알고리즘 | GRPO |
| 학습 데이터 | HotpotQA train split |
| 평가 | HotpotQA, 2WikiMultiHopQA, MuSiQue, Bamboogle, TriviaQA, Natural Questions에서 각 50개 샘플링 |
| 학습 배치 크기 | 512 |
| 프롬프트당 rollout | 4 |
| 평가 주기 | 10 스텝마다 |
| 보상 지표 | Exact Match (EM) |
(b) 결과 — Figure 7(원문 PDF 9쪽)의 학습 곡선에서 학습 보상은 꾸준히 상승하고, 검증 보상은 다음과 같이 개선된다.
| 지표 | 학습 전 | 학습 후 | 개선 |
|---|---|---|---|
| 검증 보상 (EM) | 25.1% | 41.7% | +16.6%p |
(c) 해석 — 3B급 소형 모델로 멀티홉 QA 검증 보상을 1.66배 끌어올린 것인데, 여기서 중요한 건 절대 수치가 아니라 Search-R1과 동일한 세팅을 harness 분리 구조에서 재현했다는 사실이다. 프록시 뒤에 붙었다는 이유로 학습이 망가지지 않는다는 sanity check에 가깝다.
4.2 General Instruction-Following Agent
(a) 셋업
| 항목 | 값 |
|---|---|
| 정책 모델 | Qwen3-4B-Instruct-2507 |
| 알고리즘 | RLOO |
| harness | LLM-in-Sandbox 원저자 제공 harness 그대로 사용 |
| 데이터 | Instruction Pre-Training 공개 데이터셋, 80% 학습 / 20% 평가 |
| 학습 배치 크기 | 8 |
| 프롬프트당 rollout | 8 |
| 평가 주기 | 20 스텝마다 |
에이전트는 컴퓨터 샌드박스로 외부 자원에 접근하고, 파일을 관리하고, 코드를 실행하면서 비(非)코딩 태스크를 해결한다.
(b) 결과 — Figure 8(원문 PDF 9쪽) 기준.
| 지표 | 학습 전 | 학습 후 | 개선 |
|---|---|---|---|
| 검증 보상 | 51.9% | 70.2% | +18.3%p |
(c) 해석 — 배치 크기가 8밖에 안 되다 보니 배치 단위 학습 보상은 노이즈가 심하다. 그럼에도 검증 보상은 뚜렷한 상승 추세를 보인다. 이 실험의 진짜 메시지는 “원저자가 만든 harness를 손대지 않고 그대로 학습에 투입했다”는 부분이다. harnessed agentic RL의 존재 이유를 그대로 시연한 셈이다.
4.3 Coding Agent — 논문의 본론
정책 모델은 Qwen3.5-9B, harness는 mini-SWE-agent, 태스크는 SWE-smith 기반이다.
4.3.1 데이터 전처리와 필터링
SWE-smith는 실제 Python 저장소에 버그를 주입해 만든 실행 가능한 SWE 태스크 데이터셋이다. 59,136개 태스크 / 128개 저장소로 구성되며, 문제 설명·코드 패치·검증용 테스트를 포함한다.
| 데이터셋 | Docker 이미지 크기 |
|---|---|
| SWE-smith | 295 GB |
| R2E-Gym | 4 TB |
| SWE-Gym | 6 TB |
(원문 §4.3.1 서술을 표로 재구성. 출처: He et al., 2026)
디스크 요구량이 한 자릿수 배 이상 작다는 게 “적은 자원으로 재현 가능”의 첫 번째 조건이다. 그런데 공개 데이터를 그대로 쓸 수는 없었다. 저자들이 찾아낸 문제는 이렇다.
- 59,136개 레코드 중 18,033개는 문제 설명이 비어 있음
- 1,265개는 제공된 Docker 이미지에 해당 problem branch가 없음
- 일부 태스크는 테스트 스위트가 과도하게 큼 (예:
python-jsonschema는 7,000개 이상의 테스트 실행 → CPU·메모리 폭식)
1차 필터로 빈 문제 설명·누락 브랜치·테스트 200개 초과를 제거한다. 그래도 난이도 분포가 심하게 치우쳐 학습 신호가 빈약하므로, 모델 기반 난이도 필터를 추가로 건다.
Qwen3.5-9B로 각 후보를 4회 rollout
├─ 4회 모두 성공 → 제거 (너무 쉬움, 학습 신호 없음)
├─ 성공·실패 혼재 → 유지 → 약 5,000개
└─ 4회 모두 실패 → 1,000개만 샘플링해 추가 → 너무 쉬워지지 않게 방어
최종: 학습 약 6,000개 / 테스트 400개
💡 왜 “다 맞히는 문제”를 버리는가
GRPO 계열은 같은 프롬프트의 rollout 간 보상 분산에서 학습 신호를 얻는다. 4번 모두 성공하면 그룹 내 보상이 전부 1이라 baseline도 1, advantage는 전부 0 — 그래디언트가 0이 된다. 4번 모두 실패해도 마찬가지다. 그래서 성공·실패가 섞이는 구간이 가장 값진 데이터이고, 전부 실패하는 문제를 소량만 섞는 건 커리큘럼 상한을 남겨 두려는 조치다.
4.3.2 Reward hacking 방어
학습 중 에이전트가 문제를 푸는 대신 정답 소스코드를 직접 구해오는 행동들이 관찰됐다.
- Git 히스토리를 뒤져 gold commit 찾기
wget/curl로 GitHub에서 upstream 소스 가져오기pip으로 패키지 소스 내려받기urllib등 Python 네트워크 라이브러리로 소스 다운로드
방어는 두 겹이다. 첫째, Git 명령을 비활성화하고 .git 디렉터리를 감춘다. 둘째, Kubernetes network policy로 외부 네트워크 접근을 차단하고 명시적으로 화이트리스트에 올린 서비스만 허용한다. 결과적으로 에이전트는 주어진 문제 설명과 로컬 정보만으로 풀어야 한다.
이 절이 실무적으로 가장 값지다. 보상 함수를 아무리 잘 짜도 환경이 새면 에이전트는 반드시 그 틈으로 샌다. 그리고 앞서 본 §3.3의 Kubernetes 선택이 여기서 방어 수단으로 되돌아온다.
4.3.3 학습 다이내믹스 — rollout 단위 설계 검증 (핵심 ablation)
§2의 주장(sample 수는 우발적이므로 advantage와 loss normalization 모두 rollout 단위여야 한다)을 실제로 검증한다. 세 설정 모두 동일한 GRPO 목적함수를 쓴다.
| 설정 | advantage | loss normalization |
|---|---|---|
| Sample-level Advantage (baseline) | sample 단위 | token-mean, 식 (14) |
| Rollout-level Advantage | rollout 단위 | token-mean, 식 (14) |
| Rollout-level Adv + Rollout-level Norm | rollout 단위 | rollout-level token-mean, 식 (16) |
(b) 결과 — Figure 9(원문 PDF 10쪽) 기준, step 128 시점의 최고 검증 보상.
| 설정 | 검증 보상 (step 128) |
|---|---|
| Sample-level Advantage | 35.0% |
| Rollout-level Advantage | 33.1% |
| Rollout-level Adv + Rollout-level Norm | 38.2% (최고) |
(원문 §4.3.3 Figure 9의 수치를 표로 재구성. 출처: He et al., 2026)
그리고 이 마지막 설정의 체크포인트를 SWE-bench Verified로 평가한 결과가 논문의 헤드라인이다.
| 지표 | 학습 전 | step 208 | 개선 |
|---|---|---|---|
| SWE-bench Verified (Qwen3.5-9B) | 41.8% | 56.4% | +14.6%p |
rollout 병합 통계도 함께 공개한다(Figure 10, 원문 PDF 10쪽). coding agent 궤적은 길이 편차가 커서 패딩 낭비를 줄이려 가능한 한 병합하는데, 그 결과 rollout당 샘플 수가 가변이 된다.
| 지표 | 값 (학습 전체 평균) |
|---|---|
| 단일 샘플로 남는 rollout 비율 | 36% |
| rollout당 평균 학습 샘플 수 | 2.41개 |
(c) 해석 — 이 숫자들이 왜 중요한가
가장 눈에 띄는 건 Rollout-level Advantage만 적용하면 오히려 baseline보다 나빠진다(33.1% < 35.0%)는 점이다. “더 원칙적인” 수정이 단독으로는 성능을 깎는다. 저자들의 설명은 정책 엔트로피에 있다. rollout 단위로 advantage를 고치면 엔트로피가 더 빠르게 증가하는데, loss normalization까지 rollout 단위로 맞춰야 그 엔트로피 증가가 통제되면서 검증 보상이 올라간다.
즉 두 수정은 독립적인 개선이 아니라 한 쌍이다. advantage만 고치고 정규화를 그대로 두면, 샘플 많은 rollout이 여전히 과대 가중되면서 수정된 advantage와 충돌한다. 이건 논문의 이론적 주장(§2.2, §2.3이 같은 원리의 두 얼굴)을 실험이 정확히 뒷받침하는 대목이다.
두 번째로, 36% / 2.41이라는 숫자가 이 논문 전체의 존재 이유다. 만약 rollout 대부분이 단일 샘플로 남는다면 sample 단위든 rollout 단위든 차이가 없고, 이 논문은 쓸 필요가 없었다. 실제로는 rollout의 3분의 2가 쪼개지고 평균 2.4배로 불어난다. 그래서 정규화 상수가 rollout마다 최대 몇 배씩 달라지고, 그 배수가 retokenization 운에 좌우된다.
세 번째로, SWE-bench Verified 41.8% → 56.4%는 SFT 없이 순수 RL만으로, 6K 샘플과 소규모 자원으로 나온 결과다. 대형 랩의 수만~수십만 태스크 규모 코딩 RL과 비교하면 데이터가 한 자릿수 이상 작다. 재현 가능성이라는 관점에서는 56.4%라는 절대값보다 이쪽이 더 큰 기여다.
5. 주요 인사이트 — 왜 통했고, 지금 어떤 의미인가
① “우발적 구현 상세가 학습 통계를 바꾸면 안 된다”는 단일 원칙. 이 논문의 네 가지 난제는 표면적으로는 서로 다른 문제처럼 보이지만, 답은 전부 같다. rollout이 몇 개의 샘플로 쪼개졌는지는 tokenizer 경계, chat template 구현, harness의 요약 타이밍 같은 알고리즘과 무관한 사정에 좌우된다. 그런 값이 baseline과 그래디언트 정규화 상수에 들어가면, 학습이 “무엇을 잘했는가”가 아니라 “어떻게 쪼개졌는가”를 배우게 된다. 실무자에게 주는 교훈은 명확하다 — 배치를 구성할 때, 각 정규화 상수의 분모가 무엇에 의해 결정되는지 한 번씩 따져 봐야 한다.
② 두 수정은 반드시 함께 가야 한다. 33.1% < 35.0%라는 ablation 결과는 프레임워크 사용자에게 실질적인 경고다. 프레임워크 설정에서 advantage 단위만 rollout으로 바꾸고 loss normalization을 기본값으로 두면, 아무것도 안 한 것보다 나빠질 수 있다. 부분적인 “올바름”이 전체적인 올바름을 보장하지 않는다.
③ 프레임워크마다 답이 다르다는 사실 자체가 발견이다. verl Uni-Agent와 Polar는 rollout 단위, slime과 AReaL은 sample 단위로 advantage를 계산한다. 병합 전략도 AReaL·Uni-Agent는 버퍼 치환, slime·Polar는 치환하지 않는다. 이런 차이가 문서화되지 않은 채 존재했다는 건, 같은 알고리즘·같은 데이터로 프레임워크만 바꿔도 결과가 재현되지 않을 수 있다는 뜻이다. 이 논문이 “첫 번째 포괄적 정리”를 자처하는 근거가 여기 있다.
④ 접근성이 기여다. 3,500줄, 상용 샌드박스 없는 자체 호스팅 Kubernetes, GPU를 시분할하는 collocated async, 6K 샘플. 이 조합은 전부 “작은 팀도 돌릴 수 있는가”라는 하나의 질문을 향한다. 비동기 RL이 GPU를 더 많이 요구한다는 지적, 상용 샌드박스가 RL 스케일에서는 비싸다는 지적은 논문에서 흔히 생략되는 종류의 정직함이다. 데이터 정제 파이프라인과 reward hacking 방어 스크립트까지 공개한 것도 같은 맥락이다.
⑤ 한계와 남은 문제. 저자들 스스로 rollout 내부 샘플들 사이의 credit assignment는 열어 뒀다고 밝힌다. 지금은 outcome 보상을 rollout의 모든 샘플에 균등 부여할 뿐이다. 긴 궤적에서 어느 호출이 실제로 결정적이었는지는 여전히 미해결이다. 또 실험이 3B~9B 모델 규모에 머물러 있어, 더 큰 모델과 더 긴 horizon에서도 rollout 단위 정규화가 같은 이득을 주는지는 확인되지 않았다. ablation도 coding agent 한 도메인에서만 수행됐다.
⑥ 이 흐름의 방향. harnessed agentic RL이라는 명명은 단순한 용어 놀이가 아니다. 배포 시점의 harness가 학습에 직접 참여한다는 건, 학습–배포 간 격차(train-test gap)를 harness 수준에서 좁힌다는 뜻이다. Claude Code나 Codex 같은 harness가 사실상 제품이 된 지금, 모델만 따로 학습하고 harness를 나중에 붙이는 방식은 점점 어색해진다. 이 논문은 그 전환기에 나온 인프라 정리 문서로 읽는 게 맞다.
6. 마치며
화려한 알고리즘 논문은 아니다. 새 목적함수도, 새 아키텍처도 없다. 대신 모두가 조용히 다르게 처리하고 있던 부분을 꺼내서 수식으로 적고, 어느 쪽이 맞는지 ablation으로 보이고, 3,500줄로 구현해 공개했다. agentic RL 인프라를 실제로 만지는 입장이라면 §2만 읽어도 값어치를 한다.
개인적으로는 §4.3.2의 reward hacking 목록이 가장 인상적이었다. 에이전트가 git log를 뒤지고 pip download로 정답 소스를 받아오는 장면은, 보상 설계보다 환경 격리가 먼저라는 걸 아주 구체적으로 보여 준다. 그리고 그 방어가 §3.3의 Kubernetes 선택 덕분에 가능했다는 연결이 깔끔하다.
계보상 이어지는 논문으로는 원조 Agent Lightning (arXiv:2508.03680)과, 같은 proxy 기반 접근을 대규모 스케일에서 다룬 Polar (arXiv:2605.24220)를 함께 읽으면 좋다.
원문 참고 사항. v1 본문 Introduction에
enables enables로 중복된 오타가 있고, 평균 샘플 수가 Abstract·§2.2에서는 2.4, §4.3.3에서는 2.41로 표기되어 있다. 후속 버전에서 수정될 가능성이 있으니 인용 시 확인이 필요하다.
참고자료
- 원문: Agent Lightning v1.0: Towards Harnessed Agentic RL (arXiv:2608.17528)
- 선행 연구: Agent Lightning: Train ANY AI Agents with Reinforcement Learning (arXiv:2508.03680)
- 공식 코드: microsoft/agent-lightning · 문서
- 관련 프레임워크: Polar (arXiv:2605.24220) · verl / HybridFlow · AReaL (arXiv:2505.24298)
- 사용 데이터·벤치마크: SWE-smith · SWE-bench (arXiv:2310.06770) · Search-R1 (arXiv:2503.09516)
- 알고리즘 배경: GRPO / DeepSeekMath (arXiv:2402.03300) · RLOO (arXiv:2402.14740)
- harness: mini-SWE-agent
- 관련 블로그: No More Retokenization Drift (vLLM blog)
- 본문 Figure 1 이미지 출처: arXiv 네이티브 HTML (arxiv.org/html/2608.17528v1)