메인 콘텐츠로 건너뛰기

에이전트 루프 (OpenClaw)

에이전트형 루프는 에이전트의 전체 “실제” 실행입니다: 입력 수집 → 컨텍스트 조립 → 모델 추론 → 도구 실행 → 스트리밍 응답 → 영속화. 이는 메시지를 작업과 최종 응답으로 바꾸는 권위 있는 경로이며, 세션 상태를 일관되게 유지합니다. OpenClaw에서 루프는 세션당 하나의 직렬화된 실행이며, 모델이 생각하고, 도구를 호출하고, 출력을 스트리밍할 때 수명 주기 및 스트림 이벤트를 내보냅니다. 이 문서는 이 실제 루프가 엔드 투 엔드로 어떻게 연결되는지 설명합니다.

진입점

  • Gateway RPC: agentagent.wait.
  • CLI: agent 명령어.

작동 방식(상위 수준)

  1. agent RPC는 매개변수를 검증하고, 세션을 확인하며(sessionKey/sessionId), 세션 메타데이터를 영속화하고, 즉시 { runId, acceptedAt }를 반환합니다.
  2. agentCommand가 에이전트를 실행합니다:
    • 모델 + thinking/verbose 기본값 확인
    • Skills 스냅샷 로드
    • runEmbeddedPiAgent 호출 (pi-agent-core 런타임)
    • 임베디드 루프가 내보내지 않으면 수명 주기 end/error 내보내기
  3. runEmbeddedPiAgent:
    • 세션별 + 전역 큐를 통해 실행 직렬화
    • 모델 + auth 프로필 확인 및 pi 세션 빌드
    • pi 이벤트를 구독하고 assistant/tool 델타 스트리밍
    • 제한 시간 강제 적용 -> 초과 시 실행 중단
    • 페이로드 + 사용량 메타데이터 반환
  4. subscribeEmbeddedPiSessionpi-agent-core 이벤트를 OpenClaw agent 스트림으로 브리지합니다:
    • 도구 이벤트 => stream: "tool"
    • assistant 델타 => stream: "assistant"
    • 수명 주기 이벤트 => stream: "lifecycle" (phase: "start" | "end" | "error")
  5. agent.waitwaitForAgentRun을 사용합니다:
    • runId에 대한 수명 주기 end/error 대기
    • { status: ok|error|timeout, startedAt, endedAt, error? } 반환

큐잉 + 동시성

  • 실행은 세션 키(세션 레인)별로 직렬화되며, 필요에 따라 전역 레인을 통해서도 직렬화됩니다.
  • 이렇게 하면 도구/세션 경쟁 상태를 방지하고 세션 히스토리를 일관되게 유지할 수 있습니다.
  • 메시징 채널은 이 레인 시스템에 연결되는 큐 모드(collect/steer/followup)를 선택할 수 있습니다. 명령 큐를 참고하세요.

세션 + 워크스페이스 준비

  • 워크스페이스가 확인되고 생성되며, 샌드박스 실행은 샌드박스 워크스페이스 루트로 리디렉션될 수 있습니다.
  • Skills가 로드되거나(또는 스냅샷에서 재사용되거나) env 및 프롬프트에 주입됩니다.
  • 부트스트랩/컨텍스트 파일이 확인되고 시스템 프롬프트 보고서에 주입됩니다.
  • 세션 쓰기 잠금이 획득되며, 스트리밍 전에 SessionManager가 열리고 준비됩니다.

프롬프트 조립 + 시스템 프롬프트

  • 시스템 프롬프트는 OpenClaw의 기본 프롬프트, skills 프롬프트, 부트스트랩 컨텍스트, 실행별 오버라이드로 구성됩니다.
  • 모델별 제한과 compaction 예약 토큰이 강제 적용됩니다.
  • 모델이 무엇을 보는지에 대해서는 시스템 프롬프트를 참고하세요.

훅 지점(가로챌 수 있는 위치)

OpenClaw에는 두 가지 훅 시스템이 있습니다:
  • 내부 훅(Gateway hooks): 명령 및 수명 주기 이벤트를 위한 이벤트 기반 스크립트.
  • 플러그인 훅: 에이전트/도구 수명 주기 및 gateway 파이프라인 내부의 확장 지점.

내부 훅(Gateway hooks)

  • agent:bootstrap: 시스템 프롬프트가 최종 확정되기 전에 부트스트랩 파일을 빌드하는 동안 실행됩니다. 부트스트랩 컨텍스트 파일을 추가/제거하는 데 사용합니다.
  • 명령 훅: /new, /reset, /stop 및 기타 명령 이벤트(Hooks 문서 참고).
설정 및 예제는 Hooks를 참고하세요.

플러그인 훅(에이전트 + gateway 수명 주기)

이 훅들은 에이전트 루프 또는 gateway 파이프라인 내부에서 실행됩니다:
  • before_model_resolve: 세션 전(messages 없음)에 실행되어, 모델 확인 전에 provider/model을 결정적으로 오버라이드합니다.
  • before_prompt_build: 세션 로드 후(messages 포함) 실행되어, 프롬프트 제출 전에 prependContext, systemPrompt, prependSystemContext, 또는 appendSystemContext를 주입합니다. 턴별 동적 텍스트에는 prependContext를 사용하고, 시스템 프롬프트 공간에 배치되어야 하는 안정적인 지침에는 system-context 필드를 사용하세요.
  • before_agent_start: 레거시 호환성 훅으로, 두 단계 중 어느 쪽에서든 실행될 수 있습니다. 가능하면 위의 명시적 훅을 우선 사용하세요.
  • before_agent_reply: 인라인 작업 후, 그리고 LLM 호출 전에 실행되어, 플러그인이 해당 턴을 가져가 합성 응답을 반환하거나 턴 자체를 완전히 무음 처리할 수 있게 합니다.
  • agent_end: 완료 후 최종 메시지 목록과 실행 메타데이터를 검사합니다.
  • before_compaction / after_compaction: compaction 주기를 관찰하거나 주석을 추가합니다.
  • before_tool_call / after_tool_call: 도구 매개변수/결과를 가로챕니다.
  • before_install: 내장 스캔 결과를 검사하고 skill 또는 플러그인 설치를 선택적으로 차단합니다.
  • tool_result_persist: 도구 결과가 세션 기록에 기록되기 전에 동기적으로 변환합니다.
  • message_received / message_sending / message_sent: 수신 + 발신 메시지 훅.
  • session_start / session_end: 세션 수명 주기 경계.
  • gateway_start / gateway_stop: gateway 수명 주기 이벤트.
발신/도구 가드에 대한 훅 결정 규칙:
  • before_tool_call: { block: true }는 종료 동작이며 더 낮은 우선순위의 핸들러를 중단합니다.
  • before_tool_call: { block: false }는 no-op이며 이전 block을 해제하지 않습니다.
  • before_install: { block: true }는 종료 동작이며 더 낮은 우선순위의 핸들러를 중단합니다.
  • before_install: { block: false }는 no-op이며 이전 block을 해제하지 않습니다.
  • message_sending: { cancel: true }는 종료 동작이며 더 낮은 우선순위의 핸들러를 중단합니다.
  • message_sending: { cancel: false }는 no-op이며 이전 cancel을 해제하지 않습니다.
훅 API와 등록 세부 정보는 플러그인 훅을 참고하세요.

스트리밍 + 부분 응답

  • assistant 델타는 pi-agent-core에서 스트리밍되어 assistant 이벤트로 내보내집니다.
  • 블록 스트리밍은 text_end 또는 message_end에서 부분 응답을 내보낼 수 있습니다.
  • reasoning 스트리밍은 별도의 스트림으로 또는 블록 응답으로 내보낼 수 있습니다.
  • 청킹 및 블록 응답 동작은 스트리밍을 참고하세요.

도구 실행 + 메시징 도구

  • 도구 start/update/end 이벤트는 tool 스트림으로 내보내집니다.
  • 도구 결과는 로깅/내보내기 전에 크기와 이미지 페이로드 기준으로 정리됩니다.
  • 메시징 도구 전송은 중복된 assistant 확인 메시지를 억제하기 위해 추적됩니다.

응답 형태 조정 + 억제

  • 최종 페이로드는 다음으로 조립됩니다:
    • assistant 텍스트(및 선택적 reasoning)
    • 인라인 도구 요약(verbose + 허용 시)
    • 모델 오류 발생 시 assistant 오류 텍스트
  • 정확한 무음 토큰 NO_REPLY / no_reply는 발신 페이로드에서 필터링됩니다.
  • 메시징 도구 중복 항목은 최종 페이로드 목록에서 제거됩니다.
  • 렌더링 가능한 페이로드가 남지 않았고 도구에서 오류가 발생한 경우, 대체 도구 오류 응답이 내보내집니다 (단, 메시징 도구가 이미 사용자에게 보이는 응답을 보낸 경우는 제외).

Compaction + 재시도

  • 자동 compaction은 compaction 스트림 이벤트를 내보내고 재시도를 유발할 수 있습니다.
  • 재시도 시, 중복 출력을 방지하기 위해 메모리 내 버퍼와 도구 요약이 재설정됩니다.
  • compaction 파이프라인은 Compaction을 참고하세요.

이벤트 스트림(현재)

  • lifecycle: subscribeEmbeddedPiSession에서 내보냄(agentCommand에서 대체용으로도 내보냄)
  • assistant: pi-agent-core의 스트리밍 델타
  • tool: pi-agent-core의 스트리밍 도구 이벤트

채팅 채널 처리

  • assistant 델타는 채팅 delta 메시지로 버퍼링됩니다.
  • 채팅 final수명 주기 end/error에서 내보내집니다.

제한 시간

  • agent.wait 기본값: 30초(대기만 해당). timeoutMs 매개변수로 재정의합니다.
  • 에이전트 런타임: agents.defaults.timeoutSeconds 기본값은 172800초(48시간)이며, runEmbeddedPiAgent의 abort 타이머에서 강제 적용됩니다.
  • LLM 유휴 제한 시간: agents.defaults.llm.idleTimeoutSeconds는 유휴 시간 창 안에 응답 청크가 도착하지 않으면 모델 요청을 중단합니다. 느린 로컬 모델 또는 reasoning/도구 호출 provider에 대해 명시적으로 설정하세요. 비활성화하려면 0으로 설정하세요. 설정되지 않은 경우, OpenClaw는 agents.defaults.timeoutSeconds가 구성되어 있으면 이를 사용하고, 그렇지 않으면 60초를 사용합니다. 명시적인 LLM 또는 에이전트 제한 시간이 없는 cron 트리거 실행은 유휴 watchdog을 비활성화하고 cron 외부 제한 시간에 의존합니다.

조기에 종료될 수 있는 위치

  • 에이전트 제한 시간(abort)
  • AbortSignal(cancel)
  • Gateway 연결 해제 또는 RPC 제한 시간
  • agent.wait 제한 시간(대기만 해당하며, 에이전트를 중지하지는 않음)

관련 문서

  • 도구 — 사용 가능한 에이전트 도구
  • Hooks — 에이전트 수명 주기 이벤트에 의해 트리거되는 이벤트 기반 스크립트
  • Compaction — 긴 대화가 요약되는 방식
  • Exec Approvals — 셸 명령에 대한 승인 게이트
  • Thinking — thinking/reasoning 수준 구성