Review of Google Antigravity for Building Jira Apps
Google recently launched Antigravity, a fork of Visual Studio Code providing an AI agent centric approach to software development. What does this mean? Good question, and one that I wanted to find out which is why I decided to use it to build a Forge app for Jira. Forge is Atlassian’s platform for building apps that integrate with Jira, Confluence, Bitbucket and other Atlassian cloud apps.
In this post, I’ll take you through the steps I followed to build the app. I’ll include enough details so you can replicate the steps, otherwise you can simply read about my experiences.
Setup
If you want to replicate this for yourself, visit Google Antigravity to download and install it. If you are new to Forge you should also follow the setup guide.
Create the App from a Template
I started the project by using the Forge command line interface (CLI) to create an app from a template. In this case, I selected the product-trigger template since a core feature of the app is the ability to listen to Atlassian app events to detect kudos allocations (see the app explanation below).
Step 1: Run forge create.
Step 2: Select a Developer Space or create a new Developer Space.
Step 3: Enter a name for the app, kudos-everywhere.
Step 4: When prompted to select an Atlassian app or platform tool, select Show All.
Step 5: When prompted to select a category, select Triggers and Validators.
Step 6: When prompted to select a template, select product-trigger.
Step 7: Run Google Antigravity.
Step 8: Select File → Open… and select the kudos-everywhere directory.
At this point, I had a basic Forge app that would listen to work item creation events, but obviously it had no functionality relating to the processing of kudos.
Explaining what the app does
AI is most effective when it is provided with strong guidance to avoid it having to fill the gaps with guesswork (aka hallucinate, or more accurately, Confabulation). For this reason, I created a markdown file to articulate the requirements of the app. The initial content of the file, AppRequirements.md, was quite minimal, but the intention was for the requirements to be extended as they are discovered, allowing for an agile approach to the development of the app. Here is its initial content:
# Kudos Everywhere
This app provides a range of functionality allowing users to show appreciation for their colleagues by giving kudos to each other.
In this context, kudos are simply points where each user has a kudos balance.
The typical way to give kudos to someone is to @ mention the person and add a suffix of two or more + signs. Two plus signs will increase the person's kudos balance by two points. Three plus signs will increase the person's kudos balance by three points and so on up to a maximum of 5 points. An example of a kudos allocation is @FredFlinstone+++.
The app stores the kudos balance for each user in Forge storage.
Adding the Forge MCP Server to Antigravity
In order to equip Google Antigravity with expert Forge development knowledge, I configured it with the Forge MCP server as follows:
Step 1: Open the Antigravity IDE and go to the Agent panel menu (three dots icon).
Step 2: Select MCP Servers > Manage MCP Servers.
Step 3: Click View raw config to open the mcp_config.json file in the editor.
Step 4: Add the Forge MCP server configuration to the JSON file as follows:
{
"mcpServers": {
"forge-knowledge": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.atlassian.com/v1/forge/mcp"]
}
}
}
Step 5: Save the file. The new server should now appear in your list of available MCP servers.
Step 6: In the Manage MCPs view, click the Refresh button and verify the forge-knowledge MCP server appears with a list of capabilities such as forge-development-guide.
With the Forge MCP server set up, AI commands can be addressed to it explicitly using the prefix @mcp:forge-knowledge. For example:
@mcp:forge-knowledge: What Forge module do I need to listen to Jira comment events.
However, Antigravity will use the Forge MCP server automatically when commands clearly relate to Forge. Antigravity also maintains a file named AGENTS.md. If you’ve been replicating my journey, you may want to view the file since it should now contain content derived or copied from the Forge MCP server.
Listening to Jira Comment Events
Initially the app listens to events fired when a Jira work item is created because that’s what the template that the app was created from does. However, kudos allocations will be in comments so my first task was to request Antigravity to listen to comment events instead of work item creation events. Before asking Antigravity to make any changes, I updated the AppRequirements.md by adding:
The app must detect kudos allocations in Jira work item comments.
Then I made the following request to Antigravity:
Rewrite the app so that it listens to Jira work item comment events.
Antigravity dutifully responded to the request and came up with an implementation plan, but it made a mistake regarding the event name to listen to. It assumed the event name was avi:jira:commented:created but it should have been avi:jira:commented:issue.
I decided to improve the improve the AppRequirements.md by defining the exact event to subscribe to and then I manually changed the event name in the manifest.yml file. I could have asked Antigravity to do this, but it seems pointless to ask AI to make such a trivial change.
Recognising kudos in Jira events
The next area of functionality I developed was the recognition of kudos allocations in Jira events. As explained in the AppRequirements.md, the app needs to detect kudos allocations such as @Joe+++. Here is the request I gave Antigravity:
Modify the code listening to Jira work item comments so that it reads the comment and identifies kudos allocations.
Antigravity processed this for a while and then displayed its implementation plan which also included storing the kudos in Forge storage. This was a strong indication that Antigravity was reading the AppRequirements.md file even though I didn’t specify tell it to.
I gave Antigravity the go-ahead to implement its plan and it seemed to do a pretty good job. On the surface, the code looked OK and Antigravity also updated the manifest.yml file to add the storage:appscope which was necessary due to the storage API call.
However, after reviewing the code a little more, I noticed a few issues.
Fix: More useful storage keys
Each user’s kudos balance was being stored in Forge storage using the user’s Atlassian account ID as the Forge storage key. It’s good practice to define storage keys with a prefix according to a scheme to facilitating queries so added the following to the AppRequirements.md:
When storing data using the Forge key value storage, keys should be defined with a prefix that uniquely identifies the type of data. For example, a key schem for storing kudo balances for inidividuals might be `kudos-balance-user-${accountId}`. This allows for later enhancements to the app such as storing kudos for teams with the prefix `kudos-balance-team-${teamId}`. The scheme allows for query all kudos balances using the prefix `kudos-balance-` or just kudos balances of a particular type such as `kudos-balance-user-` or specific user's balances such as `kudos-balance-user-${accountId}`.
It would most likely make sense to enhance the Forge MCP server with practices such as this rather than locating them in this specific app’s documentation, but that is a discussion for another day.
I then sent Antigravity the following request:
Update the code to use the scheme for storage keys used to kudos balances.
Fix: Spaces after @ mentions
The Atlassian editor automatically adds a space after inserting @ mentions and users rarely remove the space when giving kudos. Understandably, the code didn’t account for this so I added the following to the AppRequirements.md:
The Atlassian editor automatically adds a space after inserting @ mentions so it is common for there to be a space between an @ mention and the + signs. The app needs to account for this by trimming any leading spaces from the text following an @ mention.
I then sent Antigravity the following request:
Make sure the detection of kudos allocations handles the case where there are one or more spaces between the @ mention and the + signs as defined in the AppRequirements.md.
Antigravity responded by adding a trim operation of the text training @ mentions.
Fix: Nested paragraphs and text
The next bug I spotted related to Antigravity’s naive parsing of comments to find kudos allocations. The comment data contained in the event notification is encoded in the Atlassian Document Format (ADF) and Antigravity was assuming paragraph nodes only occur at the top level when in fact they can occur in nested nodes. To account for this, I updated the AppRequirements.md as follows:
When kudos allocations are being detected in Atlassian Document Formatted (ADF) objects, the allocations need to be detected in text nodes at any nesting depth, not just within paragraphs at the top level of the ADF object. A simple way to achieve this is by detecting if a node has a "content" property which is an array, and of so, inspecting the content array nodes.
After this, I sent Antigravity the following request:
Make sure kudos allocations are detected in nested nodes of comment ADF object as explained in AppRequirements.md.
Antigravity then refactored the code for recursive travel through the ADF object.
Leveraging Antigravity’s Rules and Skills Capabilities
So far I hadn’t really leveraged much of Antigravity capabilities apart from its AI integration. I decided to define a rule and skill, both relating to app deployments.
Deployment rule
I created an app-deployment rule with the following content (.agent/rules/app-deployment.md):
Whenever a change is made to the app manifest file, manifest.yml, the app needs to be redeployed.
Offer to deploy the app whenever changes to the app manifest is detected.
Deployment Skill
I created an app-deployment skill with the following content (.agent/skills/app-deployment/SKILL.md):
---
name: app-deployment
description: Deploys the app to the specified environment.
---
# App Deployment Skill
There are three standard environments the app can be deployed to, "development", "staging" and "production".
To deploy the app, run "forge deploy -e environment-name" where "environment-name" is one of the standard environments.
Check the output of "forge deploy" to see if it indicates the app needs to be upgraded.
If the app needs to be upgraded, run "forge install --upgrade --non-interactive -e environment-name --site some-site.atlassian.net --product some-product" where "some-site" and "some-product" can be determined by running "forge install list" to work out which sites and products that the app is out of date in.
With the rule and skill in place, I decided to continue making changes to the app to see if Antigravity would utilise them.
Refactoring Challenge
Time to throw a different kind of challenge at Antigravity. I decided to define how the source code should be arranged so I added the following to the AppRequirements.md:
The app's source must be stored using the following directory structure:
/src/frontend/: The source for the app's frontend. This may contain subdirectories.
/src/backend/: The source for the app's backend. This may contain subdirectories.
/src/shared/: The source for the app's code that is shared between the frontend and backend. This may contain subdirectories.
/src/index.js: The main entry points to varous parts of the app.
With the source code structure defined, I then asked Antigravity the following:
Refactor the app's code so that it conforms to the directory structure defined in AppRequirements.md
Antigravity did a great job of aligning the source code to the required directory structure. It kept the src/index.js file, but it now just re-exported the event handling routine from src/backend/handler.js which in turn utilised a utility that processes ADF content in src/shared/kudos.js.
Acknowledging Kudos Allocations
Whilst the app processes kudos allocations in comments, it doesn’t provide any feedback. To solve this, I added the following to the AppRequirements.md as follows:
When a kudos allocation is detected in a comment, the app must add a reply comment summarising the balances of each user that received kudos. An example reply comment is as follows:
@FredFlinstone's kudos balance is now 456
@BarneyRubble's kudos balance is now 789
I then asked Antigravity:
Add the functionality to reply to comments that contain kudos allocations as explained in AppRequirements.md.
Once again I was impressed by the changes Antigravity proposed and I accepted. This included adding the write:jira-work permission to the app manifest since that is required to add a comment to a work item. After making the changes, Antigravity redeployed the app due to the app manifest changes and the app-deployment rule specifying the app needed to be redeployed.
Reimplementation from scratch
At this point I had a decent initial version of the app so I decided to delete it 🙂. Actually, I wanted to run an experiment to see if Antigravity could rebuild the app now that I had developed detailed requirements. I cloned the project directory, opened it in Antigravity, deleted all the app code, deleted the source code directory structure, but kept the AppRequirements.md. I then asked Antigravity
Implement this app as defined in AppRequirements.md.
Antigravity responded by creating a detailed implementation plan for me to review which included creating the source code directory structure and the code within it. It also said it would implement a test case for detecting kudos allocations in ADF objects. I gave it the go-ahead and it implemented everything without a hitch. There were quite a few differences in the new implementation, but a quick test indicated it worked as expected. 👍
Antigravity Takeaways
My takeaways from my use of Antigravity so far are as follows:
🙂 I’m still learning some of Google Antigravity’s capabilities, but my first impressions are very positive. I find the idea of being able to tailor the AI’s behavor by defining rules, skills and workflows that are specific to a project or shared across projects, very powerful. I find it reassuring that Antigravity generates artefacts such as implementation plans and task lists to review rather than automatically implementing them. For more details about Antigravity’s capabilities, see the Antigravity docs.
🫤 Sometimes it feels like it would be faster to directly code the app rather than ask Antigravity to code it, although I expect in many cases there are short term and long term considerations to balance. For example, rather than making quick fixes, it may be prudent to improve a requirements document, or fix a skill to ensure Antigravity doesn’t exhibit a similar shortcoming down the track.
🫤 At this stage you can’t expect any AI to create flawless code. All changes need to be reviewed and tested. If you are an experienced developer and familiar with the platforms and development environments you are developing against, then you should be able to pick up a lot of issues in your code reviews. If you have less experience, you will need to rely on thorough testing.
AI Development Takeaway
This exercise forced me to update some of my coding habits to leverage AI. The most impactful change was the maintenance of the AppRequirements.md document to thoroughly detail the requirements of the app. The ability of Antigravity to completely re-generate the app’s source code from this document proves that the IP of an app is not necessarily just the source code. Extending this, it also indicates that the value that humans bring to software development isn’t so much as the coding, but it the decisions behind the coding. In this simple case, I encapsulated these decisions in the AppRequirements.md document. This document wasn’t explicitly required by Antigravity – without it, Antigravity would have happily hallucinated an app which no doubt would have strayed from what I wanted. In order to use AI well, we need to utilise tactics to get the most from it.
In the future, development may look more like technical writing than coding. I can imagine a version of Antigravity or similar tools that maintains the code in response the changes made to the specification rather than being explicitly told what code changes to make.