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;
}The invoke() method communicates with the backend resolver.
The generated content is displayed using textContent, which treats the response as text instead of interpreting it as HTML.
This is important because model-generated content should not be inserted directly into the page as executable markup.
A complete application should also provide loading indicators, error messages, and a way for users to request another summary.
Using Streaming for Longer AI Responses
Some AI operations take longer than a simple issue summary.
For example, a Confluence assistant might generate a detailed technical explanation or summarize a long project discussion.
Instead of waiting for the entire response, developers can use the stream() method.
import { stream } from "@forge/llm";
export async function generateExplanation(prompt) {
const response = await stream({
model: "claude-sonnet-4-6",
messages: [
{
role: "user",
content: prompt
}
],
max_completion_tokens: 1000
});
let generatedText = "";
try {
for await (const chunk of response) {
const content =
chunk.choices?.[0]?.delta?.content;
if (typeof content === "string") {
generatedText += content;
}
}
return generatedText;
} finally {
await response.close();
}
}This example illustrates incremental response collection. Check the SDK response types for the selected model and package version when implementing the streaming consumer.
Streaming can improve the perceived responsiveness of an application because users do not have to wait for the complete response before seeing generated content.
For long-running operations, consider using Forge asynchronous events and Forge Realtime to manage background execution and deliver updates to the frontend.
Using Function Calling to Build AI-Powered Workflows
The Forge LLMs API also supports tool definitions.
This allows a model to request that an application execute a specific function when additional information or an operation is required.
Consider a Jira assistant that can retrieve an issue's status.
You can define a tool that describes the available operation:
const tools = [
{
type: "function",
function: {
name: "get_issue_status",
description:
"Retrieve the current status of a Jira issue.",
parameters: {
type: "object",
properties: {
issueKey: {
type: "string",
description: "Jira issue key"
}
},
required: ["issueKey"]
}
}
}
];Pass the tool definition to the model:
const response = await chat({
model: "claude-sonnet-4-6",
messages: [
{
role: "user",
content:
"Check the status of issue DEV-101."
}
],
tools,
tool_choice: "auto"
});The model may return a tool call instead of a normal text response.
The application must inspect the returned tool call, validate its arguments, execute the corresponding backend function, and send the result back to the model.
The model should never be allowed to execute arbitrary application code.
For production implementations, use an explicit allowlist of supported functions and validate every argument before execution.
This approach can support workflows such as:
- Retrieving Jira issue information.
- Summarizing project activity.
- Finding related Confluence pages.
- Preparing workflow recommendations.
- Generating structured project reports.
Choosing the Right Model for Your Application
Not every AI feature needs the most powerful available model.
The appropriate choice depends on response quality, processing requirements, and operating cost.
| Model family | Suitable workloads | Consideration |
|---|---|---|
| Claude Haiku | Short summaries and simple classification | Lightweight tasks |
| Claude Sonnet | General-purpose assistants and analysis | Balanced capabilities |
| Claude Opus | Complex reasoning and multi-step tasks | Higher resource consumption |
These are general selection guidelines. Check the current Forge model catalogue for exact model identifiers, availability, and capabilities.
The SDK also provides a list() method that allows an application to inspect supported models and their status.
This is useful when maintaining applications across multiple environments.
Security, Privacy, and Usage Considerations
Using a hosted LLM does not remove the responsibility to protect customer information.
Developers should consider the following areas.
Data access
Only retrieve the Jira or Confluence information required for the user's request.
Do not send entire project datasets when a small amount of relevant context is sufficient.
User permissions
The application should respect the permissions of the user requesting the AI operation.
A model should not gain access to restricted Jira issues simply because the backend application has broader API permissions.
Prompt injection
Issue descriptions and Confluence pages can contain instructions that attempt to manipulate the model.
Treat retrieved content as untrusted input and avoid allowing document text to override the system instructions.
Usage and billing
Forge LLM usage is billed to the developer of the application.
Usage is measured through input and output tokens, which are converted into credits according to the selected model.
The API response includes usage information that can help developers monitor consumption.
There is no free monthly usage allowance for the Forge LLMs API, so estimate costs before releasing an AI feature to a large customer base.
The documented per-installation limits also include 100 requests per minute and 500,000 tokens per minute. Check the current model-specific context limits and other service restrictions before deployment.
Common Mistakes When Integrating Forge LLMs
| Mistake | Why it causes problems | Recommended approach |
|---|---|---|
| Forgetting the LLM manifest module | The SDK cannot be used correctly | Configure the llm module |
| Using an inactive model | Requests can fail | Check available model status |
| Sending unrestricted issue data | Increases privacy risk and token consumption | Retrieve only relevant information |
| Ignoring token usage | Creates unexpected costs | Monitor input and output tokens |
| Trusting tool arguments directly | Can cause unauthorized operations | Validate every tool call |
| Ignoring streaming failures | Produces incomplete responses | Handle partial output and errors |
| Exposing LLM calls in the frontend | Risks exposing application logic | Invoke the model from backend functions |
Best Practices for Production Forge Applications
- Keep model calls in backend functions rather than exposing them directly to the browser.
- Select models according to task complexity and cost requirements.
- Limit the amount of Jira and Confluence data included in prompts.
- Validate user input and retrieved content before sending it to the model.
- Use tool calling only for explicitly permitted application operations.
- Handle rate limits, timeouts, and incomplete responses.
- Track token usage for each important AI operation.
- Provide clear loading and error states in the user interface.
- Review the Marketplace installation and administrator approval requirements before introducing the LLM module.
- Test the application with realistic customer data and different permission levels.
Advantages and Disadvantages of the Forge LLMs API
Advantages
- Uses Atlassian-hosted language models.
- Reduces the need to manage external model infrastructure.
- Avoids separate external AI provider credentials for supported requests.
- Supports chat, streaming, and function calling.
- Provides usage information for cost monitoring.
- Can preserve eligibility for the Runs on Atlassian badge when other requirements are met.
Disadvantages
- Developers have less freedom to choose providers outside the supported model catalogue.
- Usage is billable and has no free monthly allowance.
- Model availability and capabilities can change.
- Applications must handle rate limits and token restrictions.
- Existing installations require administrator approval when the LLM module is introduced.
- Developers remain responsible for application-level security and access control.
Summary
The Atlassian Forge LLMs API provides a practical way to introduce AI capabilities into Jira and Confluence applications without independently managing model infrastructure.
Using the @forge/llm SDK, developers can send chat requests, stream generated responses, inspect token usage, and build workflows that use function calling.
The most important part of a successful implementation is not simply connecting a model. It is controlling which application data enters the prompt, validating generated responses, respecting user permissions, and monitoring usage costs.
For developers building applications within the Atlassian ecosystem, Forge LLMs provides a useful foundation for creating AI-assisted workflows while keeping supported model interactions within Atlassian-managed infrastructure.


Join the conversation! Your thoughts help the community grow.