Amazon Q 使用 AWS SDK 风格 的 API 调用,而不是标准的 REST API。
https://q.us-east-1.amazonaws.com/
注意:这是根路径,不需要额外的路径(如 /v1/conversations)
POST
Host: q.us-east-1.amazonaws.com
Content-Type: application/x-amz-json-1.0
X-Amz-Target: AmazonCodeWhispererStreamingService.GenerateAssistantResponse
Authorization: Bearer <access_token>
Accept: */*重要说明:
Content-Type必须是application/x-amz-json-1.0(AWS JSON 协议)X-Amz-Target指定要调用的服务方法Authorization使用 Bearer token 认证
请求体是 JSON 格式,结构如下:
{
"conversationState": {
"conversationId": "uuid",
"history": [],
"currentMessage": {
"userInputMessage": {
"content": "用户消息内容",
"userInputMessageContext": {
"envState": {
"operatingSystem": "macos",
"currentWorkingDirectory": "/path/to/dir"
},
"tools": []
},
"origin": "CLI",
"modelId": "claude-sonnet-4.5",
"images": [ // 可选,图片列表
{
"format": "png",
"source": {
"bytes": "base64_encoded_image_data"
}
}
]
}
},
"chatTriggerType": "MANUAL"
},
"profileArn": "arn:aws:..." // 可选,组织账号需要
}Amazon Q 返回的是 AWS Event Stream 二进制格式,不是标准的 SSE 文本格式。
每个消息包含:
[Prelude: 12 bytes]
- Total length (4 bytes, big-endian uint32)
- Headers length (4 bytes, big-endian uint32)
- Prelude CRC (4 bytes, big-endian uint32)
[Headers: variable length]
- :event-type (string)
- :content-type (string)
- :message-type (string)
[Payload: variable length]
- JSON 数据
[Message CRC: 4 bytes]
每个 header 的格式:
[Header name length: 1 byte]
[Header name: variable]
[Header value type: 1 byte] (7 = string)
[Header value length: 2 bytes, big-endian uint16]
[Header value: variable]
对话开始事件,包含 conversation ID。
Headers:
:event-type: initial-response
:content-type: application/json
:message-type: event
Payload:
{
"conversationId": "uuid-string"
}助手响应事件,包含文本内容片段。
Headers:
:event-type: assistantResponseEvent
:content-type: application/json
:message-type: event
Payload:
{
"content": "文本片段"
}特点:
- 每个事件包含一小段文本(可能是一个词或几个词)
- 多个事件组成完整的响应
- 流结束时没有特殊标记,连接关闭即表示结束
https://oidc.us-east-1.amazonaws.com/token
POST /token
Content-Type: application/json
{
"grant_type": "refresh_token",
"refresh_token": "your_refresh_token",
"client_id": "your_client_id",
"client_secret": "your_client_secret"
}{
"access_token": "new_access_token",
"refresh_token": "new_refresh_token", // 可能是 refreshToken
"expires_in": 3600, // 可能是 expiresIn
"token_type": "Bearer"
}注意:字段名可能有变化(驼峰式或下划线式),代码中已处理。
| Claude API | Amazon Q API |
|---|---|
model |
conversationState.currentMessage.userInputMessage.modelId |
messages[-1].content (文本) |
conversationState.currentMessage.userInputMessage.content |
messages[-1].content (图片) |
conversationState.currentMessage.userInputMessage.images |
messages[:-1] |
conversationState.history |
tools |
conversationState.currentMessage.userInputMessage.userInputMessageContext.tools |
system |
添加到 content 前面 |
Claude API 格式:
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "base64_encoded_data"
}
}Amazon Q API 格式:
{
"format": "png",
"source": {
"bytes": "base64_encoded_data"
}
}| Amazon Q Event | Claude API Event |
|---|---|
initial-response |
message_start |
| (自动生成) | content_block_start |
assistantResponseEvent |
content_block_delta |
| (自动生成) | content_block_stop |
| (自动生成) | message_delta (stop) |
使用 event_stream_parser.py 模块:
from event_stream_parser import EventStreamParser, extract_event_info
async for message in EventStreamParser.parse_stream(byte_stream):
event_info = extract_event_info(message)
# 处理事件使用 parser.py 模块:
from parser import parse_amazonq_event
event = parse_amazonq_event(event_info)
if isinstance(event, MessageStart):
# 处理 message_start
elif isinstance(event, ContentBlockDelta):
# 处理 content_block_delta使用 stream_handler_new.py 模块:
from stream_handler_new import handle_amazonq_stream
async for claude_event in handle_amazonq_stream(byte_stream):
# claude_event 是 Claude 格式的 SSE 事件字符串
yield claude_event-
字节流处理:
- 必须使用
response.aiter_bytes()而不是response.aiter_lines() - Event Stream 是二进制格式,不能按行处理
- 必须使用
-
请求头顺序:
- 虽然 HTTP 头部顺序通常不重要,但建议按照示例顺序设置
- 特别是
X-Amz-Target必须存在
-
Content-Type:
- 必须是
application/x-amz-json-1.0 - 不能使用
application/json
- 必须是
-
事件补全:
- Amazon Q 不提供
content_block_start和content_block_stop - 代理服务会自动生成这些事件以保持 Claude API 兼容性
- Amazon Q 不提供
-
Token 计数:
- 当前使用简化算法(4字符≈1token)
- 建议后续集成 Anthropic 官方 tokenizer
-
查看原始字节流:
async for chunk in response.aiter_bytes(): print(f"Chunk: {chunk[:100]}") # 打印前 100 字节
-
查看解析后的消息:
async for message in EventStreamParser.parse_stream(byte_stream): print(f"Headers: {message['headers']}") print(f"Payload: {message['payload']}")
-
查看转换后的事件:
event = parse_amazonq_event(event_info) print(f"Event type: {type(event).__name__}")
- AWS Event Stream 规范:https://docs.aws.amazon.com/AmazonS3/latest/API/RESTSelectObjectAppendix.html
- Amazon Q CLI 文档:https://docs.aws.amazon.com/amazonq/