Skip to content

feat(anthropic): support bearer token authentication - #3038

Merged
jujn merged 5 commits into
agentscope-ai:mainfrom
qiyu-lu:feat/anthropic-bearer-auth
Sep 12, 2026
Merged

feat(anthropic): support bearer token authentication#3038
jujn merged 5 commits into
agentscope-ai:mainfrom
qiyu-lu:feat/anthropic-bearer-auth

Conversation

@qiyu-lu

@qiyu-lu qiyu-lu commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

AgentScope-Java Version

2.0.3-SNAPSHOT

Description

Fixes #3029.

Anthropic 兼容网关需要 Authorization: Bearer <token> 时,现有模型无法通过 Builder 配置该凭据。本 PR 增加 SDK 客户端级别的 Bearer Token 支持,并保留原有 API Key 用法和公开构造方法。

  • 增加 AnthropicChatModel.Builder.authToken 和 Spring Boot 配置 agentscope.anthropic.auth-token,由底层 SDK 设置认证头。
  • API Key 和 Bearer Token 互斥:同时配置时,在创建 SDK 客户端前抛出 IllegalArgumentException,异常只包含配置项名称,不包含凭据值。校验覆盖 Builder 和直接构造入口。
  • Spring Starter 保留空白值处理及 customizer 覆盖顺序;customizer 可以在校验前通过 apiKey(null)authToken(null) 清除其中一种凭据。
  • 更新中英文文档,并补充认证请求、冲突拒绝和凭据不出现在 toString() / 校验异常中的回归测试。

Validation

  • 基于 main c5db8f72 完成本地变基,并解决两处文档链接冲突。
  • mvn -B -pl agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-anthropic,agentscope-extensions/agentscope-spring-boot-starters/agentscope-anthropic-spring-boot-starter -am '-Dtest=Anthropic*Test' -Dsurefire.failIfNoSpecifiedTests=false spotless:apply test:198 个用例,0 failures、0 errors、1 skipped。
  • 上述模块及其 reactor 依赖的 mvn -o -B ... -am spotless:check:通过。
  • git diff --check:通过。

HTTP 测试使用真实 Anthropic SDK 请求本地 MockWebServer,覆盖流式/非流式调用、Token 单独配置、API Key 单独配置、旧构造方法,以及 Starter 的空白值和 customizer 覆盖行为。新增测试覆盖双凭据拒绝、customizer 消除冲突,以及模型、Builder、配置对象和校验异常的凭据保护。未执行真实企业网关/付费模型联调或全仓测试;这些检查不代表所有 SDK 异常和日志路径均已验证。

@CLAassistant

CLAassistant commented Sep 8, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@codecov

codecov Bot commented Sep 8, 2026

Copy link
Copy Markdown

@qiyu-lu
qiyu-lu marked this pull request as ready for review September 8, 2026 07:26
Copilot AI lite review requested due to automatic review settings September 8, 2026 07:26

Copilot AI 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.

🟢 Approval recommended

The implementation cleanly forwards authToken to the underlying SDK, preserves backward compatibility and configuration precedence, and is covered by focused local HTTP regression tests.

Pull request overview

This PR adds first-class Bearer token authentication support for the Anthropic model integration, enabling Anthropic-compatible gateways that require Authorization: Bearer <token> while preserving existing API key behavior and configuration precedence in the Spring Boot starter.

Changes:

  • Extend AnthropicChatModel.Builder and constructors to accept an authToken and forward it to the underlying Anthropic SDK client.
  • Add Spring Boot property binding for agentscope.anthropic.auth-token and wire it into auto-configuration (with blank-value handling and customizer override preserved).
  • Add regression tests (local MockWebServer) and update both EN/ZH docs with builder and Spring Boot configuration examples.
File summaries
File Description
docs/v2/zh/integration/model/anthropic.md Adds ZH usage notes and examples for Bearer token authentication via builder and Spring Boot properties.
docs/v2/en/integration/model/anthropic.md Adds EN usage notes and examples for Bearer token authentication via builder and Spring Boot properties.
agentscope-extensions/agentscope-spring-boot-starters/agentscope-anthropic-spring-boot-starter/src/test/java/io/agentscope/spring/boot/anthropic/AnthropicAutoConfigurationTest.java Adds Spring Boot regression tests verifying auth-token binding, blank handling, and customizer precedence via real HTTP calls to MockWebServer.
agentscope-extensions/agentscope-spring-boot-starters/agentscope-anthropic-spring-boot-starter/src/main/java/io/agentscope/spring/boot/anthropic/AnthropicProperties.java Introduces authToken configuration property with accessor methods and Javadoc.
agentscope-extensions/agentscope-spring-boot-starters/agentscope-anthropic-spring-boot-starter/src/main/java/io/agentscope/spring/boot/anthropic/AnthropicAutoConfiguration.java Wires auth-token into AnthropicChatModel.Builder and keeps existing trimming/customizer order.
agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-anthropic/src/test/java/io/agentscope/extensions/model/anthropic/AnthropicChatModelAuthenticationTest.java Adds integration-style tests ensuring configured headers are sent in streaming/non-streaming modes and constructor backward compatibility.
agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-anthropic/src/main/java/io/agentscope/extensions/model/anthropic/AnthropicChatModel.java Adds authToken support to builder and a new constructor overload that forwards to the SDK client builder.
Review details
  • Files reviewed: 7/7 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@oss-maintainer

Copy link
Copy Markdown
Collaborator

⚠️ Merge conflict detected

@qiyu-lu This PR currently conflicts with main and cannot be merged. Please rebase or merge main into your branch:

git fetch origin
git checkout feat/anthropic-bearer-auth
git rebase origin/main
# resolve conflicts, then:
git push --force-with-lease

This is a one-time reminder. Feel free to @mention me for a re-review once conflicts are resolved.


Automated notification by github-manager-bot

@oss-maintainer oss-maintainer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Summary

Adds bearer-token auth for Anthropic-compatible gateways on top of the existing API-key path, threaded through the builder and the Spring auto-configuration, with MockWebServer assertions on the actual Authorization header. That is the right way to test this. Two things before this can move: the PR is in conflict with main, and the both-credentials-configured case currently sends two conflicting auth headers silently.


Automated review by github-manager-bot

Additional notes (not anchored to a changed line)

  • [INFO] agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-anthropic/src/main/java/io/agentscope/extensions/model/anthropic/AnthropicChatModel.java:1 — Two follow-ups: (1) this PR currently conflicts with main — see the reminder comment, please rebase; (2) please confirm the bearer token never reaches toString()/equals()/logging on the model or its config object, per the project rule that credentials must not leak into logs or events. The MockWebServer assertion in the new test is good evidence for the header itself; a toString() redaction check would close the loop. (line outside diff)


/**
* Sets the bearer token for authentication with an Anthropic-compatible gateway.
*

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The javadoc says that if both apiKey and authToken are set the SDK sends both headers, and the builder just forwards them. Silently sending two conflicting credentials is the kind of thing that produces a confusing 401 from the gateway; for an Anthropic-compatible proxy with a static Authorization header this is also a footgun in the Spring starter wiring. Consider rejecting the combination in build() (or ignoring apiKey when authToken is present and logging a warning) so the effective credential is unambiguous.

@qiyu-lu
qiyu-lu force-pushed the feat/anthropic-bearer-auth branch from 90f8699 to 0f7a4f6 Compare September 12, 2026 07:33

@oss-maintainer oss-maintainer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Summary

Re-reviewed after conflict resolution and the follow-up commits. The dual-credential concern from my earlier review is now fixed at the API level (apiKey/authToken are mutually exclusive and the message never echoes the secret values), the Spring starter trims blanks before validation, and the new MockWebServer tests assert the actual X-Api-Key / Authorization headers on both the streaming and non-streaming paths. CI is green and the CLA is signed — LGTM, with two non-blocking points below about places where the new guarantee is not yet enforced (blank strings via the public builder, and the SPI/registry path that still cannot express a bearer token).


Automated review by github-manager-bot

AnthropicBaseFormatter formatter,
ProxyConfig proxyConfig,
String cacheTtl) {
if (apiKey != null && authToken != null) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The guard is null-based, but Builder.apiKey("") / authToken(" ") are stored verbatim, so a blank credential slips through: apiKey="" + authToken="x" reaches the SDK with both headers, and authToken="" sends a malformed Authorization: Bearer . The starter trims blanks (trimToNull) before calling the builder, but this class is public API, so the same policy should be enforced here too — please normalize blank → null in the setters/constructor and only reject when two present credentials conflict, so the documented guarantee holds for direct builder users as well.

clientBuilder.apiKey(apiKey);
}

if (authToken != null) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Feature-scope gap: the SPI / model-registry path (AnthropicModelProvider.create()firstNonBlank(context.getApiKey(), ANTHROPIC_API_KEY)) still has no way to pass a bearer token — ModelCreationContext exposes only apiKey/baseUrl/options, and AnthropicCredential requires a non-null apiKey. So gateway users who configure models through the registry (non-Spring) get no authToken, while the docs page added here presents bearer auth as a general model capability. Could you either extend provider + credential + context with auth_token, or state in the doc that bearer auth currently covers the builder and Spring starter paths only?

* @param authToken the token without the {@code Bearer } prefix (null to omit)
* @return this builder
*/
public Builder authToken(String authToken) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

shouldNotExposeBearerTokenInModelOrBuilderToString passes only because neither Builder nor AnthropicChatModel overrides toString() today. That makes the guarantee accidental — a future @ToString/record refactor on the builder would silently start printing authToken (and apiKey) into logs. Since this PR is exactly about credential hygiene, it would be nice to add an explicit redacting toString() here (e.g. print authToken=***) so the test pins real behaviour.

* <p>{@code apiKey} and {@code authToken} are mutually exclusive.
*
* @param baseUrl the base URL for the Anthropic API (null for default)
* @param apiKey the API key for authentication (null to omit)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Minor javadoc drift: the pre-existing constructor documents apiKey as "null to load from ANTHROPIC_API_KEY env var", while this one says "null to omit", and the new @throws line doesn't mention that the two-credential check is what changed. Aligning the wording (and noting explicitly that env-var fallback happens in AnthropicModelProvider, not in this constructor) would keep the two overloads from reading as different contracts.

oss-maintainer

This comment was marked as abuse.

@jujn
jujn merged commit 7399ed6 into agentscope-ai:main Sep 12, 2026
6 checks passed
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.

[Feature]: AnthropicChatModel.Builder 缺少 authToken() 方法,无法支持自定义 Bearer Token 鉴权

5 participants