Skip to content

feat: Native Anthropic pass-through for Claude models (no translation)Β #38

@HXYerror

Description

@HXYerror

πŸ”¬ Research Finding (live-tested with copilot-models-litellm, enterprise endpoint β€” 2026-05-10)

GitHub Copilot upstream (api.enterprise.githubcopilot.com) natively supports the Anthropic Messages API at /v1/messages for all Claude models β€” no translation needed.

Model Γ— Endpoint matrix (10 Claude models tested)

Model /v1/messages (Anthropic native) /chat/completions (OpenAI)
claude-sonnet-4.5 βœ… βœ…
claude-sonnet-4.6 βœ… βœ…
claude-opus-4.5 βœ… βœ…
claude-opus-4.6 βœ… βœ…
claude-opus-4.6-1m βœ… βœ…
claude-opus-4.7 βœ… βœ…
claude-opus-4.7-high βœ… βœ…
claude-opus-4.7-xhigh βœ… βœ…
claude-opus-4.7-1m-internal βœ… βœ…
claude-haiku-4.5 βœ… βœ…

Feature matrix (all tested on /v1/messages native path)

Feature Status Notes
Basic chat βœ… Native {type:"message", content:[...]} response
Streaming SSE βœ… message_start / content_block_* / message_delta / message_stop
thinking blocks (4.5/4.6) βœ… Full thinking content + signature returned
thinking blocks (4.7+) ⚠️ New API: "type": "adaptive" + output_config.effort; "enabled" rejected with 400
tools / tool_use βœ… stop_reason: "tool_use", correct input
thinking + tools together βœ… Both blocks in response simultaneously
system prompt βœ… String and array form
cache_control (ephemeral) βœ… cache_creation_input_tokens in usage
top_k βœ… Accepted without error
URL images ❌ "external image URLs are not supported"
Base64 images βœ… (verified in prior tests)
Multi-turn βœ… History forwarded correctly

New API format for claude-opus-4.7+ thinking

{
  "thinking": {"type": "adaptive"},
  "output_config": {"effort": "medium"}
}

Old "type": "enabled" format rejected with:

"thinking.type.enabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort"

Native usage fields (richer than OpenAI translation path)

{
  "usage": {
    "input_tokens": 47,
    "output_tokens": 136,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 0,
    "cache_creation": {
      "ephemeral_1h_input_tokens": 0,
      "ephemeral_5m_input_tokens": 0
    }
  }
}

Problem: Current copilot-api translates everything through OpenAI

All /v1/messages requests go through:
non-stream-translation.ts β†’ Copilot /chat/completions β†’ stream-translation.ts

This loses:

  • thinking blocks entirely (dropped on input, never returned on output)
  • top_k (no OpenAI equivalent β†’ dropped)
  • cache_control, cache_creation_input_tokens
  • signature on thinking blocks (required for multi-turn reasoning)
  • New claude-opus-4.7+ thinking API (adaptive + output_config.effort)

Additionally non-stream-translation.ts:305 has a stale comment: "GitHub Copilot doesn't generate thinking blocks" β€” factually wrong.


Proposed fix: Direct Anthropic pass-through for all Claude models

When the model is Claude (vendor=Anthropic), forward the request directly to ${copilotBaseUrl}/v1/messages and pass the response back unchanged.

Client (Claude Code / Anthropic SDK)
  POST /v1/messages  {model: "claude-sonnet-4.6", thinking: ...}
        ↓
  route.ts β†’ detect Claude model
        ↓
  create-messages-native.ts
  β†’ POST api.enterprise.githubcopilot.com/v1/messages (native Anthropic format)
  ← response passed through unchanged (thinking blocks, signature, rich usage all intact)
        ↓
Client receives native Anthropic response

Non-Claude models (gpt-4o etc.) keep the existing translation path.


Sub-issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    anthropicAnthropic Messages API compatibilityepicTracking issue spanning multiple sub-issuesresponses-apiOpenAI /v1/responses API support

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions