{"id":97992,"date":"2026-08-10T12:30:00","date_gmt":"2026-08-10T19:30:00","guid":{"rendered":"https:\/\/github.blog\/?p=97992"},"modified":"2026-08-10T12:22:42","modified_gmt":"2026-08-10T19:22:42","slug":"using-the-github-copilot-sdk-for-java","status":"publish","type":"post","link":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/","title":{"rendered":"Using the GitHub Copilot SDK for Java"},"content":{"rendered":"<!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD HTML 4.0 Transitional\/\/EN\" \"http:\/\/www.w3.org\/TR\/REC-html40\/loose.dtd\">\n<html><body><p class=\"wp-block-paragraph\">Java developers no longer have to rely on Java framework-specific approaches to drive AI from their enterprise apps.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">While it is true that Langchain4j empowered developers by disintermediating specific AI vendors, you still had a dependency on Langchain4j. And with Spring AI, well, of course you had a dependency on design choices made by Spring, if not on Spring itself.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now, GitHub Copilot SDK for Java is the first truly framework agnostic way to drive AI from Java. And with its BYOK support, GitHub Copilot SDK for Java is also AI vendor neutral.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>&#128161; Even though it&rsquo;s called GitHub Copilot SDK, you can use it with any direct model provider, such as OpenAI, Azure, Anthropic, or OpenAI-compatible endpoints, by passing a <code>provider<\/code>\/<code>ProviderConfig<\/code> with your own <code>baseUrl<\/code> + <code>apiKey<\/code> (or bearer token). No Copilot subscription required.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The GitHub Copilot SDK for Java is a client library that empowers your server-side Java code to create Copilot agent sessions, register tools, send prompts, and receive structured responses&mdash;all programmatically. It works in server environments, including Jakarta EE and Spring. If you&rsquo;ve been building enterprise Java for any length of time, this SDK will feel like home: <code>CompletableFuture<\/code>, annotations, lambdas, virtual threads, it&rsquo;s all here.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This post shows you how to use the SDK, walks through a complete Jakarta EE 11 sample application, and leaves you with concrete next steps to try it yourself. I chose Jakarta EE 11 for my demo because I was the lead release coordinator for that release. I believe in open standards as the best way to empower developers. For more on Jakarta EE 11 see <a href=\"https:\/\/www.infoq.com\/news\/2025\/07\/jakarta-ee-11-updates\/\">this InfoQ article<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This sample app is an agent harness using Jakarta EE 11. But, of course, developers can build their own agent harness using the well-known Java frameworks and libraries of their choice.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/microsoft\/Build26-BRK206-your-agent-anywhere-multiclient-multidevice-with-github-copilot-sdk\">Clone the sample app and try it yourself &gt;<\/a><\/p>\n\n\n\n<h2 id=\"h-where-to-get-it\" class=\"wp-block-heading\">Where to get it<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The SDK is available as a Maven dependency:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>&lt;dependency&gt;\n    &lt;groupId&gt;com.github&lt;\/groupId&gt;\n    &lt;artifactId&gt;copilot-sdk-java&lt;\/artifactId&gt;\n    &lt;version&gt;1.0.7-preview.1&lt;\/version&gt;\n&lt;\/dependency&gt;<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value=\"&lt;dependency&gt;\n    &lt;groupId&gt;com.github&lt;\/groupId&gt;\n    &lt;artifactId&gt;copilot-sdk-java&lt;\/artifactId&gt;\n    &lt;version&gt;1.0.7-preview.1&lt;\/version&gt;\n&lt;\/dependency&gt;\" tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\"><strong>Prerequisites:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>JDK 17 or 25 (25 recommended &mdash; unlocks virtual threads and other modern features)<\/li>\n\n\n\n<li>Maven 3.9+<\/li>\n\n\n\n<li>A GitHub account with an active Copilot subscription<\/li>\n\n\n\n<li>The Copilot CLI installed locally at version 1.0.71 or later.<\/li>\n<\/ul>\n\n\n\n<h2 id=\"h-walk-through-the-sample-app\" class=\"wp-block-heading\">Walk through the sample app<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The best way to see the SDK in action is to run <a href=\"https:\/\/github.com\/microsoft\/Build26-BRK206-your-agent-anywhere-multiclient-multidevice-with-github-copilot-sdk\">this sample application<\/a>.<\/p>\n\n\n\n<h3 id=\"h-get-the-code\" class=\"wp-block-heading\">Get the code<\/h3>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>git clone https:\/\/github.com\/microsoft\/Build26-BRK206-your-agent-anywhere-multiclient-multidevice-with-github-copilot-sdk.git\ncd Build26-BRK206-your-agent-anywhere-multiclient-multidevice-with-github-copilot-sdk\/src\/java-agent-orchestrator\nmvn clean package liberty:run\n# Open http:\/\/localhost:9080\/index.xhtml<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value=\"git clone https:\/\/github.com\/microsoft\/Build26-BRK206-your-agent-anywhere-multiclient-multidevice-with-github-copilot-sdk.git\ncd Build26-BRK206-your-agent-anywhere-multiclient-multidevice-with-github-copilot-sdk\/src\/java-agent-orchestrator\nmvn clean package liberty:run\n# Open http:\/\/localhost:9080\/index.xhtml\" tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">The Java demo is built on:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Concern<\/th><th>Technology<\/th><\/tr><\/thead><tbody><tr><td>Runtime<\/td><td>Open Liberty 26.0.0.5<\/td><\/tr><tr><td>Platform<\/td><td>Jakarta EE 11 (Faces 4.1, CDI 4.1, WebSocket 2.2, Data 1.0, Persistence 3.2)<\/td><\/tr><tr><td>UI<\/td><td>PrimeFaces 15.0.16<\/td><\/tr><tr><td>AI orchestration<\/td><td>Copilot SDK for Java 1.0.7-preview.1<\/td><\/tr><tr><td>Database<\/td><td>H2 in-memory (10 seed property listings)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 id=\"h-what-the-app-does\" class=\"wp-block-heading\">What the app does<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The application is a real-estate lead-management agent pipeline. A customer submits an enquiry (&ldquo;I&rsquo;m looking for a 3-bedroom house in London under &pound;800,000&rdquo;), and the system spins up an isolated Copilot Agent on a virtual thread to process it through a pipeline:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" height=\"173\" width=\"1024\" src=\"https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-01-app-flow-diagram.png?resize=1024%2C173\" alt=\"Application flow diagram showing the pipeline stages: Customer Enquiry flows to QUEUED, then VALIDATING, which branches to either SEARCHING (if genuine) or REJECTED (if spam\/off-topic). SEARCHING leads to WRITING_REPORT (if matches found) or NO MATCHES. WRITING_REPORT completes at DONE.\" class=\"wp-image-98000\" srcset=\"https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-01-app-flow-diagram.png?w=2454 2454w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-01-app-flow-diagram.png?w=300 300w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-01-app-flow-diagram.png?w=768 768w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-01-app-flow-diagram.png?w=1024 1024w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-01-app-flow-diagram.png?w=1536 1536w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-01-app-flow-diagram.png?w=2048 2048w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The architecture uses Jakarta WebSocket to push real-time status updates from the server to the browser, so you can watch agents progress through phases as the model calls tools:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" height=\"628\" width=\"1024\" src=\"https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-02-app-architecture-diagram.png?resize=1024%2C628\" alt=\"Application architecture diagram showing Browser with Pipeline Dashboard connecting to Open Liberty server containing AppState, CopilotClient in EMPTY mode, virtual thread agents, and WebSocket push for real-time UI updates.\" class=\"wp-image-98001\" srcset=\"https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-02-app-architecture-diagram.png?w=2034 2034w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-02-app-architecture-diagram.png?w=300 300w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-02-app-architecture-diagram.png?w=768 768w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-02-app-architecture-diagram.png?w=1024 1024w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-02-app-architecture-diagram.png?w=1536 1536w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Submit multiple inquiries simultaneously to see concurrent virtual-thread agents in action. Each one processes independently with its own Copilot session.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" height=\"940\" width=\"1024\" src=\"https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-03-sample-app-01.png?resize=1024%2C940\" alt=\"Screenshot of the sample application showing the pipeline dashboard with multiple enquiries being processed concurrently.\" class=\"wp-image-98002\" srcset=\"https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-03-sample-app-01.png?w=1806 1806w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-03-sample-app-01.png?w=300 300w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-03-sample-app-01.png?w=768 768w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-03-sample-app-01.png?w=1024 1024w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-03-sample-app-01.png?w=1536 1536w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" height=\"1024\" width=\"778\" src=\"https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-04-sample-app-02.png?resize=778%2C1024\" alt=\"Screenshot of the sample application showing detailed agent event log and property search results.\" class=\"wp-image-98003\" srcset=\"https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-04-sample-app-02.png?w=1804 1804w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-04-sample-app-02.png?w=228 228w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-04-sample-app-02.png?w=768 768w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-04-sample-app-02.png?w=778 778w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-04-sample-app-02.png?w=1167 1167w, https:\/\/github.blog\/wp-content\/uploads\/2026\/08\/figure-04-sample-app-02.png?w=1556 1556w\" sizes=\"auto, (max-width: 778px) 100vw, 778px\" \/><\/figure>\n\n\n\n<h3 id=\"h-sdk-features-in-action\" class=\"wp-block-heading\">SDK features in action<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let&rsquo;s walk through the key SDK features as they appear in the sample code.<\/p>\n\n\n\n<h4 id=\"h-defining-tools-with-copilottool\" class=\"wp-block-heading\">Defining tools with <code>@CopilotTool<\/code><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">This is the headline API. If you&rsquo;ve ever written a <code>@GET<\/code> endpoint in JAX-RS or an <code>@MessageDriven<\/code> bean, this will feel instantly familiar:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>@CopilotTool(value = \"Sets the current phase of the agent. Use this to report progress.\",\n             name = \"set_current_phase\")\npublic String setCurrentPhase(\n        @CopilotToolParam(\"The phase to transition to (VALIDATING, SEARCHING, \"\n                + \"WRITING_REPORT, REJECTED_GARBAGE, REJECTED_NO_MATCHES, or DONE)\")\n        String phaseName) {\n    phase = Phase.valueOf(phaseName.trim().toUpperCase(Locale.ROOT));\n    notifyUi();\n    return \"Phase set to \" + phase.getLabel();\n}<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value='@CopilotTool(value = \"Sets the current phase of the agent. Use this to report progress.\",\n             name = \"set_current_phase\")\npublic String setCurrentPhase(\n        @CopilotToolParam(\"The phase to transition to (VALIDATING, SEARCHING, \"\n                + \"WRITING_REPORT, REJECTED_GARBAGE, REJECTED_NO_MATCHES, or DONE)\")\n        String phaseName) {\n    phase = Phase.valueOf(phaseName.trim().toUpperCase(Locale.ROOT));\n    notifyUi();\n    return \"Phase set to \" + phase.getLabel();\n}' tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">The <code>@CopilotTool<\/code> annotation declares the method as a tool the model can call. The <code>@CopilotToolParam<\/code> annotation describes each parameter so the model knows what to pass. The SDK handles all the JSON Schema generation, argument parsing, and dispatch. You just write a normal Java method.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Two build prerequisites for <code>@CopilotTool<\/code>.<\/strong> The annotation-based tool API is currently an experimental feature of the SDK, so you need to configure two things in your Maven build:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Enable experimental APIs<\/strong>: pass <code>-Acopilot.experimental.allowed=true<\/code> to the compiler. Without this flag, the annotation processor will refuse to generate the tool metadata. For more details on the experimental APIs see <a href=\"https:\/\/github.com\/github\/copilot-sdk\/tree\/main\/java#using-experimental-apis\">Copilot SDK documentation<\/a>.<\/li>\n\n\n\n<li><strong>Register the annotation processor<\/strong>: add the SDK as an <code>annotationProcessorPath<\/code> so the compiler can find the <code>@CopilotTool<\/code> processor and generate the <code>$$CopilotToolMeta<\/code> classes at compile time.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Both are configured in the <code>maven-compiler-plugin<\/code>:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>&lt;plugin&gt;\n    &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\n    &lt;artifactId&gt;maven-compiler-plugin&lt;\/artifactId&gt;\n    &lt;version&gt;3.15.0&lt;\/version&gt;\n    &lt;configuration&gt;\n        &lt;compilerArgs&gt;\n            &lt;arg&gt;-Acopilot.experimental.allowed=true&lt;\/arg&gt;\n        &lt;\/compilerArgs&gt;\n        &lt;annotationProcessorPaths&gt;\n            &lt;path&gt;\n                &lt;groupId&gt;com.github&lt;\/groupId&gt;\n                &lt;artifactId&gt;copilot-sdk-java&lt;\/artifactId&gt;\n                &lt;version&gt;1.0.7-preview.1&lt;\/version&gt;\n            &lt;\/path&gt;\n        &lt;\/annotationProcessorPaths&gt;\n    &lt;\/configuration&gt;\n&lt;\/plugin&gt;<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value=\"&lt;plugin&gt;\n    &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\n    &lt;artifactId&gt;maven-compiler-plugin&lt;\/artifactId&gt;\n    &lt;version&gt;3.15.0&lt;\/version&gt;\n    &lt;configuration&gt;\n        &lt;compilerArgs&gt;\n            &lt;arg&gt;-Acopilot.experimental.allowed=true&lt;\/arg&gt;\n        &lt;\/compilerArgs&gt;\n        &lt;annotationProcessorPaths&gt;\n            &lt;path&gt;\n                &lt;groupId&gt;com.github&lt;\/groupId&gt;\n                &lt;artifactId&gt;copilot-sdk-java&lt;\/artifactId&gt;\n                &lt;version&gt;1.0.7-preview.1&lt;\/version&gt;\n            &lt;\/path&gt;\n        &lt;\/annotationProcessorPaths&gt;\n    &lt;\/configuration&gt;\n&lt;\/plugin&gt;\" tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">To register all annotated tools from an object:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>List&lt;ToolDefinition&gt; annotatedTools = ToolDefinition.fromObject(this);<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value=\"List&lt;ToolDefinition&gt; annotatedTools = ToolDefinition.fromObject(this);\" tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<h4 id=\"h-inline-lambda-tools-with-tooldefinition-from\" class=\"wp-block-heading\">Inline lambda tools with <code>ToolDefinition.from(...)<\/code><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">When you want a tool defined at the call site without a dedicated method, use the lambda style:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>ToolDefinition reportIntentTool = ToolDefinition\n        .from(\"report_intent\",\n              \"Reports the current intent of the agent\",\n              Param.of(String.class, \"intent\", \"Intent in max 4 words\"),\n              (String intent) -&gt; {\n                  currentIntent = intent;\n                  addEvent(Instant.now(), \"intent\", \"Intent updated\", intent);\n                  notifyUi();\n                  return \"ok\";\n              })\n        .overridesBuiltInTool(true);<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value='ToolDefinition reportIntentTool = ToolDefinition\n        .from(\"report_intent\",\n              \"Reports the current intent of the agent\",\n              Param.of(String.class, \"intent\", \"Intent in max 4 words\"),\n              (String intent) -&gt; {\n                  currentIntent = intent;\n                  addEvent(Instant.now(), \"intent\", \"Intent updated\", intent);\n                  notifyUi();\n                  return \"ok\";\n              })\n        .overridesBuiltInTool(true);' tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">Notice <code>.overridesBuiltInTool(true)<\/code>. This tells the SDK that our <code>report_intent<\/code> tool deliberately replaces a built-in tool of the same name. This is useful when you need custom behaviour for a tool the model already knows about.<\/p>\n\n\n\n<h4 id=\"h-cross-class-tool-scanning\" class=\"wp-block-heading\">Cross-class tool scanning<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Tools don&rsquo;t have to live in the same class as your agent logic. Here&rsquo;s <code>searchProperties<\/code> defined in a separate CDI bean:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>@ApplicationScoped\npublic class PropertyDatabase {\n\n    @CopilotTool(value = \"Searches the real estate listings database. \"\n                       + \"Returns up to 10 matching properties.\",\n                 name = \"search_properties\")\n    public List&lt;Property&gt; searchProperties(\n            @CopilotToolParam(\"Property type substring (e.g. 'flat', 'house')\") String type,\n            @CopilotToolParam(\"City substring (e.g. 'London', 'Bristol')\") String city,\n            @CopilotToolParam(\"Minimum number of bedrooms (0 for no minimum)\") int minBedrooms,\n            @CopilotToolParam(\"Maximum price in GBP (0 for no maximum)\") double maxPriceGbp) {\n        \/\/ ... filter and return matching properties ...\n    }\n}<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value=\"@ApplicationScoped\npublic class PropertyDatabase {\n\n    @CopilotTool(value = &quot;Searches the real estate listings database. &quot;\n                       + &quot;Returns up to 10 matching properties.&quot;,\n                 name = &quot;search_properties&quot;)\n    public List&lt;Property&gt; searchProperties(\n            @CopilotToolParam(&quot;Property type substring (e.g. 'flat', 'house')&quot;) String type,\n            @CopilotToolParam(&quot;City substring (e.g. 'London', 'Bristol')&quot;) String city,\n            @CopilotToolParam(&quot;Minimum number of bedrooms (0 for no minimum)&quot;) int minBedrooms,\n            @CopilotToolParam(&quot;Maximum price in GBP (0 for no maximum)&quot;) double maxPriceGbp) {\n        \/\/ ... filter and return matching properties ...\n    }\n}\" tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">You would normally register these with <code>ToolDefinition.fromObject(propertyDatabase)<\/code>. In the sample app, we use a lambda wrapper instead, because CDI client proxies can obscure the annotation metadata.<\/p>\n\n\n\n<h4 id=\"h-customizing-the-system-message\" class=\"wp-block-heading\">Customizing the system message<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The SDK gives you fine-grained control over the system message. Use <code>SystemMessageMode.CUSTOMIZE<\/code> to replace specific sections while preserving the rest:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>SystemMessageConfig systemMessage = new SystemMessageConfig()\n        .setMode(SystemMessageMode.CUSTOMIZE)\n        .setSections(Map.of(SystemMessageSections.IDENTITY,\n            new SectionOverride()\n                .setAction(SectionOverrideAction.REPLACE)\n                .setContent(\"\"\"\n                    You are part of a real estate recommendation system.\n                    You will receive enquiries from customers, and you must\n                    carry out the following workflow...\n                    \"\"\")));<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value='SystemMessageConfig systemMessage = new SystemMessageConfig()\n        .setMode(SystemMessageMode.CUSTOMIZE)\n        .setSections(Map.of(SystemMessageSections.IDENTITY,\n            new SectionOverride()\n                .setAction(SectionOverrideAction.REPLACE)\n                .setContent(\"\"\"\n                    You are part of a real estate recommendation system.\n                    You will receive enquiries from customers, and you must\n                    carry out the following workflow...\n                    \"\"\")));' tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">The text block (<code>\"\"\"...\"\"\"<\/code>) makes multi-line prompts readable without string concatenation. The <code>IDENTITY<\/code> section override replaces only the model&rsquo;s self-description while leaving safety guardrails intact. If you prefer a simpler approach, <code>SystemMessageMode.APPEND<\/code> adds your content after the default system message without replacing anything.<\/p>\n\n\n\n<h4 id=\"h-the-agentic-loop-sendandwait\" class=\"wp-block-heading\">The agentic loop: <code>sendAndWait(...)<\/code><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">One line kicks off the full agentic loop:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>session = client.createSession(sessionConfig).get();\n\/\/ ...\nAssistantMessageEvent result = session.sendAndWait(escapedEnquiry).get();<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value=\"session = client.createSession(sessionConfig).get();\n\/\/ ...\nAssistantMessageEvent result = session.sendAndWait(escapedEnquiry).get();\" tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">Behind <code>.get()<\/code>, the model reasons, calls your tools (potentially multiple times), and returns its final response. On a virtual thread, <code>.get()<\/code> is cheap. No platform thread is consumed while waiting. The SDK dispatches tool calls to your registered handlers automatically and feeds results back to the model until it&rsquo;s done.<\/p>\n\n\n\n<h4 id=\"h-real-time-event-handling-with-session-on\" class=\"wp-block-heading\">Real-time event handling with <code>session.on(...)<\/code><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Subscribe to session events to build responsive UIs:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>sessionSubscription = session.on(event -&gt; {\n    captureSessionEvent(event);\n    uiUpdateSocket.pushDetailUpdate(id);\n});<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value=\"sessionSubscription = session.on(event -&gt; {\n    captureSessionEvent(event);\n    uiUpdateSocket.pushDetailUpdate(id);\n});\" tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">Every tool call, every result, every assistant message fires an event. The sample app captures these events and pushes them to the browser via Jakarta WebSocket, so the pipeline dashboard updates in real time. You can use pattern matching to handle specific event types:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>if (event instanceof AssistantMessageEvent msg) {\n    finalReport = msg.getData().content();\n} else if (event instanceof ToolExecutionStartEvent start) {\n    \/\/ Tool is being invoked...\n}<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value=\"if (event instanceof AssistantMessageEvent msg) {\n    finalReport = msg.getData().content();\n} else if (event instanceof ToolExecutionStartEvent start) {\n    \/\/ Tool is being invoked...\n}\" tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<h4 id=\"h-headless-client-and-permission-handling\" class=\"wp-block-heading\">Headless client and permission handling<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The client is configured for server-side operation:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>copilotClient = new CopilotClient(\n        new CopilotClientOptions()\n                .setMode(CopilotClientMode.EMPTY)\n                .setCopilotHome(copilotHome)\n                .setExecutor(contextualVirtualThreadExecutor));<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value=\"copilotClient = new CopilotClient(\n        new CopilotClientOptions()\n                .setMode(CopilotClientMode.EMPTY)\n                .setCopilotHome(copilotHome)\n                .setExecutor(contextualVirtualThreadExecutor));\" tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\"><code>CopilotClientMode.EMPTY<\/code> means no IDE integration &mdash; the client talks directly to the Copilot CLI. The custom <code>Executor<\/code> (discussed below) ensures tool callbacks run with container context.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For permission handling, the sample uses:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>sessionConfig.setOnPermissionRequest(PermissionHandler.APPROVE_ALL);<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value=\"sessionConfig.setOnPermissionRequest(PermissionHandler.APPROVE_ALL);\" tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\"><code>APPROVE_ALL<\/code> is appropriate for demos and development. In production, implement a real permission policy that validates which tools the model is allowed to invoke.<\/p>\n\n\n\n<h3 id=\"h-jakarta-ee-integration-patterns\" class=\"wp-block-heading\">Jakarta EE integration patterns<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The SDK is not a framework island. It composes naturally with Jakarta EE &mdash; and of course also with proprietary frameworks such as Spring.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The <code>Executor<\/code> parameter is the key integration point.<\/strong> Jakarta Concurrency (&sect;5.2 in the 3.1 spec) requires that application-created threads be obtained from a <code>ManagedThreadFactory<\/code> so the container can:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Track the thread for lifecycle shutdown (<code>@PreDestroy<\/code> \/ server stop)<\/li>\n\n\n\n<li>Apply concurrency constraints and policies<\/li>\n\n\n\n<li>Propagate context automatically (without needing manual <code>contextualRunnable<\/code>)<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Open Liberty 26.x supports virtual-thread <code>ManagedThreadFactory<\/code> via the <code>virtual<\/code> attribute in <code>server.xml<\/code>.<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>&lt;managedThreadFactory jndiName=\"concurrent\/virtualThreadFactory\" virtual=\"true\" \/&gt;<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value='&lt;managedThreadFactory jndiName=\"concurrent\/virtualThreadFactory\" virtual=\"true\" \/&gt;' tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">Then, in <code>AppState.java<\/code> we inject the factory:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>@Resource(lookup = \"concurrent\/virtualThreadFactory\")\nprivate ManagedThreadFactory virtualThreadFactory;<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value='@Resource(lookup = \"concurrent\/virtualThreadFactory\")\nprivate ManagedThreadFactory virtualThreadFactory;' tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">And use it to create the <code>Executor<\/code> we pass to the Copilot SDK.<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>\/\/ The ManagedThreadFactory (virtual=true) creates container-managed virtual\n\/\/ threads that automatically propagate CDI, JNDI, and transaction context.\nExecutor managedVirtualExecutor = runnable -&gt;\n    virtualThreadFactory.newThread(runnable).start()\n\nString copilotHome = Path.of(System.getProperty(\"user.home\"), \".copilot\").toString();\nCopilotClientOptions copilotClientOptions = new CopilotClientOptions()\n        .setMode(CopilotClientMode.EMPTY)\n        .setCopilotHome(copilotHome)\n        .setExecutor(managedVirtualExecutor);\ncopilotClient = new CopilotClient(copilotClientOptions);<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value='\/\/ The ManagedThreadFactory (virtual=true) creates container-managed virtual\n\/\/ threads that automatically propagate CDI, JNDI, and transaction context.\nExecutor managedVirtualExecutor = runnable -&gt;\n    virtualThreadFactory.newThread(runnable).start()\n\nString copilotHome = Path.of(System.getProperty(\"user.home\"), \".copilot\").toString();\nCopilotClientOptions copilotClientOptions = new CopilotClientOptions()\n        .setMode(CopilotClientMode.EMPTY)\n        .setCopilotHome(copilotHome)\n        .setExecutor(managedVirtualExecutor);\ncopilotClient = new CopilotClient(copilotClientOptions);' tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">This creates virtual threads that carry the container&rsquo;s context. When the SDK dispatches a tool call to <code>searchProperties()<\/code>, that method can <code>@Inject<\/code> a JPA repository and query the database, because the container context is present on the callback thread.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Other integration patterns in the sample:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>CDI <code>@ApplicationScoped<\/code><\/strong> for the singleton <code>CopilotClient<\/code> (one client per application lifecycle).<\/li>\n\n\n\n<li><strong>Jakarta Faces <code>f:websocket<\/code> push<\/strong> for real-time browser updates via <code>PushContext<\/code>.<\/li>\n\n\n\n<li><strong>Jakarta Data <code>@Repository<\/code><\/strong> for type-safe database queries without raw JPA boilerplate.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Fine-grained tool access control with <code>ToolSet<\/code>.<\/strong> The <code>SessionConfig<\/code> lets you specify exactly which tools each session can access:<\/p>\n\n\n<div class=\"wp-block-code-wrapper\">\n<pre class=\"wp-block-code\"><code>sessionConfig.setAvailableTools(new ToolSet()\n        .addCustom(\"*\")           \/\/ all registered custom tools\n        .addBuiltIn(\"web_fetch\")); \/\/ only the web_fetch built-in<\/code><\/pre>\n<clipboard-copy aria-label=\"Copy\" class=\"code-copy-btn\" data-copy-feedback=\"Copied!\" value='sessionConfig.setAvailableTools(new ToolSet()\n        .addCustom(\"*\")           \/\/ all registered custom tools\n        .addBuiltIn(\"web_fetch\")); \/\/ only the web_fetch built-in' tabindex=\"0\" role=\"button\"><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-copy js-clipboard-copy-icon\"><path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z\"><\/path><path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z\"><\/path><\/svg><svg aria-hidden=\"true\" height=\"16\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" class=\"octicon octicon-check js-clipboard-check-icon\"><path d=\"M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z\"><\/path><\/svg><\/clipboard-copy><\/div>\n\n\n<p class=\"wp-block-paragraph\">This is an important production concern. Rather than exposing every built-in tool (file system access, shell execution, etc.), you explicitly opt in to only what the agent needs. In the sample app, we allow all custom tools plus <code>web_fetch<\/code> so the agent can look up real-time property information during the Search phase.<\/p>\n\n\n\n<h2 id=\"h-summary\" class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here&rsquo;s what we covered:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Java-native API<\/strong>: <code>CompletableFuture<\/code>, annotations, lambdas, and virtual threads make the SDK feel like idiomatic Java, not a ported-from-another-language afterthought.<\/li>\n\n\n\n<li><strong>Three tool-definition styles<\/strong>: annotations for enterprise patterns, lambdas for inline convenience, JSON Schema for full control.<\/li>\n\n\n\n<li><strong>System message customization<\/strong>: section-level overrides give you precise control over agent behaviour.<\/li>\n\n\n\n<li><strong>The agentic loop in one line<\/strong>: <code>sendAndWait(...)<\/code> handles the full tool-calling loop automatically.<\/li>\n\n\n\n<li><strong>Real-time event streaming<\/strong>: <code>session.on(...)<\/code> enables responsive UIs and observability.<\/li>\n\n\n\n<li><strong>Headless server-side operation<\/strong>: no IDE required; runs anywhere the Copilot CLI is available.<\/li>\n\n\n\n<li><strong>Natural composition with Jakarta EE<\/strong>: CDI, JPA, WebSocket, and virtual threads all work together through the <code>Executor<\/code> integration point.<\/li>\n<\/ul>\n\n\n\n<h2 id=\"h-what-to-try-next\" class=\"wp-block-heading\">What to try next<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Explore the BYOK support.<\/strong> The GitHub Copilot SDK can be used directly against model providers, for example OpenAI, Azure, Anthropic, or OpenAI-compatible endpoints, by passing a <code>provider<\/code>\/<code>ProviderConfig<\/code> with your own <code>baseUrl<\/code> + <code>apiKey<\/code> (or bearer token). No Copilot subscription required.<\/li>\n\n\n\n<li><strong>Clone the sample app<\/strong> and run it locally. Submit multiple enquiries simultaneously to see virtual threads in action.<\/li>\n\n\n\n<li><strong>Swap the model.<\/strong> Try <code>session.setModel(...)<\/code> to experiment with different Copilot models.<\/li>\n\n\n\n<li><strong>Add your own tool.<\/strong> Define a new <code>@CopilotTool<\/code> method (a mortgage calculator, a school-district lookup) and watch the agent discover and use it.<\/li>\n\n\n\n<li><strong>Deploy to Azure.<\/strong> Open Liberty runs great on Azure App Service, AKS, or Azure Container Apps. See the Jakarta EE on Azure guidance at <a href=\"https:\/\/aka.ms\/java\/ee\">https:\/\/aka.ms\/java\/ee<\/a>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The Copilot SDK for Java puts the full power of GitHub Copilot behind your Java code with no IDE required and no framework lock-in.<\/p>\n\n\n\n<div class=\"wp-block-group post-content-cta has-global-padding is-layout-constrained wp-block-group-is-layout-constrained\">\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/microsoft\/Build26-BRK206-your-agent-anywhere-multiclient-multidevice-with-github-copilot-sdk\">Clone the sample app and try it yourself &gt;<\/a><\/p>\n<\/div>\n<\/body><\/html>\n","protected":false},"excerpt":{"rendered":"<p>Enterprise Java developers have a new superpower\u2014drive GitHub Copilot from idiomatic Java code with annotations, virtual threads, and more.<\/p>\n","protected":false},"author":2472,"featured_media":93173,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_gh_post_show_toc":"yes","_gh_post_is_no_robots":"no","_gh_post_is_featured":"yes","_gh_post_is_excluded":"no","_gh_post_is_unlisted":"","_gh_post_related_link_1":"","_gh_post_related_link_2":"","_gh_post_related_link_3":"","_gh_post_sq_img":"","_gh_post_sq_img_id":"","_gh_post_cta_title":"","_gh_post_cta_text":"","_gh_post_cta_link":"","_gh_post_cta_button":"","_gh_post_recirc_hide":"","_gh_post_recirc_col_1":"","_gh_post_recirc_col_2":"","_gh_post_recirc_col_3":"","_gh_post_recirc_col_4":"","_featured_video":"","_gh_post_additional_query_params":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"{title}\n\n{excerpt}\n\n{url}","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false,"_links_to":"","_links_to_target":""},"categories":[3293,72],"tags":[3802,1823],"coauthors":[3904],"class_list":["post-97992","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-and-ml","category-engineering","tag-github-copilot-sdk","tag-java"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.4 (Yoast SEO v28.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Using the GitHub Copilot SDK for Java - The GitHub Blog<\/title>\n<meta name=\"description\" content=\"Enterprise Java developers have a new superpower\u2014drive GitHub Copilot from idiomatic Java code with annotations, virtual threads, and more.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using the GitHub Copilot SDK for Java\" \/>\n<meta property=\"og:description\" content=\"Enterprise Java developers have a new superpower\u2014drive GitHub Copilot from idiomatic Java code with annotations, virtual threads, and more.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/\" \/>\n<meta property=\"og:site_name\" content=\"The GitHub Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-10T19:30:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/github.blog\/wp-content\/uploads\/2026\/01\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1080\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Edward Burns\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Edward Burns\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/\"},\"author\":{\"name\":\"Edward Burns\",\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/107e46c3d2e58230e906cda05146ca50\"},\"headline\":\"Using the GitHub Copilot SDK for Java\",\"datePublished\":\"2026-08-10T19:30:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/\"},\"wordCount\":1525,\"image\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080\",\"keywords\":[\"GitHub Copilot SDK\",\"java\"],\"articleSection\":[\"AI &amp; ML\",\"Engineering\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/\",\"url\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/\",\"name\":\"Using the GitHub Copilot SDK for Java - The GitHub Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/github.blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080\",\"datePublished\":\"2026-08-10T19:30:00+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/107e46c3d2e58230e906cda05146ca50\"},\"description\":\"Enterprise Java developers have a new superpower\u2014drive GitHub Copilot from idiomatic Java code with annotations, virtual threads, and more.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/#primaryimage\",\"url\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080\",\"contentUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080\",\"width\":1920,\"height\":1080,\"caption\":\"Copilot hovering above geometric blocks featuring the GitHub invertocat logo in a decorative scene.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/using-the-github-copilot-sdk-for-java\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/github.blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Engineering\",\"item\":\"https:\\\/\\\/github.blog\\\/engineering\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Using the GitHub Copilot SDK for Java\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/github.blog\\\/#website\",\"url\":\"https:\\\/\\\/github.blog\\\/\",\"name\":\"The GitHub Blog\",\"description\":\"Updates, ideas, and inspiration from GitHub to help developers build and design software.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/github.blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/107e46c3d2e58230e906cda05146ca50\",\"name\":\"Edward Burns\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c42c095b0936762297016fed0c4fdd6e4914e8ed4a946fae7cd340e6890cd7d7?s=96&d=mm&r=g6c17f0da575e8db06e5a1b01726eb972\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c42c095b0936762297016fed0c4fdd6e4914e8ed4a946fae7cd340e6890cd7d7?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c42c095b0936762297016fed0c4fdd6e4914e8ed4a946fae7cd340e6890cd7d7?s=96&d=mm&r=g\",\"caption\":\"Edward Burns\"},\"description\":\"Ed Burns is a Principal Software Engineer working to bring Java idiomatic experiences to Microsoft and GitHub technologies. Ed's been working with Java since 1997 in all aspects from client to server to cloud and AI.\",\"url\":\"https:\\\/\\\/github.blog\\\/author\\\/edburns\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Using the GitHub Copilot SDK for Java - The GitHub Blog","description":"Enterprise Java developers have a new superpower\u2014drive GitHub Copilot from idiomatic Java code with annotations, virtual threads, and more.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/","og_locale":"en_US","og_type":"article","og_title":"Using the GitHub Copilot SDK for Java","og_description":"Enterprise Java developers have a new superpower\u2014drive GitHub Copilot from idiomatic Java code with annotations, virtual threads, and more.","og_url":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/","og_site_name":"The GitHub Blog","article_published_time":"2026-08-10T19:30:00+00:00","og_image":[{"width":1920,"height":1080,"url":"https:\/\/github.blog\/wp-content\/uploads\/2026\/01\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080","type":"image\/png"}],"author":"Edward Burns","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Edward Burns","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/#article","isPartOf":{"@id":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/"},"author":{"name":"Edward Burns","@id":"https:\/\/github.blog\/#\/schema\/person\/107e46c3d2e58230e906cda05146ca50"},"headline":"Using the GitHub Copilot SDK for Java","datePublished":"2026-08-10T19:30:00+00:00","mainEntityOfPage":{"@id":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/"},"wordCount":1525,"image":{"@id":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/#primaryimage"},"thumbnailUrl":"https:\/\/github.blog\/wp-content\/uploads\/2026\/01\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080","keywords":["GitHub Copilot SDK","java"],"articleSection":["AI &amp; ML","Engineering"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/","url":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/","name":"Using the GitHub Copilot SDK for Java - The GitHub Blog","isPartOf":{"@id":"https:\/\/github.blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/#primaryimage"},"image":{"@id":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/#primaryimage"},"thumbnailUrl":"https:\/\/github.blog\/wp-content\/uploads\/2026\/01\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080","datePublished":"2026-08-10T19:30:00+00:00","author":{"@id":"https:\/\/github.blog\/#\/schema\/person\/107e46c3d2e58230e906cda05146ca50"},"description":"Enterprise Java developers have a new superpower\u2014drive GitHub Copilot from idiomatic Java code with annotations, virtual threads, and more.","breadcrumb":{"@id":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/#primaryimage","url":"https:\/\/github.blog\/wp-content\/uploads\/2026\/01\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080","contentUrl":"https:\/\/github.blog\/wp-content\/uploads\/2026\/01\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080","width":1920,"height":1080,"caption":"Copilot hovering above geometric blocks featuring the GitHub invertocat logo in a decorative scene."},{"@type":"BreadcrumbList","@id":"https:\/\/github.blog\/engineering\/using-the-github-copilot-sdk-for-java\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/github.blog\/"},{"@type":"ListItem","position":2,"name":"Engineering","item":"https:\/\/github.blog\/engineering\/"},{"@type":"ListItem","position":3,"name":"Using the GitHub Copilot SDK for Java"}]},{"@type":"WebSite","@id":"https:\/\/github.blog\/#website","url":"https:\/\/github.blog\/","name":"The GitHub Blog","description":"Updates, ideas, and inspiration from GitHub to help developers build and design software.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/github.blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/github.blog\/#\/schema\/person\/107e46c3d2e58230e906cda05146ca50","name":"Edward Burns","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/c42c095b0936762297016fed0c4fdd6e4914e8ed4a946fae7cd340e6890cd7d7?s=96&d=mm&r=g6c17f0da575e8db06e5a1b01726eb972","url":"https:\/\/secure.gravatar.com\/avatar\/c42c095b0936762297016fed0c4fdd6e4914e8ed4a946fae7cd340e6890cd7d7?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c42c095b0936762297016fed0c4fdd6e4914e8ed4a946fae7cd340e6890cd7d7?s=96&d=mm&r=g","caption":"Edward Burns"},"description":"Ed Burns is a Principal Software Engineer working to bring Java idiomatic experiences to Microsoft and GitHub technologies. Ed's been working with Java since 1997 in all aspects from client to server to cloud and AI.","url":"https:\/\/github.blog\/author\/edburns\/"}]}},"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/pamS32-puw","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/github.blog\/wp-content\/uploads\/2026\/01\/generic-copilot-flying-invertocat-logo-github.png?fit=1920%2C1080","_links":{"self":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/97992","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/users\/2472"}],"replies":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/comments?post=97992"}],"version-history":[{"count":6,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/97992\/revisions"}],"predecessor-version":[{"id":98103,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/97992\/revisions\/98103"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/media\/93173"}],"wp:attachment":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/media?parent=97992"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/categories?post=97992"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/tags?post=97992"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/coauthors?post=97992"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}