CLI 백엔드(대체 런타임)
OpenClaw는 API provider가 중단되었거나, 속도 제한에 걸렸거나, 일시적으로 오동작할 때 텍스트 전용 대체 경로로 로컬 AI CLI를 실행할 수 있습니다. 이는 의도적으로 보수적으로 설계되었습니다:- OpenClaw 도구는 직접 주입되지 않지만,
bundleMcp: true인 백엔드(Claude CLI 기본값)는 loopback MCP 브리지를 통해 gateway 도구를 받을 수 있습니다. - JSONL 스트리밍(Claude CLI는
--output-format stream-json을--include-partial-messages와 함께 사용하며, 프롬프트는 stdin으로 전송됨). - 세션이 지원됩니다(후속 턴이 일관성을 유지하도록).
- CLI가 이미지 경로를 허용한다면 이미지를 전달할 수 있습니다.
초보자용 빠른 시작
아무 config 없이도 Claude CLI를 사용할 수 있습니다(번들 Anthropic plugin이 기본 백엔드를 등록합니다):agents.defaults.cliBackends 아래에서 해당 백엔드를 명시적으로 참조하면
소유 번들 plugin을 자동 로드합니다.
대체 경로로 사용하기
기본 모델이 실패할 때만 실행되도록 대체 목록에 CLI 백엔드를 추가하세요:agents.defaults.models(허용 목록)을 사용한다면claude-cli/...도 포함해야 합니다.- 기본 provider가 실패하면(인증, 속도 제한, 시간 초과) OpenClaw가 다음으로 CLI 백엔드를 시도합니다.
- 번들 Claude CLI 백엔드는 여전히
claude-cli/opus,claude-cli/opus-4.6,claude-cli/sonnet같은 짧은 별칭을 허용하지만, 문서와 config 예시는 정식claude-cli/claude-*ref를 사용합니다.
구성 개요
모든 CLI 백엔드는 다음 아래에 있습니다:claude-cli, my-cli)로 키 지정됩니다.
provider id는 모델 ref의 왼쪽 부분이 됩니다:
예시 config
작동 방식
- provider 접두사(
claude-cli/...)를 기준으로 백엔드를 선택합니다. - 동일한 OpenClaw 프롬프트 + 워크스페이스 context를 사용해 시스템 프롬프트를 구성합니다.
- 기록이 일관되게 유지되도록 세션 id(지원되는 경우)와 함께 CLI를 실행합니다.
- 출력을 파싱하고(JSON 또는 일반 텍스트) 최종 텍스트를 반환합니다.
- 백엔드별로 세션 id를 유지하므로 후속 턴이 같은 CLI 세션을 재사용합니다.
세션
- CLI가 세션을 지원한다면
sessionArg(예:--session-id) 또는 ID를 여러 플래그에 삽입해야 하는 경우sessionArgs(플레이스홀더{sessionId})를 설정하세요. - CLI가 다른 플래그를 가진 resume 하위 명령을 사용한다면
resumeArgs(args를 대체함)를 설정하고, 필요하면resumeOutput(JSON이 아닌 resume용)도 설정하세요. sessionMode:always: 항상 세션 id를 보냅니다(저장된 값이 없으면 새 UUID).existing: 이전에 저장된 세션 id가 있을 때만 보냅니다.none: 세션 id를 보내지 않습니다.
serialize: true는 같은 lane 실행의 순서를 유지합니다.- 대부분의 CLI는 하나의 provider lane에서 직렬화합니다.
claude-cli는 더 좁습니다. 재개된 실행은 Claude 세션 id별로 직렬화되고, 새 실행은 워크스페이스 경로별로 직렬화됩니다. 독립적인 워크스페이스는 병렬 실행할 수 있습니다.- OpenClaw는 백엔드 인증 상태가 변경되면 저장된 CLI 세션 재사용을 버립니다. 여기에는 재로그인, 토큰 교체, 변경된 auth profile 자격 증명이 포함됩니다.
이미지(전달)
CLI가 이미지 경로를 허용한다면imageArg를 설정하세요:
imageArg가 설정되어 있으면 해당
경로가 CLI 인수로 전달됩니다. imageArg가 없으면 OpenClaw는
파일 경로를 프롬프트에 추가합니다(경로 주입). 이것만으로도 일반 경로에서 로컬 파일을 자동 로드하는
CLI에는 충분합니다(Claude CLI 동작).
입력 / 출력
output: "json"(기본값)은 JSON을 파싱하여 텍스트 + 세션 id를 추출하려고 시도합니다.- Gemini CLI JSON 출력의 경우 OpenClaw는
usage가 없거나 비어 있으면response에서 응답 텍스트를,stats에서 사용량을 읽습니다. output: "jsonl"은 JSONL 스트림(예: Claude CLIstream-json및 Codex CLI--json)을 파싱하고 최종 agent 메시지와 존재하는 경우 세션 식별자를 추출합니다.output: "text"는 stdout을 최종 응답으로 취급합니다.
input: "arg"(기본값)는 프롬프트를 마지막 CLI 인수로 전달합니다.input: "stdin"은 프롬프트를 stdin으로 보냅니다.- 프롬프트가 매우 길고
maxPromptArgChars가 설정되어 있으면 stdin이 사용됩니다.
기본값(plugin 소유)
번들 Anthropic plugin은claude-cli에 대한 기본값을 등록합니다:
command: "claude"args: ["-p", "--output-format", "stream-json", "--include-partial-messages", "--verbose", "--permission-mode", "bypassPermissions"]resumeArgs: ["-p", "--output-format", "stream-json", "--include-partial-messages", "--verbose", "--permission-mode", "bypassPermissions", "--resume", "{sessionId}"]output: "jsonl"input: "stdin"modelArg: "--model"systemPromptArg: "--append-system-prompt"sessionArg: "--session-id"systemPromptWhen: "first"sessionMode: "always"
codex-cli에 대한 기본값을 등록합니다:
command: "codex"args: ["exec","--json","--color","never","--sandbox","workspace-write","--skip-git-repo-check"]resumeArgs: ["exec","resume","{sessionId}","--color","never","--sandbox","workspace-write","--skip-git-repo-check"]output: "jsonl"resumeOutput: "text"modelArg: "--model"imageArg: "--image"sessionMode: "existing"
google-gemini-cli에 대한 기본값을 등록합니다:
command: "gemini"args: ["--prompt", "--output-format", "json"]resumeArgs: ["--resume", "{sessionId}", "--prompt", "--output-format", "json"]modelArg: "--model"sessionMode: "existing"sessionIdFields: ["session_id", "sessionId"]
gemini로 사용할 수 있어야 합니다(brew install gemini-cli 또는
npm install -g @google/gemini-cli).
Gemini CLI JSON 참고 사항:
- 응답 텍스트는 JSON
response필드에서 읽습니다. usage가 없거나 비어 있으면 사용량은stats로 대체됩니다.stats.cached는 OpenClawcacheRead로 정규화됩니다.stats.input이 없으면 OpenClaw는stats.input_tokens - stats.cached에서 입력 토큰을 계산합니다.
command 경로).
plugin 소유 기본값
CLI 백엔드 기본값은 이제 plugin 표면의 일부입니다:- plugin은
api.registerCliBackend(...)로 이를 등록합니다. - 백엔드
id는 모델 ref의 provider 접두사가 됩니다. agents.defaults.cliBackends.<id>아래의 사용자 config는 여전히 plugin 기본값을 재정의합니다.- 백엔드별 config 정리는 선택적
normalizeConfig훅을 통해 plugin 소유로 유지됩니다.
Bundle MCP 오버레이
CLI 백엔드는 OpenClaw 도구 호출을 직접 받지 않지만, 백엔드는bundleMcp: true로 생성된 MCP config 오버레이를 선택적으로 사용할 수 있습니다.
현재 번들 동작:
claude-cli:bundleMcp: true(기본값)codex-cli: bundle MCP 오버레이 없음google-gemini-cli: bundle MCP 오버레이 없음
- gateway 도구를 CLI 프로세스에 노출하는 loopback HTTP MCP 서버를 실행합니다
- 세션별 토큰(
OPENCLAW_MCP_TOKEN)으로 브리지를 인증합니다 - 도구 접근을 현재 세션, 계정, 채널 context로 제한합니다
- 현재 워크스페이스에 대해 활성화된 bundle-MCP 서버를 로드합니다
- 이를 기존 백엔드
--mcp-config와 병합합니다 - 생성된 파일을 전달하도록 CLI 인수를
--strict-mcp-config --mcp-config <generated-file>로 다시 작성합니다
--strict-mcp-config 플래그는 Claude CLI가 주변
사용자 수준 또는 전역 MCP 서버를 상속하지 못하게 합니다. MCP 서버가 활성화되어 있지 않더라도 OpenClaw는 백그라운드 실행이 격리된 상태를 유지하도록 엄격한 빈 config를 계속 주입합니다.
제한 사항
- 직접적인 OpenClaw 도구 호출은 없습니다. OpenClaw는
CLI 백엔드 프로토콜에 도구 호출을 주입하지 않습니다. 그러나
bundleMcp: true인 백엔드(기본값인 Claude CLI)는 loopback MCP 브리지를 통해 gateway 도구를 받으므로, Claude CLI는 자체 native MCP 지원을 통해 OpenClaw 도구를 호출할 수 있습니다. - 스트리밍은 백엔드별입니다. Claude CLI는 JSONL 스트리밍
(
stream-json+--include-partial-messages)을 사용합니다. 다른 CLI 백엔드는 종료 시점까지 버퍼링될 수 있습니다. - 구조화된 출력은 CLI의 JSON 형식에 따라 달라집니다.
- Codex CLI 세션은 텍스트 출력으로 resume하므로(JSONL 아님),
초기
--json실행보다 구조화 정도가 낮습니다. OpenClaw 세션은 여전히 정상적으로 동작합니다.
문제 해결
- CLI를 찾을 수 없음:
command를 전체 경로로 설정하세요. - 잘못된 모델 이름:
modelAliases를 사용해provider/model→ CLI 모델로 매핑하세요. - 세션 연속성이 없음:
sessionArg가 설정되어 있고sessionMode가none이 아닌지 확인하세요(Codex CLI는 현재 JSON 출력으로 resume할 수 없음). - 이미지가 무시됨:
imageArg를 설정하고(그리고 CLI가 파일 경로를 지원하는지 확인하세요).