Skip to content

Support Anthropic API /v1/messages Endpoint - #22627

Merged
simon-mo merged 28 commits into
vllm-project:mainfrom
LiuLi1998:dev/antropic_v2
Oct 22, 2025
Merged

Support Anthropic API /v1/messages Endpoint#22627
simon-mo merged 28 commits into
vllm-project:mainfrom
LiuLi1998:dev/antropic_v2

Conversation

@LiuLi1998

@LiuLi1998 LiuLi1998 commented Aug 11, 2025

Copy link
Copy Markdown
Contributor

Relate issue: #21313
This PR adds support for the Anthropic /v1/messages REST API endpoint to the vLLM FastAPI server.

  • Support /v1/messages API
  • Compatibale with all existed tool call parser in OpenAI API

@LiuLi1998
LiuLi1998 requested a review from aarnphm as a code owner August 11, 2025 08:20
@mergify mergify Bot added the frontend label Aug 11, 2025

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for the Anthropic Messages API by adding a new API server, protocol definitions, and a serving layer for format conversion. The implementation is based on the existing OpenAI-compatible server. My review has identified several critical and high-severity issues, including a potential NoneType access error, incorrect Pydantic model usage that could lead to validation errors, a risk of generating duplicate tool call IDs, and another case of incorrect attribute access on a Pydantic model that would cause a runtime error. I have provided specific code suggestions to address these issues and ensure the stability and correctness of the new endpoint.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

When handler is None, messages(raw_request) is also None. Calling create_error_response on a None object will raise an AttributeError, causing an unhandled exception and a 500 server error. You should construct an ErrorResponse directly to ensure a proper error is returned. You will need to import ErrorResponse from vllm.entrypoints.openai.protocol and HTTPStatus from http.

Suggested change
return messages(raw_request).create_error_response(
message="The model does not support Chat Completions API")
return ErrorResponse(message="The model does not support Chat Completions API",
type="model_not_found",
code=HTTPStatus.NOT_FOUND.value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

anthropic_request.tool_choice is a Pydantic model instance, not a dictionary. Accessing its attributes should be done with dot notation (e.g., .name). Using .get("name") will result in an AttributeError at runtime.

Suggested change
"name": anthropic_request.tool_choice.get("name")
"name": anthropic_request.tool_choice.name

Comment thread vllm/entrypoints/anthropic/protocol.py Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The id field is defined as a required field. The model_post_init method, which attempts to set a default value, is called after Pydantic's validation. If id is not provided during initialization, a ValidationError will be raised before model_post_init can execute. To correctly provide a default value for an optional field, you should use default_factory in the field definition and remove the model_post_init method.

Suggested change
id: str
id: str = Field(default_factory=lambda: f"msg_{int(time.time() * 1000)}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using int(time.time()) to generate tool call IDs is not safe as it can produce duplicate IDs for tool calls created in the same second. This can lead to incorrect behavior when matching tool calls to their results. It's better to use a UUID-based approach for uniqueness. You can use random_tool_call_id from vllm.entrypoints.chat_utils for this, which needs to be imported.

Suggested change
"id": block.id or f"call_{int(time.time())}",
"id": block.id or random_tool_call_id(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

A text AnthropicContentBlock is created even if generator.choices[0].message.content is None. This can lead to an invalid content block, as the Anthropic API requires the text field for text blocks. When serialized with exclude_none=True, this would result in an invalid content block. You should only create the text content block if there is content available.

Suggested change
content: List[AnthropicContentBlock] = [
AnthropicContentBlock(
type="text",
text=generator.choices[0].message.content
)
]
content: List[AnthropicContentBlock] = []
if generator.choices[0].message.content:
content.append(
AnthropicContentBlock(
type="text",
text=generator.choices[0].message.content))

@github-actions

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the vLLM project.

💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in #pr-reviews, coordinate on features in #feat- channels, or join special interest groups in #sig- channels.

Just a reminder: PRs would not trigger full CI run by default. Instead, it would only run fastcheck CI which starts running only a small and essential subset of CI tests to quickly catch errors. You can run other CI tests on top of those by going to your fastcheck build on Buildkite UI (linked in the PR checks section) and unblock them. If you do not have permission to unblock, ping simon-mo or khluu to add you in our Buildkite org.

Once the PR is approved and ready to go, your PR reviewer(s) can run CI to test the changes comprehensively before merging.

To run CI, PR reviewers can either: Add ready label to the PR or enable auto-merge.

🚀

@mgoin

mgoin commented Aug 11, 2025

Copy link
Copy Markdown
Member

Exciting! Make sure to add some unit tests before ready and I wonder if we can also include a smoke test that claude code/some other application can communicate with the API correctly

@mgoin
mgoin self-requested a review August 11, 2025 19:09
@njhill

njhill commented Aug 11, 2025

Copy link
Copy Markdown
Member

Thanks @LiuLi1998! Would you also be willing to help with ongoing support/maintenance of the API?

@LiuLi1998

Copy link
Copy Markdown
Contributor Author

Exciting! Make sure to add some unit tests before ready and I wonder if we can also include a smoke test that claude code/some other application can communicate with the API correctly

Thanks for the input! I agree — I’ll add some tests soon to make sure everything works as expected.

@LiuLi1998

Copy link
Copy Markdown
Contributor Author

Thanks @LiuLi1998! Would you also be willing to help with ongoing support/maintenance of the API?

Definitely! I’m glad to take part in the support/maintenance of the API

Signed-off-by: liuli <ll407707@alibaba-inc.com>
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Signed-off-by: liuli <ll407707@alibaba-inc.com>
@LiuLi1998

Copy link
Copy Markdown
Contributor Author

Exciting! Make sure to add some unit tests before ready and I wonder if we can also include a smoke test that claude code/some other application can communicate with the API correctly

I've added initial tests.I'm not entirely sure if the current approach follows best practices or covers everything needed—would really appreciate your feedback on improvements or any other cases

Signed-off-by: liuli <ll407707@alibaba-inc.com>
@mgoin mgoin changed the title Support Anthropic API Endponit Support Anthropic API /v1/messages Endpoint Aug 13, 2025
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Signed-off-by: liuli <ll407707@alibaba-inc.com>
@mergify

mergify Bot commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @LiuLi1998.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Aug 18, 2025
# Conflicts:
#	tests/utils.py
@mergify mergify Bot removed the needs-rebase label Aug 20, 2025
@LiuLi1998

Copy link
Copy Markdown
Contributor Author

@mgoin While adding tests, I triggered the CI and encountered the following error:
ModuleNotFoundError: No module named 'anthropic'.
Could someone advise how to add the required dependency to the project's requirements? Should I add anthropic to requirements.txt or requirements-test.txt (or another file)? Any guidance on the correct procedure would be appreciated!

Signed-off-by: liuli <ll407707@alibaba-inc.com>
@mergify mergify Bot added the ci/build label Aug 20, 2025
@mergify

mergify Bot commented Aug 23, 2025

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @LiuLi1998.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Aug 23, 2025
usberkeley pushed a commit to usberkeley/vllm that referenced this pull request Oct 23, 2025
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: Michael Goin <mgoin64@gmail.com>
@shoted

shoted commented Oct 24, 2025

Copy link
Copy Markdown

how to support both openai and anthropic api

@tlipoca9

Copy link
Copy Markdown
Contributor

how to support both openai and anthropic api

@LiuLi1998 +1, is it possible? I also want it

0xrushi pushed a commit to 0xrushi/vllm that referenced this pull request Oct 26, 2025
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: Michael Goin <mgoin64@gmail.com>
Signed-off-by: 0xrushi <6279035+0xrushi@users.noreply.github.com>
0xrushi pushed a commit to 0xrushi/vllm that referenced this pull request Oct 26, 2025
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: Michael Goin <mgoin64@gmail.com>
Signed-off-by: 0xrushi <6279035+0xrushi@users.noreply.github.com>
@LiuLi1998

Copy link
Copy Markdown
Contributor Author

how to support both openai and anthropic api

@LiuLi1998 +1, is it possible? I also want it

Currently, the OpenAI and Anthropic APIs are separate api servers and cannot be used at the same time.

@shoted

shoted commented Oct 28, 2025

Copy link
Copy Markdown

how to support both openai and anthropic api如何同时支持 OpenAI 和 Anthropic API

@LiuLi1998 +1, is it possible? I also want it+1,有可能吗?我也想要

Currently, the OpenAI and Anthropic APIs are separate api servers and cannot be used at the same time.目前,OpenAI 和 Anthropic API 是独立的 api 服务器,不能同时使用。

Is there a plan to support them simultaneously?

See https://docs.anthropic.com/en/api/messages
for the API specification. This API mimics the Anthropic messages API.
"""
logger.debug("Received messages request %s", request.model_dump_json())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would this be super slow? it calls request.model_dump_json() unconditionally.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will only work when VLLM_LOGGING_LEVEL=DEBUG

return JSONResponse(content=generator.model_dump())

elif isinstance(generator, AnthropicMessagesResponse):
logger.debug(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar problem, unconditional call of generator.model_dump(exclude_none=True)



@router.post(
"/v1/messages",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems anthropic API only has a new /v1/messages endpoint, why not merge it with the openai server? like serving both v1/chat/completions and /v1/messages endpoints together.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they are two different protocols, and It's possible to merge them together for functional compatibility, but I think it could lead to semantic confusion.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think Kaichao is saying to merge them into one endpoint, just hosting them side-by-side. So when you run vllm serve you get /v1/completions, /v1/chat/completions, /v1/messages, etc. I agree this would be optimal for user ease

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think Kaichao is saying to merge them into one endpoint, just hosting them side-by-side. So when you run vllm serve you get /v1/completions, /v1/chat/completions, /v1/messages, etc. I agree this would be optimal for user ease

I agree it's the most user-friendly solution.

@bbartels

Copy link
Copy Markdown
Contributor

@youkaichao @mgoin @shoted Raised #27882 to add /v1/messages to openai api_server

@shoted

shoted commented Nov 4, 2025

Copy link
Copy Markdown

@youkaichao @mgoin @shoted Raised #27882 to add /v1/messages to openai api_server

nice, bro

ilmarkov pushed a commit to neuralmagic/vllm that referenced this pull request Nov 7, 2025
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: Michael Goin <mgoin64@gmail.com>
rtourgeman pushed a commit to rtourgeman/vllm that referenced this pull request Nov 10, 2025
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: Michael Goin <mgoin64@gmail.com>
devpatelio pushed a commit to SumanthRH/vllm that referenced this pull request Nov 29, 2025
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: Michael Goin <mgoin64@gmail.com>
mystous pushed a commit to mystous/vllm_hybrid that referenced this pull request May 10, 2026
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: Michael Goin <mgoin64@gmail.com>
my-other-github-account pushed a commit to my-other-github-account/vllm that referenced this pull request May 15, 2026
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: Michael Goin <mgoin64@gmail.com>
0826joyce pushed a commit to 0826joyce/vllm-serving-optimization that referenced this pull request May 19, 2026
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: Michael Goin <mgoin64@gmail.com>
plasticchris pushed a commit to plasticchris/vllm that referenced this pull request Jul 20, 2026
Signed-off-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: liuli <ll407707@alibaba-inc.com>
Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-authored-by: Michael Goin <mgoin64@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/build frontend ready ONLY add when PR is ready to merge/full CI is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants