Artificial intelligence is becoming part of everyday software development, including project management, collaboration, and workflow automation. Applications built on Atlassian Forge can now use large language models without managing a separate model hosting environment or sending application data to an external AI provider.
The Forge LLMs API allows developers to call Atlassian-hosted language models directly from Forge applications. It provides a common interface for generating responses, processing user prompts, streaming output, and building AI-powered workflows.
For developers building Jira and Confluence applications, this removes several integration challenges. There is no need to manage an external model API key or independently deploy model infrastructure for supported Forge LLM requests.
In this article, we will explore how the Forge LLMs API works, how to configure it in a Forge application, and how to build a practical AI-powered Jira feature using the @forge/llm SDK.
What Is the Atlassian Forge LLMs API?
The Forge LLMs API is a platform capability that allows Forge applications to interact with large language models hosted by Atlassian.
Previously, developers commonly integrated AI features by connecting their Forge applications to external providers. This required API credentials, external network permissions, provider-specific SDKs, and additional data-handling considerations.
The hosted LLM API provides an alternative.
A Forge application can send a prompt to a supported model through the Forge runtime and receive the generated response.
The main capabilities include:
- Chat-based interactions with language models.
- Streaming responses for incremental output.
- Multi-turn conversations using message history.
- Function calling through tool definitions.
- Model selection based on application requirements.
- Token usage information for monitoring consumption.
The API currently supports Anthropic Claude model families. Developers can check the available models and their status through the SDK rather than assuming that every model is available permanently.
One important advantage is that requests remain within Atlassian-managed infrastructure. Apps using Forge LLMs can retain eligibility for the Runs on Atlassian badge, provided they meet the other applicable requirements.
Understanding the Forge LLM Architecture
A typical Forge application contains a frontend, backend functions, and Atlassian platform services.
The LLM integration usually happens in a backend function rather than directly in the browser.
Consider an AI assistant that summarizes Jira issues.
The workflow looks like this:
Jira User Interface
|
v
Forge Frontend
|
v
Forge Backend Function
|
v
@forge/llm SDK
|
v
Atlassian Hosted LLM
|
v
Generated Response
|
v
Forge Frontend
|
v
Display SummaryEach component has a specific responsibility.
The frontend collects the user's request and displays the generated response.
The backend retrieves the necessary Jira information and prepares the prompt.
The Forge LLM SDK sends the request to the selected hosted model.
The model generates a response, which the backend validates before returning it to the frontend.
Keeping this integration on the backend also helps prevent unnecessary exposure of application data and business logic.
Prerequisites for Building a Forge LLM Application
Before implementing the integration, prepare the following:
- An Atlassian developer account.
- Access to a Jira or Confluence development site.
- Forge CLI installed on your development machine.
- Node.js compatible with the current Forge development environment.
- Basic knowledge of JavaScript or TypeScript.
- Familiarity with Forge modules and application manifests.
You should also understand how Forge functions communicate with the frontend.
Step 1: Create a Forge Application
If you do not already have a Forge project, create one using the Forge CLI.
forge createChoose an appropriate application template, such as a Jira issue panel.
Move into the generated project directory:
cd jira-ai-assistantInstall the Forge LLM package:
npm install @forge/llmThis package provides the SDK used to communicate with Atlassian-hosted language models.
It includes methods for listing available models, sending chat requests, and streaming responses.
Step 2: Configure the LLM Module
Open the manifest.yml file.
Add the LLM module configuration:
modules:
llm:
- key: jira-ai-llm
model:
- claude
jira:issuePanel:
- key: jira-ai-panel
resource: main
resolver:
function: resolver
title: AI Issue Assistant
function:
- key: resolver
handler: index.handlerThe important configuration is:
llm:
- key: jira-ai-llm
model:
- claudeThe llm module enables access to the supported model family.
At present, the documented module configuration uses the Claude family.
There is an important deployment consideration. Adding the LLM module to an existing Forge application triggers a major version upgrade and requires administrators of existing installations to review and approve the update.
This is particularly important for Marketplace applications because adding an AI capability changes the app's functionality and data-processing behavior.
Step 3: Create a Basic LLM Request
Create or update the backend function file.
For this example, we will build a function that summarizes a Jira issue description.
import { chat } from "@forge/llm";
export async function summarizeIssue(issueDescription) {
const response = await chat({
model: "claude-sonnet-4-6",
messages: [
{
role: "system",
content:
"You are an assistant that summarizes Jira issues. " +
"Use clear and simple language."
},
{
role: "user",
content:
`Summarize the following Jira issue:\n\n${issueDescription}`
}
],
max_completion_tokens: 500
});
const summary =
response.choices?.[0]?.message?.content;
return {
summary,
usage: response.usage
};
}The example uses a model identifier; verify that it is active for your Forge environment before deployment.
Let's understand the important parts.
The chat() method sends a request to the selected model.
The model property identifies which supported model should process the request.
The messages array contains the conversation. The system message establishes the assistant's behavior, while the user message contains the Jira issue information.
The max_completion_tokens property limits the generated response length.
Finally, the function extracts the generated text and returns the token usage information.
In production, validate the issue description before sending it to the model. Also handle cases where the response does not contain usable text.
Step 4: Connect the Function to the Forge Resolver
The backend function needs to be exposed through a Forge resolver so that the frontend can request an issue summary.
For example:
import Resolver from "@forge/resolver";
import { summarizeIssue } from "./llm-service";
const resolver = new Resolver();
resolver.define("summarizeIssue", async ({ payload }) => {
const description = payload.description;
if (
typeof description !== "string" ||
description.trim().length === 0
) {
throw new Error("A valid issue description is required.");
}
return await summarizeIssue(description);
});
export const handler = resolver.getDefinitions();The resolver performs basic input validation before invoking the LLM service.
This separation is useful because it keeps the frontend communication logic independent of the model integration.
For an actual Jira issue panel, retrieve the issue information through the appropriate Forge context or Jira API rather than trusting arbitrary issue data supplied by the browser.
Step 5: Display the AI Response in the Frontend
The frontend can call the resolver and display the generated summary.
A simplified Custom UI example looks like this:
import { invoke } from "@forge/bridge";
async function generateSummary(description) {
const result = await invoke("summarizeIssue", {
description
});
document.getElementById("summary").textContent =
result.summary;
}
Join the conversation! Your thoughts help the community grow.