How CCX Messages, Chat, Responses, Gemini, and Images Channels Differ: Protocol & Implementation Guide
In CCX, the five channels differ primarily by their upstream protocols: Messages uses Anthropic's Claude Messages API, Chat uses OpenAI's Chat Completions, Responses uses OpenAI's legacy Completions endpoint, Gemini uses Google's Gemini API, and Images uses OpenAI's Image generation/editing endpoints—each requiring distinct authentication headers, request bodies, and response parsers as implemented in their dedicated Go handler files.
CCX (Cross‑Channel eXchange) is an open‑source proxy that unifies large language model APIs under a common routing layer. Understanding the specific protocol differences between the Messages, Chat, Responses, Gemini, and Images channels is critical for configuring upstream providers and troubleshooting integration errors. This guide examines the implementation details from the BenedictKing/ccx repository, including exact handler file paths and runnable request examples.
Messages Channel: Anthropic Claude Protocol
The Messages channel implements the Anthropic Messages API for Claude models. Unlike standard OpenAI‑compatible endpoints, this channel requires the anthropic-version header and uses Claude's native message structure.
Key implementation details in backend-go/internal/handlers/messages/channels.go:
- Endpoint:
POST /v1/messages - Required Headers:
Authorization: Bearer <key>andanthropic-version: 2023-06-01 - Request Body: Uses a
messagesarray withroleandcontentfields, but follows Claude's formatting conventions - Response Structure: Returns
type: "message"withroleandcontentarrays, distinct from OpenAI'schoiceswrapper
curl -X POST http://localhost:8080/v1/messages \
-H "Authorization: Bearer $CLAUDE_API_KEY" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model":"claude-3-5-sonnet-20240620",
"messages":[
{"role":"user","content":"Explain quantum tunneling in one sentence."}
],
"max_tokens":256
}'
Chat Channel: OpenAI Chat Completions
The Chat channel handles OpenAI's standard Chat Completions protocol, which has become the industry default for conversational AI. This is the most commonly used channel for modern GPT models.
Implementation resides in backend-go/internal/handlers/chat/channels.go:
- Endpoint:
POST /v1/chat/completions - Authentication: Standard
Authorization: Bearer <key> - Request Body: JSON with
messagesarray containing objects withrole(system,user,assistant) andcontent - Response Format: Returns
choices[0].messagestructure - Streaming: Supports
stream=truefor Server‑Sent Events (SSE)
curl -X POST http://localhost:8080/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model":"gpt-4o-mini",
"messages":[
{"role":"system","content":"You are a helpful assistant."},
{"role":"user","content":"Write a haiku about spring."}
],
"temperature":0.7
}'
Responses Channel: OpenAI Legacy Completions
The Responses channel corresponds to OpenAI's legacy Completions API (not Chat). This protocol differs significantly from the Chat channel by using raw prompt strings instead of structured message arrays.
Found in backend-go/internal/handlers/responses/channels.go:
- Endpoint:
POST /v1/completions - Request Body: Uses
promptfield (string or array of strings) rather thanmessages - Response Format: Returns
choices[0].textwithoutrolefields, providing only the generated text completion - Use Case: Text completion workflows that predate conversational formats
curl -X POST http://localhost:8080/v1/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model":"gpt-4o-mini",
"prompt":"Summarize the plot of \"Pride and Prejudice\" in 30 words.",
"max_tokens":150
}'
Gemini Channel: Google Gemini API
The Gemini channel provides a bridge to Google's Gemini models via the v1beta API. This channel handles protocol translation between Google's native format and OpenAI‑compatible responses.
Implementation in backend-go/internal/handlers/gemini/channels.go:
- Endpoint:
POST /v1beta/models/{model}:generateContent - Authentication: Uses
x-goog-api-keyheader instead of Bearer tokens - Model Listing: Queries
/v1beta/modelsand converts the response to OpenAI‑compatibleobject: "list"JSON format - Request Structure: Uses Gemini's
contentsarray withpartsobjects containing text
curl -X POST http://localhost:8080/v1beta/models/gemini-1.5-pro:generateContent \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents":[{"role":"user","parts":[{"text":"What is the capital of Canada?"}]}],
"generationConfig":{"temperature":0.5}
}'
To retrieve models through CCX's unified interface:
curl -X POST http://localhost:8080/gemini/channels/0/models \
-H "Content-Type: application/json" \
-d '{"key":"'"$GEMINI_API_KEY"'"}'
Images Channel: OpenAI Image Operations
The Images channel supports OpenAI's DALL‑E style image generation, editing, and variations. This channel has strict service type requirements and handles multipart form data for image uploads.
Located in backend-go/internal/handlers/images/channels.go:
- Service Type Restriction: Only accepts upstream configurations with
serviceType: "openai" - Endpoints:
/v1/images/generations,/v1/images/edits,/v1/images/variations - Content Types: JSON for generations,
multipart/form-datafor edits and variations - Authentication: Standard OpenAI Bearer token only
Image Generation (JSON):
curl -X POST http://localhost:8080/v1/images/generations \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt":"A futuristic cityscape at night, cyberpunk style",
"n":1,
"size":"1024x1024"
}'
Image Editing (multipart/form-data):
curl -X POST http://localhost:8080/v1/images/edits \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F "image=@original.png" \
-F "mask=@mask.png" \
-F 'prompt=Add a flying car' \
-F "n=1"
Authentication & Header Differences
Each channel enforces distinct authentication patterns:
- Messages: Requires
Authorization: Bearer <key>andanthropic-version: 2023-06-01 - Chat, Responses, Images: Standard
Authorization: Bearer <key>(OpenAI‑compatible) - Gemini: Uses
x-goog-api-key: <key>(Google‑specific header)
The backend-go/internal/config/config.go file defines the UpstreamConfig structure that stores these authentication credentials, while backend-go/internal/scheduler/channel_scheduler.go manages channel‑specific routing and failover logic based on these upstream types.
Request Structure Comparison
The five channels accept fundamentally different request payloads:
- Messages & Chat: Both use
messagesarrays, but Messages requires Claude‑specific formatting and versioning - Responses: Uses legacy
promptstrings instead of structured conversations - Gemini: Implements Google's
contentsarray with nestedpartsobjects - Images: Uses either JSON parameters (generations) or multipart form uploads (edits/variations)
Response parsing also varies: Messages returns Claude's native format, Chat returns choices[0].message, Responses returns choices[0].text, and Gemini responses are proxied with format conversion for model listings.
Summary
- Messages (
backend-go/internal/handlers/messages/channels.go): Anthropic Claude protocol requiringanthropic-versionheaders and native message structures - Chat (
backend-go/internal/handlers/chat/channels.go): Standard OpenAI Chat Completions withmessagesarrays and streaming support - Responses (
backend-go/internal/handlers/responses/channels.go): OpenAI legacy Completions usingpromptstrings and returning plain text - Gemini (
backend-go/internal/handlers/gemini/channels.go): Google Gemini API withx-goog-api-keyauthentication andv1betaendpoints, includes OpenAI‑compatible model list conversion - Images (
backend-go/internal/handlers/images/channels.go): OpenAI Image API restricted toserviceType: "openai", supporting both JSON and multipart form data
Frequently Asked Questions
Which CCX channel should I use for Claude 3.5 Sonnet?
Use the Messages channel. According to backend-go/internal/handlers/messages/channels.go, this channel implements the Anthropic Messages API and is the only route that properly handles Claude's anthropic-version header requirements and message‑based conversation format.
Why does the Gemini channel require a different authentication header?
The Gemini channel communicates directly with Google's API infrastructure, which uses x-goog-api-key instead of the Bearer token scheme standardized by OpenAI. The handler in backend-go/internal/handlers/gemini/channels.go manages this translation, forwarding requests to Google's v1beta endpoints while optionally converting responses to OpenAI‑compatible formats for upstream model listings.
Can I use non‑OpenAI providers with the Images channel?
No. The Images channel explicitly requires serviceType: "openai" in the upstream configuration. As implemented in backend-go/internal/handlers/images/channels.go, this restriction ensures that only OpenAI‑compatible image endpoints (supporting generations, edits, and variations) are routed through this channel.
What is the difference between the Chat and Responses channels?
Chat uses the modern OpenAI Chat Completions protocol with structured messages arrays containing role and content fields, returning assistant messages in choices[0].message. Responses uses the legacy Completions API, accepting a raw prompt string and returning generated text in choices[0].text without role metadata. Choose Chat for conversational agents and Responses for single‑turn text completion tasks.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →