feat(copilot): support Claude Code subscription auth for SDK mode - #12288
Conversation
Add `CHAT_USE_CLAUDE_CODE_SUBSCRIPTION` config option that lets the copilot SDK path use the Claude CLI's own subscription auth (from `claude login`) instead of requiring API keys. When enabled: - SDK subprocess inherits CLI credentials (no ANTHROPIC_BASE_URL/AUTH_TOKEN override) - Forces SDK mode regardless of LaunchDarkly flag (baseline can't use CLI auth) - Validates CLI installation on first use with clear error messages Setup: `npm install -g @anthropic-ai/claude-code && claude login`, then set `CHAT_USE_CLAUDE_CODE_SUBSCRIPTION=true`.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a Claude Code CLI subscription mode: new Changes
Sequence Diagram(s)sequenceDiagram
participant Processor
participant ConfigFF as Config/FeatureFlag
participant SDKService
participant ClaudeCLI
participant ExternalAPI
Processor->>ConfigFF: read use_claude_code_subscription + COPILOT_SDK
alt use SDK (flag or subscription)
Processor->>SDKService: stream_chat_completion_sdk(...)
SDKService->>ClaudeCLI: validate CLI & version (if subscription)
ClaudeCLI-->>SDKService: CLI OK / model default
SDKService->>ExternalAPI: stream via SDK/CLI bridge
ExternalAPI-->>SDKService: responses
SDKService-->>Processor: stream events
else use API key
Processor->>SDKService: stream_chat_completion_sdk(...)
SDKService->>ExternalAPI: stream via API key/base URL
ExternalAPI-->>SDKService: responses
SDKService-->>Processor: stream events
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔍 PR Overlap DetectionThis check compares your PR against all other open PRs targeting the same branch to detect potential merge conflicts early. 🔴 Merge Conflicts DetectedThe following PRs have been tested and will have merge conflicts if merged after this PR. Consider coordinating with the authors.
🟡 Medium Risk — Some Line OverlapThese PRs have some overlapping changes:
🟢 Low Risk — File Overlap OnlyThese PRs touch the same files but different sections (click to expand)
Summary: 3 conflict(s), 1 medium risk, 9 low risk (out of 13 PRs with file overlap) Auto-generated on push. Ignores: |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@autogpt_platform/backend/backend/copilot/sdk/service.py`:
- Around line 301-343: The function _validate_claude_code_subscription currently
only checks that the Claude CLI binary exists and responds to --version but the
docstring misleadingly claims it validates authentication and will run `claude
login`; update the docstring to accurately state that when
config.use_claude_code_subscription is true it only verifies the CLI binary is
present and responsive via --version (and may raise if missing, non-zero, or
times out) and remove any mention of attempting interactive login; reference the
symbols _validate_claude_code_subscription, config.use_claude_code_subscription,
claude_path, and the subprocess.run --version check so reviewers can locate and
edit the docstring to match the implementation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: eaf01cfc-f9f3-44c8-952a-f5614b61319c
📒 Files selected for processing (3)
autogpt_platform/backend/backend/copilot/config.pyautogpt_platform/backend/backend/copilot/executor/processor.pyautogpt_platform/backend/backend/copilot/sdk/service.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: types
- GitHub Check: Seer Code Review
- GitHub Check: test (3.11)
- GitHub Check: test (3.12)
- GitHub Check: test (3.13)
- GitHub Check: Analyze (typescript)
- GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (4)
autogpt_platform/backend/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development
Files:
autogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/copilot/config.pyautogpt_platform/backend/backend/copilot/executor/processor.py
autogpt_platform/backend/**/*.{py,txt}
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use
poetry runprefix for all Python commands, including testing, linting, formatting, and migrations
Files:
autogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/copilot/config.pyautogpt_platform/backend/backend/copilot/executor/processor.py
autogpt_platform/backend/backend/**/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings
Files:
autogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/copilot/config.pyautogpt_platform/backend/backend/copilot/executor/processor.py
autogpt_platform/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Format Python code with
poetry run format
Files:
autogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/copilot/config.pyautogpt_platform/backend/backend/copilot/executor/processor.py
🧠 Learnings (4)
📓 Common learnings
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12284
File: autogpt_platform/frontend/src/app/api/openapi.json:11897-11900
Timestamp: 2026-03-04T23:58:09.319Z
Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12284`
Backend/frontend OpenAPI codegen convention: In backend/api/features/store/model.py, the StoreSubmission and StoreSubmissionAdminView models define submitted_at: datetime | None, changes_summary: str | None, and instructions: str | None with no default. This is intentional to produce “required but nullable” fields in OpenAPI (properties appear in required[] and use anyOf [type, null]). This matches Prisma’s submittedAt DateTime? and changesSummary String?. Do not flag this as a required/nullable mismatch.
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.
Applied to files:
autogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/copilot/config.pyautogpt_platform/backend/backend/copilot/executor/processor.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.
Applied to files:
autogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/copilot/config.pyautogpt_platform/backend/backend/copilot/executor/processor.py
📚 Learning: 2026-02-20T03:28:06.619Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12173
File: autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py:153-179
Timestamp: 2026-02-20T03:28:06.619Z
Learning: The copilot executor (`backend.copilot.executor`) runs in its own Docker container with Python 3.13, so Python 3.11+ features like `asyncio.timeout()` are available in copilot code even though the general backend pyproject.toml specifies `python = ">=3.10,<3.14"`.
Applied to files:
autogpt_platform/backend/backend/copilot/executor/processor.py
🔇 Additional comments (4)
autogpt_platform/backend/backend/copilot/executor/processor.py (1)
211-224: SDK override for subscription mode is correctly wired.Line 214 correctly forces SDK mode when
use_claude_code_subscriptionis true, while preserving feature-flag control otherwise.autogpt_platform/backend/backend/copilot/config.py (1)
90-94: Config toggle and env plumbing look solid.The new field and validator cleanly add
CHAT_USE_CLAUDE_CODE_SUBSCRIPTIONwith a safe default (False) and expected truthy parsing behavior.Also applies to: 175-183
autogpt_platform/backend/backend/copilot/sdk/service.py (2)
365-372: Subscription env handoff is clean.Returning early from
_build_sdk_env()in subscription mode correctly avoids injectingANTHROPIC_*overrides and lets CLI credentials flow through as intended.
782-793: Credential guard correctly exempts subscription mode.The updated guard and error text now properly allow SDK execution without API keys when
CHAT_USE_CLAUDE_CODE_SUBSCRIPTION=true.
…PI_KEY fallback - Replace lru_cache(maxsize=1) with @functools.cache (simpler, no args) - Restructure _build_sdk_env to use if/elif instead of early return - Add ANTHROPIC_API_KEY as last fallback in config.api_key resolver - Simplify fail-fast check to use config.api_key instead of os.environ
- Clear ANTHROPIC_API_KEY/AUTH_TOKEN/BASE_URL in subprocess env so CLI uses subscription auth instead of inheriting parent's API key - Skip model override when using subscription (let CLI use plan default) - Share ANTHROPIC_CUSTOM_HEADERS between subscription and proxy branches - Bump claude-agent-sdk to ^0.1.46 (handles unknown message types like rate_limit_event gracefully) - Use `not v` instead of `v is None` in config validators so empty strings trigger env var fallback
…ess calls @functools.cache doesn't cache exceptions, so validation failures would re-execute the blocking subprocess.run on every request. Replace with a single module-level sentinel that caches both success and failure.
….cache Validation failure means the CLI isn't installed — a config error requiring process restart — so caching exceptions isn't needed.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@autogpt_platform/backend/backend/copilot/sdk/service.py`:
- Around line 381-396: The code currently always builds and sets
ANTHROPIC_CUSTOM_HEADERS using _safe, headers, session_id, and user_id; restrict
this so headers are only injected when the request is routed through your
proxy/OpenRouter path: wrap the headers construction and
env["ANTHROPIC_CUSTOM_HEADERS"] assignment in a conditional that checks the
client routing mode (e.g., an existing proxy/OpenRouter indicator such as
openrouter_url, proxy_url, or a transport/openrouter flag) and skip
building/setting these headers for direct Anthropic/subscription mode; keep the
_safe function and header format unchanged but move them inside that guard so
internal session_id/user_id are not sent to Anthropic unless using the
OpenRouter proxy.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 35a2c2dd-657d-4aa6-9305-cdca0cf8374d
📒 Files selected for processing (1)
autogpt_platform/backend/backend/copilot/sdk/service.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: types
- GitHub Check: test (3.11)
- GitHub Check: test (3.13)
- GitHub Check: test (3.12)
- GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (4)
autogpt_platform/backend/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development
Files:
autogpt_platform/backend/backend/copilot/sdk/service.py
autogpt_platform/backend/**/*.{py,txt}
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use
poetry runprefix for all Python commands, including testing, linting, formatting, and migrations
Files:
autogpt_platform/backend/backend/copilot/sdk/service.py
autogpt_platform/backend/backend/**/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings
Files:
autogpt_platform/backend/backend/copilot/sdk/service.py
autogpt_platform/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Format Python code with
poetry run format
Files:
autogpt_platform/backend/backend/copilot/sdk/service.py
🧠 Learnings (4)
📓 Common learnings
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12284
File: autogpt_platform/frontend/src/app/api/openapi.json:11897-11900
Timestamp: 2026-03-04T23:58:09.319Z
Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12284`
Backend/frontend OpenAPI codegen convention: In backend/api/features/store/model.py, the StoreSubmission and StoreSubmissionAdminView models define submitted_at: datetime | None, changes_summary: str | None, and instructions: str | None with no default. This is intentional to produce “required but nullable” fields in OpenAPI (properties appear in required[] and use anyOf [type, null]). This matches Prisma’s submittedAt DateTime? and changesSummary String?. Do not flag this as a required/nullable mismatch.
📚 Learning: 2026-02-04T16:50:51.495Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-04T16:50:51.495Z
Learning: Applies to autogpt_platform/**/data/*.py : For changes touching `data/*.py`, validate user ID checks or explain why not needed
Applied to files:
autogpt_platform/backend/backend/copilot/sdk/service.py
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.
Applied to files:
autogpt_platform/backend/backend/copilot/sdk/service.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.
Applied to files:
autogpt_platform/backend/backend/copilot/sdk/service.py
🔇 Additional comments (3)
autogpt_platform/backend/backend/copilot/sdk/service.py (3)
287-301: Model resolution fallback for subscription mode looks correct.Line 300–301 cleanly defers model choice to Claude CLI defaults when subscription auth is enabled and no explicit SDK model is configured.
308-337: Claude CLI preflight validation is a solid fail-fast addition.Line 316–336 provides clear install/runtime errors and a bounded timeout for the CLI check.
776-787: Credential error message improvement is clear and actionable.Line 784–787 now explicitly documents both API-key and Claude subscription auth paths for operators.
The SDK CLI reads ANTHROPIC_API_KEY from the env natively. Including it in config.api_key would pair it with the OpenRouter base_url default, sending Anthropic credentials to OpenRouter and causing auth failures.
- Only inject ANTHROPIC_CUSTOM_HEADERS when routing through OpenRouter (ANTHROPIC_BASE_URL is set). In subscription mode they're meaningless and would leak internal session/user IDs to Anthropic directly. - Remove redundant `not sdk_env` from fail-fast check — sdk_env is always populated with headers now. The meaningful checks are `not config.api_key` and `not config.use_claude_code_subscription`.
|
Addressed all review comments in latest commits:
|
…uests Requested by @Swiftyos PR #12288 bumped claude-agent-sdk from 0.1.39 to ^0.1.46, which upgraded the bundled Claude CLI from v2.1.49 to v2.1.69. The newer CLI produces malformed Anthropic API requests — messages[3].content contains array elements that are neither valid text nor image blocks, causing 400 errors on first message. Pin to exact version 0.1.39 (not ^) until the upstream CLI bug is resolved. Our code doesn't use any 0.1.46-specific SDK APIs.
…ntent block validation error (#12294) Requested by @majdyz ## Problem CoPilot throws `400 Invalid Anthropic Messages API request` errors on first message, both locally and on Dev. ## Root Cause The CLI's built-in `ToolSearch` tool returns `tool_reference` content blocks (`{"type": "tool_reference", "tool_name": "mcp__copilot__find_block"}`). When the CLI constructs the next Anthropic API request, it passes these blocks as-is in the `tool_result.content` field. However, the Anthropic Messages API only accepts `text` and `image` content block types in tool results. This causes a Zod validation error: ``` messages[3].content[0].content: Invalid input: expected string, received array ``` The error only manifests when using **OpenRouter** (`ANTHROPIC_BASE_URL` set) because the Anthropic TypeScript SDK performs stricter client-side Zod validation in that code path vs the subscription auth path. PR #12288 bumped `claude-agent-sdk` from `0.1.39` to `^0.1.46`, which upgraded the bundled Claude CLI from `v2.1.49` to `v2.1.69` where this issue was introduced. ## Fix Pin to `0.1.45` which has a CLI version that doesn't produce `tool_reference` content blocks in tool results. ## Testing - CoPilot first message should work without 400 errors via OpenRouter - SDK compat tests should still pass
…ntent block validation error (#12294) Requested by @majdyz ## Problem CoPilot throws `400 Invalid Anthropic Messages API request` errors on first message, both locally and on Dev. ## Root Cause The CLI's built-in `ToolSearch` tool returns `tool_reference` content blocks (`{"type": "tool_reference", "tool_name": "mcp__copilot__find_block"}`). When the CLI constructs the next Anthropic API request, it passes these blocks as-is in the `tool_result.content` field. However, the Anthropic Messages API only accepts `text` and `image` content block types in tool results. This causes a Zod validation error: ``` messages[3].content[0].content: Invalid input: expected string, received array ``` The error only manifests when using **OpenRouter** (`ANTHROPIC_BASE_URL` set) because the Anthropic TypeScript SDK performs stricter client-side Zod validation in that code path vs the subscription auth path. PR #12288 bumped `claude-agent-sdk` from `0.1.39` to `^0.1.46`, which upgraded the bundled Claude CLI from `v2.1.49` to `v2.1.69` where this issue was introduced. ## Fix Pin to `0.1.45` which has a CLI version that doesn't produce `tool_reference` content blocks in tool results. ## Testing - CoPilot first message should work without 400 errors via OpenRouter - SDK compat tests should still pass
Summary
CHAT_USE_CLAUDE_CODE_SUBSCRIPTIONconfig flag to let the copilot SDK path use the Claude CLI's own subscription auth (fromclaude login) instead of API keysANTHROPIC_BASE_URL/AUTH_TOKENoverride is injectedopenai.AsyncOpenAIwhich requires an API key)Setup
npm install -g @anthropic-ai/claude-code claude login # then set in .env: CHAT_USE_CLAUDE_CODE_SUBSCRIPTION=trueChanges
copilot/config.pyuse_claude_code_subscriptionfield + env var validatorcopilot/sdk/service.py_validate_claude_code_subscription()+_build_sdk_env()early-return + fail-fast guardcopilot/executor/processor.pyorTest plan
CHAT_USE_CLAUDE_CODE_SUBSCRIPTION=true, unset all API keysclaude loginon the host