企业Java开发者可通过惯用Java代码和注解、虚拟线程等驱动GitHub Copilot,实现从Java直接调用AI代码补全能力。
Java 开发者不再需要依赖 Java 框架特定的方式来从企业应用中驱动 AI。
诚然,Langchain4j 通过解耦特定 AI 供应商为开发者赋能,但你仍然依赖 Langchain4j。而 Spring AI 嘛,如果你不依赖 Spring 本身,自然也会依赖 Spring 的设计选择。
现在,GitHub Copilot SDK for Java 是首个真正与框架无关的 Java AI 驱动方式。凭借其 BYOK 支持,GitHub Copilot SDK for Java 也是 AI 供应商无关的。
💡 尽管它叫 GitHub Copilot SDK,但你可以通过传入自定义的 provider/ProviderConfig(包含自己的 baseUrl + apiKey,或 bearer token)来使用任何直连模型供应商,如 OpenAI、Azure、Anthropic 或 OpenAI 兼容端点。无需 Copilot 订阅。
GitHub Copilot SDK for Java 是一个客户端库,赋能你的服务端 Java 代码以编程方式创建 Copilot 智能体会话、注册工具、发送提示并接收结构化响应。它可在服务器环境中运行,包括 Jakarta EE 和 Spring。如果你在企业级 Java 开发中有些年头了,这个 SDK 会让你有回家的感觉:CompletableFuture、注解、lambda、虚拟线程,应有尽有。
本文将展示如何使用该 SDK,带你走过一个完整的 Jakarta EE 11 示例应用,并留下具体的后续步骤供你自行尝试。我选择 Jakarta EE 11 作为演示,因为我是该版本的首席发布协调员。我相信开放标准是赋能开发者的最佳方式。更多关于 Jakarta EE 11 的信息请参阅这篇 InfoQ 文章。
这个示例应用是一个使用 Jakarta EE 11 构建的智能体 harness。但当然,开发者可以使用自己熟悉的 Java 框架和库来构建自己的智能体 harness。
克隆示例应用并自行尝试 >
SDK 可作为 Maven 依赖引入:
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.7-preview.1</version>
</dependency>
前置要求:
示例应用详解
了解 SDK 运作的最佳方式是运行这个示例应用。
git clone https://github.com/microsoft/Build26-BRK206-your-agent-anywhere-multiclient-multidevice-with-github-copilot-sdk.git
cd Build26-BRK206-your-agent-anywhere-multiclient-multidevice-with-github-copilot-sdk/src/java-agent-orchestrator
mvn clean package liberty:run
# Open http://localhost:9080/index.xhtml
Java 演示基于以下技术构建:
| 技术领域 | 选型 |
|---|---|
| 运行时 | Open Liberty 26.0.0.5 |
| 平台 | Jakarta EE 11(Faces 4.1, CDI 4.1, WebSocket 2.2, Data 1.0, Persistence 3.2) |
| UI | PrimeFaces 15.0.16 |
| AI 编排 | Copilot SDK for Java 1.0.7-preview.1 |
| 数据库 | H2 内存数据库(10 条种子房产列表) |
该应用是一个房地产潜在客户管理智能体流水线。客户提交查询("我在找一套位于伦敦、价格低于 80 万英镑的三居室"),系统会在虚拟线程上启动一个隔离的 Copilot 智能体来处理整个管道流程:

该架构使用 Jakarta WebSocket 将实时状态更新从服务器推送到浏览器,这样你就可以观察智能体在模型调用工具时如何推进各阶段:

同时提交多个查询,以查看并发虚拟线程智能体的实际运行。每个查询独立处理,拥有各自的 Copilot 会话。


SDK 功能实战
让我们通过示例代码来走一遍 SDK 的关键功能。
这是核心 API。如果你曾经写过 JAX-RS 的 @GET 端点或 @MessageDriven bean,这会让你立刻感到熟悉:
@CopilotTool(value = "Sets the current phase of the agent. Use this to report progress.",
name = "set_current_phase")
public String setCurrentPhase(
@CopilotToolParam("The phase to transition to (VALIDATING, SEARCHING, "
+ "WRITING_REPORT, REJECTED_GARBAGE, REJECTED_NO_MATCHES, or DONE)")
String phaseName) {
phase = Phase.valueOf(phaseName.trim().toUpperCase(Locale.ROOT));
notifyUi();
return "Phase set to " + phase.getLabel();
}
@CopilotTool 注解将该方法声明为模型可以调用的工具。@CopilotToolParam 注解描述每个参数,使模型知道该传递什么。SDK 处理所有的 JSON Schema 生成、参数解析和分发。你只需写一个普通的 Java 方法。
@CopilotTool 的两个构建前提条件。基于注解的工具 API 目前是 SDK 的实验性功能,因此你需要在 Maven 构建中配置两项:
启用实验性 API:向编译器传递 -Acopilot.experimental.allowed=true。若无此标志,注解处理器将拒绝生成工具元数据。关于实验性 API 的更多详情请参阅 Copilot SDK 文档。
注册注解处理器:将 SDK 添加为 annotationProcessorPath,以便编译器能找到 @CopilotTool 处理器并在编译时生成 $$CopilotToolMeta 类。
两者都在 maven-compiler-plugin 中配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.15.0</version>
<configuration>
<compilerArgs>
<arg>-Acopilot.experimental.allowed=true</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.7-preview.1</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
注册一个对象中的所有注解工具:
List<ToolDefinition> annotatedTools = ToolDefinition.fromObject(this);
当你希望在调用站点定义一个工具而不想专门写一个方法时,可以使用 lambda 风格:
ToolDefinition reportIntentTool = ToolDefinition
.from("report_intent",
"Reports the current intent of the agent",
Param.of(String.class, "intent", "Intent in max 4 words"),
(String intent) -> {
currentIntent = intent;
addEvent(Instant.now(), "intent", "Intent updated", intent);
notifyUi();
return "ok";
})
.overridesBuiltInTool(true);
注意 .overridesBuiltInTool(true)。这告诉 SDK,我们的 report_intent 工具故意替换了同名内置工具。当你需要对模型已知的工具自定义行为时,这很有用。
工具不必与你的智能体逻辑放在同一个类中。下面是定义在独立 CDI bean 中的 searchProperties:
@ApplicationScoped
public class PropertyDatabase {
@CopilotTool(value = "Searches the real estate listings database. "
+ "Returns up to 10 matching properties.",
name = "search_properties")
public List<Property> searchProperties(
@CopilotToolParam("Property type substring (e.g. 'flat', 'house')") String type,
@CopilotToolParam("City substring (e.g. 'London', 'Bristol')") String city,
@CopilotToolParam("Minimum number of bedrooms (0 for no minimum)") int minBedrooms,
@CopilotToolParam("Maximum price in GBP (0 for no maximum)") double maxPriceGbp) {
// ... filter and return matching properties ...
}
}
你通常会用 ToolDefinition.fromObject(propertyDatabase) 来注册这些工具。在示例应用中,我们使用 lambda 包装器,因为 CDI 客户端代理可能会掩盖注解元数据。
SDK 让你对系统消息进行细粒度控制。使用 SystemMessageMode.CUSTOMIZE 在保留其余部分的同时替换特定章节:
SystemMessageConfig systemMessage = new SystemMessageConfig()
.setMode(SystemMessageMode.CUSTOMIZE)
.setSections(Map.of(SystemMessageSections.IDENTITY,
new SectionOverride()
.setAction(SectionOverrideAction.REPLACE)
.setContent("""
You are part of a real estate recommendation system.
You will receive enquiries from customers, and you must
carry out the following workflow...
""")));
这段文本块("""...""")让多行提示词无需字符串拼接即可保持可读性。IDENTITY 区段覆盖只替换模型的自述部分,同时保留安全护栏。如果你想用更简单的方案,SystemMessageMode.APPEND 会在默认系统消息之后追加你的内容,而不做任何替换。
一行代码即可启动完整的 AI 智能体循环:
session = client.createSession(sessionConfig).get();
// ...
AssistantMessageEvent result = session.sendAndWait(escapedEnquiry).get();
在 .get() 背后,模型进行推理、调用你的工具(可能多次),并返回最终响应。在虚拟线程上,.get() 的开销极低。等待期间不会占用任何平台线程。SDK 会自动将工具调用分发到你注册的处理器,并将结果反馈给模型,直到它完成。
订阅会话事件以构建响应式 UI:
sessionSubscription = session.on(event -> {
captureSessionEvent(event);
uiUpdateSocket.pushDetailUpdate(id);
});
每一次工具调用、每一个结果、每一条助手消息都会触发一个事件。示例应用捕获这些事件并通过 Jakarta WebSocket 将它们推送到浏览器,使流水线仪表板能够实时更新。你可以使用模式匹配来处理特定的事件类型:
if (event instanceof AssistantMessageEvent msg) {
finalReport = msg.getData().content();
} else if (event instanceof ToolExecutionStartEvent start) {
// Tool is being invoked...
}
客户端配置为服务端运行模式:
copilotClient = new CopilotClient(
new CopilotClientOptions()
.setMode(CopilotClientMode.EMPTY)
.setCopilotHome(copilotHome)
.setExecutor(contextualVirtualThreadExecutor));
CopilotClientMode.EMPTY 表示不进行 IDE 集成——客户端直接与 Copilot CLI 通信。自定义 Executor(下文讨论)确保工具回调在容器上下文中运行。
关于权限处理,示例使用:
sessionConfig.setOnPermissionRequest(PermissionHandler.APPROVE_ALL);
APPROVE_ALL 适用于演示和开发环境。在生产环境中,需要实现真实的权限策略来验证模型被允许调用哪些工具。
SDK 并非一个孤立框架。它可以与 Jakarta EE 自然组合——当然也可以与 Spring 等 proprietary 框架组合。
Executor 参数是关键的集成点。Jakarta Concurrency(3.1 规范 §5.2)要求应用程序创建的线程必须从 ManagedThreadFactory 获取,以便容器能够:
Open Liberty 26.x 通过 server.xml 中的 virtual 属性支持虚拟线程 ManagedThreadFactory。
<managedThreadFactory jndiName="concurrent/virtualThreadFactory" virtual="true" />
然后在 AppState.java 中注入该工厂:
@Resource(lookup = "concurrent/virtualThreadFactory")
private ManagedThreadFactory virtualThreadFactory;
并使用它创建传递给 Copilot SDK 的 Executor。
// The ManagedThreadFactory (virtual=true) creates container-managed virtual
// threads that automatically propagate CDI, JNDI, and transaction context.
Executor managedVirtualExecutor = runnable ->
virtualThreadFactory.newThread(runnable).start()
String copilotHome = Path.of(System.getProperty("user.home"), ".copilot").toString();
CopilotClientOptions copilotClientOptions = new CopilotClientOptions()
.setMode(CopilotClientMode.EMPTY)
.setCopilotHome(copilotHome)
.setExecutor(managedVirtualExecutor);
copilotClient = new CopilotClient(copilotClientOptions);
这创建了携带容器上下文的虚拟线程。当 SDK 分发工具调用到 searchProperties() 时,该方法可以 @Inject 一个 JPA repository 并查询数据库,因为容器上下文存在于回调线程上。
示例中的其他集成模式:
@ApplicationScoped 用于单例 CopilotClient(每个应用生命周期一个客户端)f:websocket push 通过 PushContext 实现实时浏览器更新@Repository 用于类型安全的数据库查询,无需原始 JPA 样板代码sessionConfig.setAvailableTools(new ToolSet()
.addCustom("*") // all registered custom tools
.addBuiltIn("web_fetch")); // only the web_fetch built-in
这是重要的生产级考量。你不需要暴露每一个内置工具(文件系统访问、shell 执行等),而是明确选择仅开放代理所需的工具。在示例应用中,我们允许所有自定义工具加上 web_fetch,以便代理在搜索阶段能够查询实时房产信息。
以下是本文涵盖的内容:
sendAndWait(...) 自动处理完整的工具调用循环session.on(...) 支持响应式 UI 和可观测性探索 BYOK 支持。GitHub Copilot SDK 可以直接对接模型提供商使用,例如 OpenAI、Azure、Anthropic 或 OpenAI 兼容端点,只需传入带有你自己的 baseUrl + apiKey(或 bearer token)的 provider/ProviderConfig。无需 Copilot 订阅。
克隆示例应用并在本地运行。同时提交多个查询,观察虚拟线程的工作方式。
切换模型。尝试 session.setModel(...) 来实验不同的 Copilot 模型。
添加你自己的工具。定义一个新的 @CopilotTool 方法(抵押贷款计算器、学区查询),然后观察 AI 智能体如何发现并使用它。
部署到 Azure。Open Liberty 在 Azure App Service、AKS 或 Azure Container Apps 上运行良好。参阅 https://aka.ms/java/ee 上的 Jakarta EE on Azure 指南。
Copilot SDK for Java 以无需 IDE、无框架锁定的形式,将 GitHub Copilot 的全部能力置于你的 Java 代码背后。
克隆示例应用并亲自试用 >
Ed Burns 是 Microsoft 和 GitHub 技术团队中负责带来 idiomatic Java 体验的首席软件工程师。Ed 自 1997 年起从事 Java 工作,涵盖客户端、服务器、云和 AI 等各个领域。
在 GitHub Copilot 应用中超越聊天功能,使用这些斜杠命令。它们将帮助你规划、协作、自动化和自定义开发工作流程。
了解如何构建工具来简化你的工作方式——无需编写一行代码。
与其产生一个巨大的、无法审查的拉取请求,不如教编码代理将工作分解为清晰的、有序的堆栈,使用 GitHub stacked pull requests。