Skip to main content

에이전트 루프

Copilot CLI가 사용자 메시지를 엔드투엔드로 처리하는 방식: 프롬프트부터 session.idle까지.

아키텍처

다이어그램: 설명된 프로세스를 보여 주는 그래프 다이어그램

SDK는 전송 계층으로, JSON-RPC 통해 Copilot CLI 프롬프트를 보내고 이벤트를 앱에 다시 표시합니다. CLI는 에이전트 도구 사용 루프를 실행하는 오케스트레이터로, 작업이 완료될 때까지 하나 이상의 LLM API 호출을 수행합니다.

도구 사용 루프

호출 session.send({ prompt })할 때 CLI는 루프를 입력합니다.

다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.

모델은 각 호출에 대한 전체 대화 기록 (시스템 프롬프트, 사용자 메시지 및 모든 이전 도구 호출 및 결과)을 확인합니다.

주요 인사이트: 이 루프의 각 반복은 이벤트 로그에서 한 assistant.turn_start / assistant.turn_end 쌍으로 표시되는 하나의 LLM API 호출입니다. 숨겨진 호출이 없습니다.

턴—무엇인가

은 단일 LLM API 호출 및 그 결과입니다.

  1. CLI는 LLM에 대화 기록을 보냅니다.
  2. LLM이 응답합니다(도구 요청이 있을 수 있음).
  3. 도구가 요청된 경우 CLI는 도구를 실행합니다.
  4. assistant.turn_end 가 내보내집니다.

단일 사용자 메시지는 일반적으로 여러 번 발생합니다. 예를 들어 "X는 이 코드베이스에서 어떻게 작동하나요?"와 같은 질문이 있습니다. 다음을 생성할 수 있습니다:

회전모델에서 수행하는 작업toolRequests?
1코드베이스를 검색하기 위해 grepglob을 호출합니다
✅ 예
2검색 결과에 따라 특정 파일을 읽습니다.
✅ 예
3더 심층적인 컨텍스트를 위해 더 많은 파일을 읽습니다.
✅ 예
4최종 텍스트 대답을 생성합니다.
❌ → 루프 끝 없음

모델은 각 턴에서 더 많은 도구를 요청할지 아니면 최종 답변을 생성할지 결정합니다. 각 호출은 전체 누적 컨텍스트 (모든 이전 도구 호출 및 결과)를 확인하므로 충분한 정보가 있는지 여부에 대한 정보에 입각한 결정을 내릴 수 있습니다.

다중 턴 상호 작용에 대한 이벤트 흐름

다이어그램: 설명된 프로세스를 보여 주는 순서도입니다.

각 턴을 트리거하는 사람은 누구인가요?

Actor책임
고객님의 앱를 통해 초기 프롬프트를 보냅니다. session.send()
Copilot CLI도구 사용 루프를 실행합니다. 도구를 실행하고 다음 턴을 위해 결과를 LLM에 다시 공급합니다.
Llm도구를 요청할지(계속 반복) 또는 최종 응답 생성(중지) 결정
SDK이벤트를 전달합니다. 는 루프를 제어하지 않습니다.

CLI는 그저 기계적으로 작동합니다. "모델이 도구를 요청함 → 실행 → 모델을 다시 호출." 이 모델은 중지할 시기를 결정하는 결정자입니다.

session.idlesession.task_complete

이는 매우 다른 보장을 가진 두 가지 서로 다른 완료 신호입니다.

session.idle

  • 도구 사용 루프가 종료될 때 항상 내보내
  • 임시: 디스크에 유지되지 않고 세션 다시 시작 시 재생되지 않음
  • 의미: "에이전트가 처리를 중지했으며 다음 메시지에 대한 준비가 되었습니다."
  • 이를 신뢰할 수 있는 "완료" 신호로 사용

SDK의 sendAndWait() 메서드는 이 이벤트를 기다립니다.

// Blocks until session.idle fires
const response = await session.sendAndWait({ prompt: "Fix the bug" });

session.task_complete

  • 선택적으로 내보내기: 모델이 명시적으로 신호를 보낼 것을 요구합니다.
  • 지속형: 디스크의 세션 이벤트 로그에 저장
  • 의미: "에이전트는 전체 작업이 완료된 것으로 간주합니다."
  • 선택적 summary 필드를 전달합니다.
session.on("session.task_complete", (event) => {
    console.log("Task done:", event.data.summary);
});

Autopilot 모드: CLI가 task_complete를 요청함

autopilot 모드(헤드리스/자율 작업)에서 CLI는 모델이 호출task_complete되었는지 여부를 적극적으로 추적합니다. 그것 없이 도구 사용 루프가 끝나면, CLI는 모델을 유도하는 합성 사용자 메시지를 삽입합니다:

"task_complete 도구를 사용하여 작업을 완료로 표시하지 않았습니다. 계획 중인 경우 계획을 중지하고 구현을 시작합니다. 작업을 완전히 완료할 때까지 완료되지 않습니다."

이렇게 하면 도구 사용 루프가 사실상 다시 시작됩니다. 모델은 이 신호를 새로운 사용자 메시지로 간주하고 작업을 계속 수행합니다. 또한 이 유도는 모델에 task_complete을(를) 성급하게 호출하지 않도록 지시합니다.

  • 열린 질문이 있는 경우 호출하지 마세요. 결정을 내리고 계속 작업하세요.
  • 오류가 발생한 경우 호출하지 마세요. 해결해 보세요.
  • 남아 있는 단계가 있으면 호출하지 말고 먼저 완료하세요

이렇게 하면 autopilot에서 2단계 완성 메커니즘 이 만들어집니다.

  1. 모델이 요약과 함께 task_complete을 호출 → CLI가 session.task_complete을 출력 → 완료
  2. 모델이 이를 호출하지 않고 중지됨 → CLI가 유도함 → 모델이 계속 진행되거나 task_complete를 호출함

task_complete이(가) 표시되지 않을 수 있는 이유

대화형 모드(일반 채팅)에서는 CLI가 task_complete을(를) 요청하지 않습니다. 모델은 아예 건너뛸 수 있습니다. 일반적인 원인:

  • 대화형 Q&A: 모델은 질문에 답변하고 단순히 중지합니다. 완료할 개별 "작업"이 없습니다.
  • 모델 재량: 모델은 작업 완료 신호를 호출하지 않고 최종 텍스트 응답을 생성합니다.
  • 중단된 세션: 모델이 완료 지점에 도달하기 전에 세션이 종료됩니다.

CLI는 어쨌든 session.idle를 내보냅니다. 이는 의미적 신호(모델이 완료됐다고 판단함)가 아니라 기계적 신호(루프가 끝났다는 뜻)이기 때문입니다.

어느 것을 사용하시겠습니까?

사용 사례신호
"에이전트가 처리를 완료할 때까지 기다립니다."
session.idle
"코딩 작업이 완료되면 알 수 있습니다."
session.task_complete (최선의 노력)
"시간 제한/오류 처리"
session.idle

session.error ✅ |

LLM 호출 수 계산

이벤트 로그의 assistant.turn_start / assistant.turn_end 쌍 수는 총 LLM API 호출 수와 같습니다. 계획, 평가 또는 완료 확인에 대한 숨겨진 호출은 없습니다.

세션의 턴 카운트를 검사하려면:

# Count turns in a session's event log
grep -c "assistant.turn_start" ~/.copilot/session-state/<sessionId>/events.jsonl

추가 읽기