Skip to content

feat: support Anthropic Messages API format in the Custom post-processing provider - #2257

Open
diligentpig wants to merge 2 commits into
cjpais:mainfrom
diligentpig:feat/custom-anthropic-messages
Open

diligentpig wants to merge 2 commits into
cjpais:mainfrom
diligentpig:feat/custom-anthropic-messages

Conversation

@diligentpig

@diligentpig diligentpig commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Before Submitting This PR

Please submit only one fix or feature per pull request. Pull requests containing multiple fixes or features will likely be closed.

Please confirm you have done the following:

If this is a feature or change that was previously closed/rejected:

  • I have explained in the description below why this should be reconsidered
  • I have gathered community feedback (link to discussion below)

Human Written Description

I've deployed both the OpenAI GPT model and the Anthropic Claude model in Microsoft Foundry. While gpt model is supported by the Custom provider in post process, the claude model's Anthropic Messages API format is not supported currently.

  • I'm using LiteLLM as a proxy to run the claude model in Handy, which adding another service to maintain.

It would be great if the Custom provider could support the Anthropic Messages API format, which could benefit both online models and future local models.

Implementation notes

As discussed in #2250, I tried to keep this as small as possible:

  • One new row in the UI. An "API Format" dropdown appears only when the Custom provider is selected, directly below Provider. It uses the existing Dropdown / SettingContainer pattern, so no new UI components.
  • Default is unchanged. api_format defaults to openai via #[serde(default)], so existing settings load as before without any migration. Built-in providers always use openai, and only the Custom provider can change it.
  • The OpenAI path is untouched. send_chat_completion hands off to a new send_anthropic_message only when the format is anthropic. The Chat Completions request/response code is not modified. The other change is in build_headers: the Anthropic format uses x-api-key + anthropic-version, like the built-in Anthropic provider.
  • Scope of the Anthropic path. It is a single user message with max_tokens (required by the Messages API), and the response joins the text blocks. The Custom provider never uses structured output and Claude doesn't think unless asked, so there's no schema or reasoning handling. API key auth only.
  • Model list. No change was needed. /models works on Anthropic's own API now that the headers are right. Microsoft Foundry doesn't offer the Models API (documented here), so the list stays empty there and the deployment name is typed in, which the model field already supports.

Small wording changes so the labels stay accurate (applied to all locales; translations for the new strings were added for every language, so a native-speaker check would be welcome):

  • Section title API (OpenAI Compatible) → API. With two formats the parenthetical was no longer accurate, and Apple Intelligence was already listed under it. A plain title also won't need updating if another format is ever added.
  • Provider tooltip: Select an OpenAI-compatible provider. → Select an OpenAI-compatible or Anthropic-compatible provider.
  • The Base URL placeholder switches to https://api.anthropic.com/v1 for the Anthropic format. As now, the URL is entered up to /v1 and Handy appends the endpoint path.

I'm happy to adjust naming, placement, or wording, or trim anything further if you'd prefer. As mentioned in the discussion, I'm also glad to help with any bugs that come up around this.

Related Issues/Discussions

Discussion: #2250
Related: #1386 (closed as a feature request rather than a bug, with a note that a PR could be submitted)

Community Feedback

Testing

Tested in bun run tauri dev on macOS 26.6 (Apple Silicon):

  • Custom + OpenAI Compatible: GPT on Azure OpenAI. Model list loads and post-processing works as before.
  • Custom + Anthropic Messages: Claude Haiku 5.5 on Microsoft Foundry (https://<resource>.services.ai.azure.com/anthropic/v1). Post-processing returns 200 and the text is pasted correctly. The model name is entered manually, as noted above.
  • Switching between formats and providers keeps the Base URL and API key unchanged.
  • Existing settings load with the default format (no migration).
  • cargo test (all pass, including 4 new tests for the Anthropic headers, request body, response parsing, and a mock round trip), cargo fmt --check, cargo clippy, bun run lint, prettier --check.

Not tested: Anthropic's own API directly (I don't have a key). Help testing there would be appreciated.

Screenshots/Videos (if applicable)

image

AI Assistance

  • No AI was used in this PR
  • AI was used (please describe below)

If AI was used:

  • Tools used: Claude Code
  • How extensively: Claude Code wrote most of the code and tests. I worked out the design, scope, and UI wording with it, reviewed the changes, and tested the feature myself against my Microsoft Foundry deployments.

🤖 Generated with Claude Code (Claude Opus 5.5, high effort)

diligentpig and others added 2 commits October 10, 2026 19:09
…sing provider

Endpoints such as Claude on Microsoft Foundry only speak the Anthropic
Messages API, so the Custom provider (OpenAI Chat Completions only) could
not reach them. An "API Format" option on the Custom provider lets users
pick the request format without adding a provider per hosting service.
OpenAI Compatible stays the default and its request path is unchanged.

Discussion: cjpais#2250

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The translation consistency check requires every locale to carry the new
keys. Also sync the section title and provider description so no locale
still describes the API section as OpenAI-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cjpais

cjpais commented Oct 11, 2026

Copy link
Copy Markdown
Owner

This works, thanks, I will take a look and pull in when I have a chance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants