Calling AgentCore models, MCP services, Skills, memory, and credentials from a Java application means handling service addresses, access credentials, and protocol encapsulation on your own. The AgentCore Java SDK unifies these hosted resources behind a single AgentCore client entry point. Adapter modules for Spring AI, LangChain4j, and AgentScope Java let you build Agent applications that expose AG-UI and OpenAI Chat Completions services.
The following sections cover the complete implementation path, from installing the SDK to calling the deployed service. The resource sections from "Call a hosted model" through "Connect custom resources" are independent references — go directly to the resource you need. To build, deploy, and call a complete Agent service, follow "Build an Agent service with LangChain4j" and then "Call the Agent service".
Prerequisites
AgentCore is activated, and a workspace is created in the AgentCore console. For instructions, see Manage a workspace.
The resources used by the examples are prepared as described in the following table, and the Agent has the required access permissions.
The build environment runs JDK 17 or later and Maven 3.9 or later.
Placeholder | Resource | Requirement |
| Model Connection | Created. See Manage models |
| Model | Configured in the selected model connection. The framework tool examples require a model that supports tool calling |
| MCP Service | Created. See Manage MCP services |
| Skill | Enabled, with a published version available. See Manage Skills |
| MemoryStore | Created |
| Credential (API key) | Created |
| Credential (MCP header) | Created, and allowed to apply to the target MCP service |
All examples in this topic use the placeholder values in the preceding table. Replace them with your own resource names. To call models only, you do not need an MCP service, a Skill, a MemoryStore, or additional credentials.
The hosted-resource examples run in the AgentCore managed environment and get their access settings from the runtime environment, so the application code does not need platform access keys.
Install the SDK
The SDK is published on Maven Central, so no additional repository configuration is required. Add the base SDK dependency to pom.xml:
<dependency>
<groupId>io.github.ai-agentcore</groupId>
<artifactId>agentcore-sdk</artifactId>
<version>0.1.0</version>
</dependency>Add the remaining modules with the same groupId and version as needed:
Module (artifactId) | Capabilities |
| Base SDK, which provides the Model, MCP, Skill, Memory, and Credential resource interfaces |
| AG-UI, OpenAI Chat Completions, and custom protocol services |
| Spring AI adapter |
| LangChain4j adapter |
| AgentScope Java adapter |
The framework modules bring in the base SDK and the corresponding framework dependencies, so you do not need to declare them again. For artifact coordinates, see Maven Central. Code package names start with io.agentcore, which differs from the Maven groupId io.github.ai-agentcore.
Call a hosted model
When you call a hosted model, specify the model connection name and the model name separately. You do not need to assemble the service address manually.
try (var core = AgentCore.auto()) {
var model = core.model("my-model-connection", "my-model").block();
var response = model.completion(
List.of(Map.of("role", "user", "content", "Introduce Hangzhou in one sentence.")),
Map.of("temperature", 0.2)).block();
}The base APIs return the Reactor types Mono and Flux. Use block() only on a regular main thread. In reactive requests such as WebFlux, compose the returned values instead of blocking the event loop.
Streaming output
Use stream for streaming output:
model.stream(messages).doOnNext(System.out::println).blockLast();A regular call and a streaming call are two independent requests. The response structure depends on the model protocol, and the OpenAI and Anthropic protocols return different fields.
Responses API
If the model uses the OpenAI protocol and supports the Responses API, you can call responses(input, parameters) and responsesStream(input, parameters). When a Responses call fails, the SDK does not automatically fall back to Chat Completions.
Limits
The hosted model client does not provide embedding capabilities. The embedding(input, parameters) method of a direct OpenAI-compatible client applies only to services that support vector generation.
Use MCP tools
Use the MCP client within the lifecycle of core:
var mcp = core.mcp("my-mcp").block();
mcp.listTools().block();
mcp.callTool("<tool-name>", Map.of("<parameter-name>", "<parameter-value>")).block();listTools() only discovers tools and does not run them. callTool() starts a call with a tool name and parameters.
To let the model select and run tools on its own, register the tools with an Agent framework. For details, see "Build an Agent service with LangChain4j" and "Integrate other frameworks". Calling a model alone does not automatically run MCP tools.
Use Skills
Load a platform Skill and get its tools:
var skill = core.skills().load("my-skill", "1.0.0").block();
skill.tools();The version 1.0.0 must be a published version. If you omit the version, the latest version is resolved. A single Core pins the version that was first loaded successfully, so specify the version explicitly.
Load local Skills from a directory:
core.skills().local(Path.of("./skills")).block();Each Skill contains a SKILL.md file and the files that it references. To load multiple Skills, use io.agentcore.skill.Skill.tools(skills, workingDirectory) to generate the tools together.
Loading a Skill is not the same as running it. Load only Skills from trusted sources: the scripts in a Skill run with the permissions of the application process, and the runtime environment must have the script dependencies installed in advance. If command execution is not required, set ALLOW_EXECUTE_COMMAND=false.
Use memory
A MemoryStore stores and retrieves long-term memory. It does not replace the conversation history of the Agent framework, and the retrieved results reach the model through the application code or the framework adapter.
Write and retrieve memory:
var store = core.memory("my-memory");
var writeScope = new MemoryScope("example-user", "example-agent", "example-session");
store.addMemories(text, writeScope).block();
var readScope = new MemoryScope("example-user", "example-agent", null);
store.searchMemories(query, readScope, 5).block();Pass sessionId as null during retrieval to search across sessions.
Parameter | Description |
| The logical identifier of the business user |
| The logical identifier of the Agent |
| The session identifier. If you specify it during retrieval, the search is limited to that session |
| The maximum number of results to return |
The workspace comes from the resource context of Core and does not need to be passed again. Scope fields must come from a trusted business context, must not be set arbitrarily by the model, and do not replace access control. In multi-user scenarios, set the scope explicitly.
Besides writing and retrieving memory, a MemoryStore also supports listMemories, getMemory, updateMemory, deleteMemory, listMemorySessions, and listMemorySessionMessages. To query session messages, provide the session ID and at least one of userId or agentId.
Newly written memory may take some time to become retrievable. If the first retrieval returns no results, confirm that the write succeeded and that the scopes match instead of writing repeatedly.
Use memory in frameworks
All three frameworks first construct a MemoryContext and then register it in their own way:
new MemoryContext(core.memory("my-memory"), readScope, writeScope, 5);Framework | Integration |
Spring AI | Register a |
LangChain4j | Register |
AgentScope Java | Register a |
Automatic write-back is disabled by default. Enable it with the constructor that takes true. Write-back stores only the user input of the current turn and the final text answer of a turn that completed normally; it does not write history messages or tool results again. After you enable automatic write-back, do not manually write back the same turn. Registering only retriever() retrieves memory without writing back.
The following example integrates memory with LangChain4j:
var adapter = new MemoryAdapter(memory, true);
var assistant = AiServices.builder(Assistant.class)
.streamingChatModel(AgentCoreLangChain4j.streamingModel(model))
.contentRetriever(adapter.retriever())
.build();
adapter.stream(input, () -> assistant.chat(input));adapter.stream(...) returns an event stream. The Spring AI MemoryAdvisor applies to the ChatClient invocation chain, and does not apply to a separate flow that calls SpringAIEvents.stream directly.
For the complete example, see MemoryAdapters.java.
Use credentials and MCP headers
Get managed credentials:
core.credentials().get("my-api-key").block().value();
core.credentials().get("my-mcp-header").block().asHeaders();value() returns an API key, and asHeaders() returns MCP headers. Do not write credential values into source code, logs, or external responses.
Bind a credential to an MCP service:
core.mcp("my-mcp", "my-mcp-header", Map.of("X-Business-Id", "my-app")).block();The bound header credential must be allowed to apply to that MCP service. If no credential is required, use core.mcp("my-mcp"). To fix headers only without binding a credential, pass null as the second parameter.
Headers are fixed client-level settings that apply to the handshake, tool discovery, and tool calls. They do not represent the user identity of each request. Note the following limits:
Header names are case-insensitive. A conflict raises an error instead of being silently overwritten.
Headers cannot override
Authorization, platform headers, or MCP reserved fields.The SDK does not automatically copy headers from inbound requests. Do not switch user identities by modifying a shared client.
Connect custom resources
Your own models, your own MCP services, and local Skills do not need to be registered as platform resources. The application provides the connection settings.
core.directModel(name, URI.create(baseUrl), ModelClient.Protocol.OPENAI, headerProvider);
core.directMcp(URI.create(url), MCPClient.Transport.STREAMABLE_HTTP, headerProvider);The examples use the following environment variables to provide connection settings. In the calls above, name, baseUrl, and url correspond to CUSTOM_MODEL_NAME, CUSTOM_MODEL_BASE_URL, and CUSTOM_MCP_URL, and headerProvider supplies the API key from CUSTOM_MODEL_API_KEY.
Environment variable | Description |
| The name of your own model |
| The base URL of the OpenAI-compatible service, which usually ends with |
| The API key of your own model. Provide it through the runtime environment or a secrets management service instead of hardcoding it |
| The full Streamable HTTP address of your own MCP service |
A direct model connection also supports Protocol.ANTHROPIC. In that case:
The base URL does not include the trailing
/v1.Requests must specify
max_tokens.Authentication is configured as the service requires.
A direct MCP connection also supports the SSE and stdio transports, and stdio does not carry HTTP headers.
To connect multiple providers at the same time, continue to use the native providers of the three frameworks and reuse the AgentCore tool and memory adapters.
Build an Agent service with LangChain4j
In this tutorial, you connect a hosted model, MCP, and Skills to LangChain4j, and use AgentCoreServer to expose AG-UI and OpenAI Chat Completions services. All three adapter modules — Spring AI, LangChain4j, and AgentScope Java — support model, tool, execution event, and memory integration. LangChain4j is the framework used for the end-to-end example in this section. If your project already uses Spring AI or AgentScope Java, follow the corresponding guide in "Integrate other frameworks" instead.
The example service processes only the latest user text for each request. It does not configure ChatMemory, so history is not kept across requests and multi-turn conversations are managed by the application or the framework. Memory is not enabled; to use long-term memory, integrate it explicitly as described in "Use memory".
Step 1: Create a Maven project
Add agentcore-sdk-langchain4j and agentcore-sdk-server to pom.xml, both at version 0.1.0, and set the release of maven-compiler-plugin to 17. For the complete pom.xml, see the GitHub example at the end of this topic.
Step 2: Write the application entry point
The following code is simplified pseudo-code that outlines the application entry point. It does not compile as written. For the complete runnable source, see LangChainAgent.java.
var model = AgentCoreLangChain4j.streamingModel(core.model(...).block());
var tools = core.mcp(...).listTools() + core.skills().load(...).tools();
var assistant = AiServices.builder(Assistant.class)
.streamingChatModel(model)
.tools(AgentCoreLangChain4j.tools(tools))
.build();
new AgentCoreServer(request -> ... LangChain4jEvents.from(() -> assistant.chat(input))).start(9000);The example merges the MCP tools and the Skill tools and registers them with AiServices. If you do not use MCP or Skills, remove the corresponding loading and registration code.
LangChain4jEvents.from starts the TokenStream and converts text, tool calls, tool results, and message boundaries into service events. Do not call start() manually, and do not forward only the text callback, which would lose the tool execution process.
Step 3: Build and deploy
Build the application:
mvn -B -ntp packageUse the copy-dependencies goal of maven-dependency-plugin (-DincludeScope=runtime) to export the runtime dependencies, and put target/classes and target/dependency into the image. For the plugin configuration, see the complete pom.xml in LangChainAgent.java. Start the application in the managed environment (Linux):
java -cp 'target/classes:target/dependency/*' AppThe deployment settings on the platform side must match the code:
Setting | Value |
Runtime | JRE 17 or later |
Listen address |
|
Port |
|
AG-UI endpoint |
|
OpenAI Chat Completions endpoint |
|
Liveness probe |
|
Readiness probe |
|
The default AG-UI path of Java SDK 0.1.0 is /agui. Do not copy the path from examples of SDKs in other languages.
The container image must be Linux amd64, must include /bin/bash and /bin/sh, and must be reachable and pullable from the image repository. Building a JAR alone does not mean that the image contains these components.
Code upload, image building, and deployment are not handled by the SDK.
Step 4: Verify the deployment
After the deployment completes, verify that the service is running before you call it. Send a GET /readyz request (the readiness probe) to the deployed endpoint and confirm that the service reports ready. Do not continue until the readiness check succeeds.
The example service starts only after resource initialization completes. GET /healthz (the liveness probe) does not check the state of downstream resources. To customize the readiness check, use the readiness callback of AgentCoreServer.
Call the Agent service
In the following requests, replace https://<agent-endpoint> with the actual address of the application and add authentication information as needed. This address is the address of the Agent application, not the address of the model provider.
AG-UI
The AG-UI endpoint is POST /agui. The request body contains threadId, runId, messages, state, tools, context, and forwardedProps. threadId and runId must not be empty, and each run uses a new runId. The same conversation can reuse a threadId, but the example service does not automatically restore history. An empty tools field does not disable the tools registered in the code.
A successful response starts with RUN_STARTED and ends with RUN_FINISHED, and a failure returns RUN_ERROR. Tool calls and tool results are correlated by toolCallId.
OpenAI Chat Completions
The OpenAI Chat Completions endpoint is POST /openai/v1/chat/completions. The request body contains model, messages, and stream. A streaming response ends with data: [DONE], and stream=false returns regular JSON. The model field does not automatically switch the downstream model.
Choose a protocol
Aspect | AG-UI | OpenAI Chat Completions |
Text output | Supported | Supported |
Message boundaries | Keeps the message start, content, and end events | Aggregates into a single assistant message |
Tool calls | Keeps the tool call ID and parameters | Returned as |
Tool results | Returned as separate events | Not provided |
Use case | Shows a multi-step execution process | Works with existing Chat Completions clients |
Both SSE endpoints send a heartbeat comment after 15 seconds of idle time. A heartbeat is not model output and does not indicate that generation is complete.
The framework service already runs tools on the server side, so the client must not run the tool call traces that it receives. To show the complete execution process, use the AG-UI protocol with the framework event converter.
Integrate other frameworks
All three frameworks support model, tool, execution event, and memory adapters. The adapter modules of SDK 0.1.0 correspond to the following framework versions:
Framework | Adapter module | Framework version |
Spring AI |
| 2.0.1 |
LangChain4j |
| 1.20.0 |
AgentScope Java |
| 2.0.3 |
Spring AI
The entry classes are io.agentcore.springai.AgentCoreSpringAI, SpringAIEvents, and MemoryAdvisor.
var model = AgentCoreSpringAI.model(core.model(...).block());
var callbacks = mcp.listTools().stream().map(AgentCoreSpringAI::tool).toArray(ToolCallback[]::new);
var options = ToolCallingChatOptions.mutate().toolCallbacks(callbacks);
var events = SpringAIEvents.stream(model, new Prompt(prompt, options));Resources are loaded at initialization, and a Prompt is constructed per request at each call. Skill tools are registered in the same way. An existing ChatClient can register a MemoryAdvisor.
For the integration guide, see spring-ai.md. For an example, see SpringAIAgent.java.
AgentScope Java
The entry classes are io.agentcore.agentscope.AgentCoreAgentScope, AgentScopeEvents, and MemoryMiddleware.
var model = AgentCoreAgentScope.model(...);
toolkit.registerAgentTool(AgentCoreAgentScope.tool(tool));Create a separate ReActAgent for each request and release it after the request completes, fails, or is canceled; Flux.using can wrap this pattern. To use memory, register the corresponding MemoryMiddleware.
For the integration guide, see agentscope.md. For an example, see AgentScopeAgent.java.
Reuse native framework providers
If a native model is already available, use the native provider of the framework directly and continue to register the AgentCore tool and memory adapters. For an example, see NativeFrameworkAgents.java.
FAQ
Is AgentCoreServer required?
No. You can call the resource interfaces directly from an existing web service or executor. Use AgentCoreServer to reuse the protocol encapsulation.
Why does the model still not call tools after MCP or Skills are loaded?
Loading only completes the preparation. Register the tools with a framework and select a model that supports tool calling. For a simple question, the model may also decide that no tool call is needed.
Does the same session ID automatically restore history?
No. AgentCoreServer does not persist history, and multi-turn conversations are managed by the application or the framework. Memory does not replace the full conversation history.
Does automatic memory write-back store all history?
No. Write-back is disabled by default. After it is enabled, only the user input of the current turn and the final text answer are stored. The caller handles failures of explicit MemoryStore calls.
Do clients need to be closed manually?
Reuse Core within the application lifecycle, and call close() or use try-with-resources at exit. Do not close a shared Core after a single HTTP request. A reactive call runs only after it is subscribed.
How are logging and cross-origin browser access handled?
The SDK uses SLF4J, and the application configures a logging implementation such as Logback. Do not log keys or sensitive conversation content. Cross-origin access is configured by the application or the gateway with CORS rules for each origin.
References
SDK Overview: the companion document in this series.
Java SDK source code: the SDK implementation and version information.
Java SDK examples guide: descriptions of the complete runnable examples.
Maven Central: artifact versions and dependency coordinates.