Responses API so với Chat Completions chủ yếu là câu hỏi về việc ai sở hữu trạng thái hội thoại, chứ không phải endpoint nào trông mới hơn. Chat Completions yêu cầu trình điều phối (orchestrator) của bạn gửi lại toàn bộ mảng messages trong mỗi lượt. Trong khi đó, Responses có thể tiếp tục từ một response ID đã lưu. Chúng tôi đã đọc tài liệu API được công bố của TokenLab và API mô hình trực tiếp vào ngày 03/10/2026, và câu trả lời cũng phụ thuộc vào các định dạng mà mô hình của bạn chấp nhận. Vì vậy, chúng ta hãy bắt đầu với một bảng quyết định.
| Yêu cầu của Agent | Lựa chọn | Tại sao |
|---|---|---|
| Client chat tương thích với OpenAI hiện có, có thể di chuyển giữa nhiều mô hình | Chat Completions (/v1/chat/completions) |
Khả năng tương thích mô hình rộng nhất, theo hướng dẫn định dạng API (quan sát ngày 03/10/2026) |
| Tiếp tục hội thoại từ một response phía server đã lưu | Responses (/v1/responses) |
previous_response_id và store là các trường của Responses |
| Chỉnh sửa lịch sử tùy ý, cắt tỉa hoặc ẩn tin nhắn giữa các lượt | Chat Completions | Bạn sở hữu toàn bộ mảng messages |
| Phản hồi nền hoặc các sự kiện Responses | Responses | Được ghi nhận cho các mô hình hỗ trợ chúng |
| Kết nối WebSocket bền vững với tính năng tiếp tục | Responses | wss://api.tokenlab.sh/v1/responses |
| Đầu ra đối tượng JSON di động | Chat Completions | response_format: {"type": "json_object"} |
Mô hình không liệt kê openai_responses |
Chat Completions, hoặc định dạng gốc của mô hình | Responses chỉ dành cho các mô hình liệt kê nó |
| Claude thinking blocks, Claude tool use, các trường prompt-cache | Anthropic Messages (/v1/messages) |
Chat Completions không đảm bảo các trường đó |
Gemini contents, files, cached content, Gemini tools |
Gemini (/v1beta/models/:model:generateContent) |
Giữ các trường gốc của Gemini trên route Gemini |
Các điểm chính
- Chat Completions là trạng thái do client quản lý. Responses có thể được tham chiếu phía server thông qua
previous_response_id. - Các lệnh gọi công cụ (tool calls) chuyển từ
tool_callslồng nhau cộng với tin nhắnrole: "tool"sang các mụcfunction_callvàfunction_call_outputcó kiểu dữ liệu. - Streaming thay đổi từ các chunk
choices[0].deltasang các sự kiện có tên, và một client Responses cũng phải theo dõiresponse.failedvàresponse.incomplete. - Hỗ trợ định dạng tùy theo từng mô hình. Vào ngày 03/10/2026, chỉ có
gpt-5.6-terratrong số ba mô hình ví dụ của chúng tôi chấp nhậnopenai_responses. - Không bao giờ trộn lẫn các định dạng trong một hội thoại. Hãy chuyển đổi và xác thực lịch sử đã lưu trước yêu cầu tiếp theo.
Responses API so với Chat Completions: cùng một tác vụ, hai yêu cầu
Lấy một tác vụ đơn lượt: giải thích tại sao bầu trời có màu xanh trong hai câu. Đây là yêu cầu Chat Completions, sử dụng thiết lập client từ hướng dẫn định dạng API (quan sát ngày 03/10/2026):
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["TOKENLAB_API_KEY"],
base_url="https://api.tokenlab.sh/v1",
)
response = client.chat.completions.create(
model="gpt-5.6-terra",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain why the sky is blue in two sentences."},
],
max_tokens=1000,
)
print(response.choices[0].message.content)
Và đây là cùng tác vụ đó dưới dạng yêu cầu Responses:
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["TOKENLAB_API_KEY"],
base_url="https://api.tokenlab.sh/v1",
)
response = client.responses.create(
model="gpt-5.6-terra",
instructions="You are a helpful assistant.",
input="Explain why the sky is blue in two sentences.",
max_output_tokens=1000,
)
print(response.output_text)
Các trường ánh xạ một-một cho trường hợp đơn giản này. Tin nhắn hệ thống trở thành instructions cấp cao nhất. messages trở thành input, chấp nhận một chuỗi hoặc một mảng các mục. max_tokens trở thành max_output_tokens.
Phần thân phản hồi khác biệt hơn. Chat Completions trả về choices[0].message và một finish_reason. Responses trả về một mảng output gồm các mục có kiểu dữ liệu và một trường status. Tài liệu tham khảo Create Response (quan sát ngày 03/10/2026) liệt kê queued, in_progress, completed, incomplete, failed, và cancelled, đồng thời yêu cầu bạn kiểm tra status ngay cả khi yêu cầu HTTP thành công. Các khóa sử dụng cũng khác nhau: prompt_tokens và completion_tokens ở một bên, input_tokens và output_tokens ở bên kia. Các ví dụ tham khảo hiển thị lần lượt là 20/9/29 và 10/12/22. Đó là các payload mẫu, không phải phép đo.
Tiếp tục một hội thoại
Hãy tưởng tượng một agent hỗ trợ vừa trả lời một câu hỏi và bây giờ nhận được "Còn đơn hàng #4472 thì sao?". Với Chat Completions, bạn thêm tin nhắn người dùng mới vào mảng đã lưu và gửi lại tất cả. Với Responses, bạn chuyển id của phản hồi trước đó và chỉ gửi lượt mới:
{
"model": "gpt-5.6-terra",
"previous_response_id": "resp_abc123",
"input": "What about order #4472?"
}
store mặc định là true, vì vậy phản hồi trước đó được giữ lại để truy xuất sau trừ khi bạn tắt nó đi. Ứng dụng của bạn vẫn phải lưu trữ id được trả về một cách bền vững giữa các lần chuyển tiếp. Nếu bạn cần cắt tỉa tùy chỉnh hoặc ẩn tin nhắn, định dạng không trạng thái (stateless) là lựa chọn phù hợp hơn.
Một ước tính sơ bộ cho thấy lý do tại sao việc gửi lại không trạng thái lại quan trọng ở quy mô agent. Giả sử lịch sử 10.000 token được gửi lại trong mỗi lần trong số 20 lần gọi. Đó là 200.000 input token. Với giá input của gpt-5.6-terra là $0,60 cho mỗi 1 triệu token, con số đó là 200.000 × 0,60 / 1.000.000 = $0,12 (ước tính; giả định số lượng token, không có bộ nhớ đệm). Giá này đến từ API mô hình trực tiếp, quan sát ngày 03/10/2026, với giá được cập nhật vào 2026-10-02T16:53:30.068Z.
Hai lưu ý được áp dụng. Tài liệu chúng tôi đọc không nói rõ liệu ngữ cảnh do server giữ có được tính phí như input token hay không, vì vậy hãy tự so sánh usage trên lưu lượng truy cập của riêng bạn. Và các yêu cầu trên 272K input token được tính giá gấp 2 lần input và 1,5 lần output cho toàn bộ yêu cầu: $1,20 và $5,40 cho mỗi 1 triệu thay vì $0,60 và $3,60. Các lịch sử không trạng thái dài có thể vượt qua giới hạn đó.
Gọi công cụ (Tool calling): hình dạng yêu cầu và phản hồi
Cả hai định dạng đều tuân theo vòng lặp trong hướng dẫn Structured Outputs & Tool Calling (quan sát ngày 03/10/2026). Gửi công cụ, đọc lệnh gọi, chạy nó trong backend của riêng bạn, trả về kết quả ở cùng định dạng và lặp lại cho đến khi có câu trả lời cuối cùng. Hình dạng của chúng khác nhau.
Chat Completions. Các công cụ được khai báo là {"type": "function", "function": {...}}. Mô hình trả lời với tool_calls trên choices[0].message, và finish_reason là tool_calls. Để tiếp tục, bạn gửi lại toàn bộ mảng, bao gồm tin nhắn trợ lý với tool_calls của nó và một tin nhắn role: "tool" mang tool_call_id. Các giá trị bên dưới mang tính minh họa; lookup_customer là tên công cụ được sử dụng trong hướng dẫn:
{
"model": "gpt-5.6-terra",
"messages": [
{"role": "user", "content": "Look up ana@example.com"},
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_xyz789",
"type": "function",
"function": {"name": "lookup_customer", "arguments": "{\"email\": \"ana@example.com\"}"}
}
]
},
{"role": "tool", "tool_call_id": "call_xyz789", "content": "{\"status\": \"active\"}"}
]
}
Responses. Mô hình trả lời với các mục function_call bên trong output, mỗi mục mang call_id, name, và arguments. Bạn trả về kết quả dưới dạng một mục input function_call_output và trỏ đến phản hồi trước đó:
{
"model": "gpt-5.6-terra",
"previous_response_id": "resp_abc123",
"input": [
{
"type": "function_call_output",
"call_id": "call_xyz789",
"output": "{\"status\": \"shipped\", \"tracking_number\": \"1Z999\"}"
}
]
}
Bạn không bao giờ xây dựng lại tin nhắn công cụ trợ lý trung gian. parallel_tool_calls tồn tại trong cả hai định dạng. Trong tài liệu tham khảo Create Response, nó mặc định là true. Tài liệu tham khảo Chat liệt kê nó mà không có giá trị mặc định và nói rằng nó áp dụng "khi được hỗ trợ bởi mô hình đã chọn."
Chúng tôi tìm thấy một khoảng trống. Các trang chúng tôi đọc chỉ mô tả tools và tool_choice của Responses theo thuật ngữ chung. Trước khi bạn chuyển đổi các lược đồ công cụ, hãy đọc hình dạng định nghĩa công cụ trong tài liệu tham khảo Create Response và kiểm tra nó trên mô hình mục tiêu của bạn. Đồng thời tuân thủ các quy tắc này từ hướng dẫn:
- TokenLab không chuyển đổi các công cụ tích hợp giữa các định dạng.
- Xác thực các đối số công cụ trước bất kỳ tác dụng phụ nào.
- Làm cho việc thực thi công cụ có tính lũy đẳng (idempotent), vì việc thử lại của client có thể lặp lại cùng một lệnh gọi.
- Áp dụng các kiểm tra quyền của riêng bạn.
Streaming: các sự kiện mà client phải xử lý
Chat Completions stream các chunk SSE. Client của bạn đọc choices[0].delta.content, ghi lại finish_reason, và bỏ qua các chunk không có choices. Với stream_options={"include_usage": True}, mức sử dụng sẽ đến trong một chunk như vậy. Hướng dẫn Streaming (quan sát ngày 03/10/2026) coi stop là hoàn thành, length là giới hạn token, và tool_calls là yêu cầu chạy công cụ.
Responses stream các sự kiện có tên. Consumer của hướng dẫn xử lý các sự kiện này:
response.output_text.deltacho văn bản cần thêm vàoresponse.completedcho dấu hiệu thành côngresponse.failed,response.incomplete, vàerrorlà các vấn đề kết thúc
import os
from openai import OpenAI
with OpenAI(
api_key=os.environ["TOKENLAB_API_KEY"],
base_url="https://api.tokenlab.sh/v1",
timeout=30.0,
max_retries=0,
) as client:
completed = False
with client.responses.create(
model="gpt-5.6-terra",
input="Write a short poem.",
stream=True,
) as stream:
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)
elif event.type == "response.completed":
completed = True
elif event.type in {"response.failed", "response.incomplete", "error"}:
raise RuntimeError(f"Stream ended with {event.type}")
if not completed:
raise RuntimeError("Stream closed before response.completed")
Ba quy tắc client tuân theo từ hướng dẫn:
- Sau khi sự kiện đầu tiên đến, một stream bị gián đoạn là không hoàn chỉnh và không được tự động khởi động lại. Giữ lại đầu ra một phần nếu nó hữu ích, nhưng không đánh dấu nó là hoàn thành. Một yêu cầu lặp lại có thể khác biệt và tốn phí lần nữa.
- Sử dụng SDK để phân tích SSE, vì một chunk mạng không nhất thiết là một sự kiện hoàn chỉnh.
- Hủy stream ngược dòng khi người dùng dừng hoặc ngắt kết nối, và giữ khóa trên server của bạn.
Responses cũng cung cấp một WebSocket tại wss://api.tokenlab.sh/v1/responses. Các phản hồi ở đó luôn được stream, background và response.cancel không được hỗ trợ, mỗi kết nối chạy một phản hồi hoạt động tại một thời điểm, và một kết nối kéo dài tối đa 60 phút. Các sự kiện mang sequence_number theo phạm vi phản hồi. Các sự kiện stream có tên error là các đối tượng phẳng, trong khi các lỗi kết nối và giao thức sử dụng một đối tượng error lồng nhau, vì vậy hãy xử lý cả hai hình dạng.
Kiểm tra các định dạng mà mô hình chấp nhận trước khi gửi
Đọc tokenlab.accepted_request_formats từ trang mô hình hoặc từ GET /v1/models/{model}, như được mô tả trong tài liệu tham khảo Get a Model (quan sát ngày 03/10/2026):
curl "https://api.tokenlab.sh/v1/models/gpt-5.6-terra"
Phản hồi bao gồm một đối tượng tokenlab với accepted_request_formats, pricing, các giới hạn, và lifecycle. Các giá trị ánh xạ tới các endpoint như hướng dẫn lỗi mô tả: openai_chat_completions tới /v1/chat/completions, openai_responses tới /v1/responses, anthropic_messages tới /v1/messages, và gemini_generate_content tới /v1beta/models/{model}:generateContent. Một định dạng được chấp nhận chỉ xác nhận endpoint. Các công cụ và trường riêng lẻ vẫn có thể thay đổi tùy theo mô hình.
Chúng tôi đã kiểm tra ba mô hình mà bài viết này tham chiếu so với API mô hình trực tiếp vào ngày 03/10/2026:
| Mô hình | Định dạng được chấp nhận | Max input / output tokens | Giá mỗi 1M in / out (USD) | Nguồn |
|---|---|---|---|---|
gpt-5.6-terra |
openai_chat_completions, openai_responses |
1,050,000 / 128,000 | 0.60 / 3.60 (inputs lên tới 272K) | live API |
claude-sonnet-5 |
anthropic_messages, openai_chat_completions |
1,000,000 / 128,000 | 0.90 / 4.50 | live API |
gemini-3.5-flash |
gemini_generate_content, openai_chat_completions |
1,048,576 / 65,536 | 0.75 / 4.50 | live API |
Cả ba đều đang trong giai đoạn vòng đời hoạt động mà không có mô hình thay thế, và giá cả được cập nhật vào 2026-10-02T16:53:30.068Z. Vì vậy, chỉ có gpt-5.6-terra nhận yêu cầu Responses hôm nay. Hai mô hình còn lại hoạt động thông qua Chat Completions hoặc các route gốc của chúng. Hãy kiểm tra lại trước khi bạn triển khai, vì vòng đời và giá cả có thể thay đổi.
Việc xử lý lỗi cũng quan trọng ở đây. Một mô hình bị viết sai trong lệnh gọi create trả về 400 model_not_found và có thể bao gồm did_you_mean. Việc hỏi GET /v1/models/{model} về một ID không xác định trả về 404 model_not_found. Một lỗi 503 all_channels_failed với retryable: false có nghĩa là việc lặp lại yêu cầu sẽ không giúp ích gì. Đừng tự động hoán đổi mô hình trừ khi sản phẩm của bạn có quyền làm như vậy.
Danh sách kiểm tra di chuyển: Responses API so với Chat Completions
Sử dụng thứ tự này khi bạn chuyển một agent từ Chat Completions sang Responses.
- Xác nhận mô hình liệt kê
openai_responses. Nếu không, hãy dừng lại ở đây. Ở lại với Chat Completions là con đường được hỗ trợ. - Chọn ranh giới cắt chuyển. Bắt đầu các hội thoại mới trên Responses. Đừng chuyển đổi một luồng trực tiếp giữa chừng, vì các định dạng đại diện cho trạng thái và lệnh gọi công cụ khác nhau.
- Chuyển đổi lịch sử đã lưu một cách có chủ đích. Nếu bạn phải di chuyển các luồng cũ, hãy chuyển đổi và xác thực chúng trong ứng dụng của bạn trước yêu cầu tiếp theo.
- Đổi tên các trường cốt lõi.
messagestrở thànhinput, tin nhắn hệ thống hoặc nhà phát triển trở thànhinstructions, vàmax_tokenshoặcmax_completion_tokenstrở thànhmax_output_tokens. - Viết lại vòng lặp công cụ. Thay thế việc phân tích cú pháp
choices[0].message.tool_callsbằng các mụcfunction_call, và thay thế các tin nhắnrole: "tool"bằng các mụcfunction_call_outputđược khóa bởicall_id. - Lưu trữ các ID phản hồi. Lưu trữ từng
idđể bạn có thể chuyểnprevious_response_id. Quyết định vềstorevà việc lưu giữ ngay từ đầu, và kiểm tra xem TokenLab giữ các phản hồi đã lưu trong bao lâu, vì các trang chúng tôi đọc không nói rõ. - Viết lại consumer stream. Xử lý
response.output_text.delta,response.completed,response.failed,response.incomplete, vàerror. Coi một stream đã đóng mà không córesponse.completedlà một lỗi. - Kiểm tra
status. Một thành công HTTP vẫn có thể mangincompletehoặcfailed. - Kiểm tra các tham số có thể không được chuyển sang. Trang Create Response liệt kê
temperature,top_p,tools,parallel_tool_calls,reasoning, vàtext. Nó không liệt kên,logprobs,logit_bias,frequency_penalty,presence_penalty,seed,top_k,stop,user, hoặcstream_options. Xác minh từng cái trên mô hình của bạn trước khi dựa vào nó. TokenLab có thể chuyển các trường không xác định qua, nhưng điều đó không có nghĩa là mô hình chấp nhận chúng. - Ánh xạ đầu ra JSON. Chat sử dụng
response_format. Responses sử dụng đối tượngtext, và hỗ trợtext.formatphụ thuộc vào mô hình. - Lập kế hoạch xung quanh các endpoint bị thiếu. Các endpoint cancel, input-items, và input-tokens hiện không khả dụng. Việc xóa một phản hồi đã lưu không hủy quá trình tạo.
- Kiểm tra phát lại với chế độ tắt thử lại. Giữ
max_retries=0và tự quyết định trong mã của riêng bạn khi nào việc thử lại là an toàn. Các quá trình tạo bị hết thời gian chờ không nên phát lại tự động.
Câu hỏi thường gặp
Tôi có thể gửi yêu cầu Responses đến Claude Sonnet 5 hoặc Gemini 3.5 Flash không?
Không theo API mô hình trực tiếp vào ngày 03/10/2026. claude-sonnet-5 liệt kê anthropic_messages và openai_chat_completions. gemini-3.5-flash liệt kê gemini_generate_content và openai_chat_completions. Sử dụng Chat Completions hoặc route gốc, và kiểm tra lại accepted_request_formats trước khi bạn triển khai.
Tôi có ngừng trả tiền cho các lượt trước đó khi tôi sử dụng previous_response_id không?
Các trang chúng tôi đọc không nói rõ. Chúng ghi lại rằng server có thể tiếp tục từ một phản hồi đã lưu, nhưng không nói rõ ngữ cảnh được khôi phục được tính phí như thế nào. Hãy chạy một vài cuộc gọi đa lượt và so sánh các trường usage với đường cơ sở không trạng thái của bạn trước khi bạn lập kế hoạch tiết kiệm.
Tôi có thể chuyển đổi định dạng giữa chừng một hội thoại không?
Không. Các hướng dẫn của TokenLab yêu cầu giữ một định dạng cho mỗi hội thoại, vì mỗi định dạng đại diện cho trạng thái và lệnh gọi công cụ khác nhau. Nếu bạn phải di chuyển lịch sử đã lưu, hãy chuyển đổi và xác thực nó trong ứng dụng của bạn trước khi gửi yêu cầu tiếp theo.
Làm cách nào để hủy một yêu cầu Responses đang chạy?
Một endpoint hủy hiện không khả dụng. Việc xóa một phản hồi đã lưu không hủy quá trình tạo, và các phản hồi WebSocket không hỗ trợ response.cancel. Đối với các stream, hãy đóng stream ngược dòng từ server của bạn khi người dùng dừng hoặc ngắt kết nối.
Trước khi bạn thay đổi endpoint, hãy mở danh mục mô hình TokenLab và xác nhận accepted_request_formats cho chính xác mô hình mà agent của bạn gọi.
Nguồn
Giá quan sát ngày 2026-10-03
- TokenLab Docs: API formatsQuan sát ngày 2026-10-03
- TokenLab Docs: Create ResponseQuan sát ngày 2026-10-03
- TokenLab Docs: Create Chat CompletionQuan sát ngày 2026-10-03
- TokenLab Docs: Structured Outputs & Tool CallingQuan sát ngày 2026-10-03
- TokenLab Docs: StreamingQuan sát ngày 2026-10-03
- TokenLab Docs: Errors agents can act onQuan sát ngày 2026-10-03
- TokenLab Docs: Migration GuidesQuan sát ngày 2026-10-03
- TokenLab Docs: Get a ModelQuan sát ngày 2026-10-03
