AWS Builder Center

Automating Incident Response: Jira ↔ AWS DevOps Agent Bidirectional Integration

AWS Devops Agent Integration with Jira

The Problem

When an incident ticket is created in Jira, engineers manually investigate — correlating CloudWatch metrics, deployment history, and logs. This takes 2–4 hours per incident. Meanwhile, the Jira ticket sits waiting for someone to add findings.
AWS DevOps Agent can investigate autonomously in under 2 minutes, however the service does not have native integration for Jira. This blog talks about connecting devops agent bidirectionally to Jira using webhooks — so that a Jira issue triggers an investigation AND the findings automatically appear as a Jira comment — requires a few extra pieces.

Architecture

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ Jira Issue Created │
│ │ │
│ │ Jira Webhook (native) │
│ ▼ │
│ API Gateway ──► Bridge Lambda │
│ │ │
│ │ HMAC-signed payload │
│ ▼ │
│ AWS DevOps Agent Webhook │
│ │ │
│ ▼ │
│ Investigation Runs (~2 min) │
│ │ │
│ ▼ │
│ EventBridge │
│ "Investigation Completed" │
│ │ │
│ ▼ │
│ Writer Lambda │
│ │ GetBacklogTask → extract Jira key │
│ │ ListJournalRecords → fetch summary │
│ ▼ │
│ Jira REST API → POST /issue/{key}/comment │
│ │ │
│ ▼ │
│ Jira Ticket Updated with Investigation Findings ✅ │
│ │
└─────────────────────────────────────────────────────────────────────┘

Why a Bridge Lambda is Required

Jira's native webhook cannot directly trigger AWS DevOps Agent. Here's why:
Jira sendsDevOps Agent expects
Signature headerX-Hub-Signature: sha256=<hex>x-amzn-event-signature: <base64>
TimestampNot includedx-amzn-event-timestamp: <ISO8601>
Signature inputHMAC(secret, body)HMAC(secret, timestamp + ":" + body)
Payload schemaJira native format{eventType, incidentId, priority, title...}
The Bridge Lambda handles:
  1. Receiving Jira's native payload
  2. Transforming it to DevOps Agent's expected schema
  3. Computing the correct HMAC signature (timestamp:body → base64)
  4. Adding [Jira MDP-X] prefix to the title — this is the key that enables write-back

How Write-back Works (The Clever Part)

The EventBridge event from DevOps Agent only contains a task_id — no Jira issue key. To post back to the correct ticket, we use the title we set:
1
2
3
Bridge Lambda sets title: "[Jira MDP-16-1780950336] Payment service errors"
↑
Jira key embedded
When investigation completes, the Writer Lambda:
  1. Calls devops-agent:GetBacklogTask(task_id) → gets the title and referenceId
  2. Parses MDP-16 from referenceId: "MDP-16-1780950336"
  3. Calls devops-agent:ListBacklogTasks → finds all other tickets linked to this investigation (e.g. MDP-17, MDP-19)
  4. Calls devops-agent:ListJournalRecords(executionId) → gets the full investigation summary
  5. Posts the right comment to each ticket — different message for original vs linked tickets
No DynamoDB, no state management — the Jira key is embedded in the investigation itself, and ListBacklogTasks provides the fan-out to linked tickets.

What Gets Posted to Jira

Original ticket (investigation ran fresh)

1
2
3
4
5
6
7
8
AWS DevOps Agent — Investigation Completed

Status: COMPLETED | Task ID: dd57da79-...

Findings:
[Full RCA summary from DevOps Agent]

View full investigation in the AWS DevOps Agent console.

Linked ticket (similar incident seen before)

1
2
3
4
5
6
7
8
9
10
AWS DevOps Agent — Investigation Linked

This incident is similar to a previously investigated issue.
Linked to original investigation from: MDP-16
Task ID: dd57da79-...

Investigation findings from the original incident:
[Summary from the original investigation]

View full investigation in the AWS DevOps Agent console.
The linked message tells engineers exactly which ticket the original investigation came from, so they can reference it directly without hunting through the DevOps Agent console.

What Triggers a Comment for Every Outcome

The EventBridge rule catches all investigation lifecycle events — no ticket is ever left without a response:
EventWho gets the commentWhat the comment says
Investigation CompletedOriginal ticket onlyFull findings + RCA summary
Investigation LinkedBoth original AND newly linked ticketOriginal: findings. Linked: "linked to MDP-X" + findings
Investigation FailedOriginal ticket"Could not complete — investigate manually"
Investigation Timed OutOriginal ticket"Timed out"
Investigation CancelledOriginal ticket"Cancelled"
Investigation SkippedOriginal ticket"Skipped based on skill criteria"

Prerequisites

  • AWS account with DevOps Agent enabled and an Agent Space configured
  • Atlassian Jira Cloud account
  • AWS CLI configured (aws sts get-caller-identity works)
  • SAM CLI installed — pip install aws-sam-cli

Setup — Two Options

📁 All required files available here: Amazon WorkDocs — jira-devops-bridge 
Download the complete jira-devops-bridge folder which contains template.yaml, bridge_lambda/, writer_lambda/, and the Kiro steering file. Follow either option below.

Option A: Use Kiro (Recommended — automated end-to-end)

Kiro can build and deploy the entire integration for you with zero manual file creation.
Step 1 — Add the steering file
Download the steering file from this repo:
1
.kiro/steering/jira-devops-agent-integration.md
Copy it into your workspace at .kiro/steering/jira-devops-agent-integration.md.
Step 2 — Tell Kiro to install it
Open Kiro and say:
1
Install the Jira DevOps Agent integration
Kiro will:
  1. Ask you for the 6 required credentials (webhook URL, webhook secret, Jira URL, Jira email, Jira API token, Agent Space ID)
  2. Create all project files (template.yaml, bridge_lambda/index.py, writer_lambda/index.py)
  3. Run sam build and sam deploy automatically
  4. Output the Jira webhook URL to configure
Step 3 — Configure Jira webhook
Kiro will tell you the API Gateway URL. Paste it into Jira:
  1. Go to https://<your-org>.atlassian.net/plugins/servlet/webhooks
  2. Click Create a WebHook
  3. Set URL to the output from Kiro, Events to Issue → created
  4. Save

Option B: Manual Setup

If you prefer to deploy manually without Kiro.
Step 1 — Get required credentials
CredentialWhere to find it
DevOps Agent Webhook URLAgent Space → Capabilities → Webhook → Generate webhook
DevOps Agent Webhook SecretShown once when generating the webhook
Jira base URLhttps://<your-org>.atlassian.net
Jira emailYour Atlassian account email
Jira API tokenhttps://id.atlassian.com/manage-profile/security/api-tokens
Agent Space IDUUID from DevOps Agent console URL or EventBridge events
Step 2 — Download the folder and build
Download the complete jira-devops-bridge folder from Amazon WorkDocs . It contains all files ready to deploy:
1
2
3
4
5
6
7
8
jira-devops-bridge/
├── template.yaml ← SAM stack definition
├── bridge_lambda/
│ └── index.py ← Bridge Lambda code
├── writer_lambda/
│ └── index.py ← Writer Lambda code
└── .kiro/steering/
└── jira-devops-agent-integration.md ← Kiro steering file
Then build:
1
2
cd jira-devops-bridge
sam build
Step 3 — Deploy
The SAM stack creates all AWS resources automatically:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
sam deploy \
--template-file template.yaml \
--stack-name jira-devops-bridge \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides \
"DevOpsAgentWebhookUrl=<your-webhook-url>" \
"DevOpsAgentWebhookSecret=<your-webhook-secret>" \
"JiraBaseUrl=<https://yourorg.atlassian.net>" \
"JiraEmail=<your-jira-email>" \
"JiraApiToken=<your-jira-api-token>" \
"AgentSpaceId=<your-agent-space-id>" \
--resolve-s3 \
--region us-east-1 \
--no-confirm-changeset
--resolve-s3 automatically creates an S3 bucket for SAM artifacts — no manual S3 setup needed.
Stack output:
1
JiraWebhookUrl: https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com/prod/jira
Step 4 — Configure Jira webhook
  1. Go to https://<your-org>.atlassian.net/plugins/servlet/webhooks
  2. Click Create a WebHook
  3. Fill in:
    • Name: devops-agent-bridge
    • URL: paste the JiraWebhookUrl from the stack output
    • Events: check Issue → created
  4. Click Save
Step 5 — Test end-to-end
Create a Jira issue with a unique title and check:
  1. DevOps Agent console — investigation should start within 30 seconds
  2. Wait ~2 minutes for investigation to complete
  3. Jira issue — a comment with investigation findings should appear automatically

What Gets Deployed (Both Options)

ResourceWhat it does
API Gateway (HTTP API)Public HTTPS endpoint (/jira) that Jira calls when an issue is created. Routes requests to the Bridge Lambda.
Bridge Lambda (jira-devops-bridge-v2)Receives Jira's native payload → transforms it to DevOps Agent schema → computes HMAC signature → triggers investigation
Writer Lambda (jira-devops-writer-v2)Triggered by EventBridge → calls DevOps Agent API to get investigation findings → posts comment to Jira
EventBridge RuleWatches default event bus for aws.aidevops events. Triggers Writer Lambda on Completed, Linked, Failed, Timed Out, Cancelled, Skipped
Secrets ManagerStores DevOps Agent webhook secret + Jira API token. Lambdas read at runtime — credentials never in code
IAM RolesLeast-privilege roles for each Lambda: Bridge needs Secrets Manager read; Writer needs Secrets Manager + DevOps Agent API read

Key Implementation Details

Bridge Lambda — HMAC Signing

1
2
3
4
5
6
# DevOps Agent requires: HMAC(secret_as_raw_string, "timestamp:body") → base64
webhook_secret = secrets["webhook_secret"] # use as-is, NOT base64-decoded
sig_input = f"{timestamp}:{payload_str}"
signature = base64.b64encode(
hmac.new(webhook_secret.encode("utf-8"), sig_input.encode("utf-8"), hashlib.sha256).digest()
).decode()
Common mistake: base64-decoding the secret before signing. DevOps Agent uses the raw secret string.

Unique incidentId per trigger

1
2
epoch = int(time.time())
incident_id = f"{issue_key}-{epoch}" # e.g. "MDP-16-1780950336"
DevOps Agent deduplicates on content similarity. Using a unique incidentId with epoch ensures each trigger creates a fresh investigation.

Writer Lambda — Extracting Jira keys (including linked tickets)

The tricky part: The EventBridge event fires for the primary (original) investigation's task_id, not the newly linked task. So GetBacklogTask(task_id) returns the original ticket's key — missing all newly linked Jira tickets.
The solution: use ListBacklogTasks to find all tasks where primaryTaskId == task_id, then post to all of them:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def get_all_jira_keys(client, agent_space_id, task_id):
"""Returns Jira keys for the primary task + all linked tasks."""
jira_keys = set()

# 1. Primary task's Jira key
resp = client.get_backlog_task(agentSpaceId=agent_space_id, taskId=task_id)
ref_id = resp["task"]["reference"]["referenceId"] # e.g. "MDP-16-1234567"
m = re.match(r"^([A-Z]+-\d+)", ref_id)
if m:
jira_keys.add(m.group(1)) # "MDP-16"

# 2. All tasks linked to this one (primaryTaskId == task_id)
all_tasks = client.list_backlog_tasks(agentSpaceId=agent_space_id, limit=50)
for t in all_tasks["tasks"]:
if t.get("primaryTaskId") == task_id:
ref_id = t["reference"]["referenceId"] # e.g. "MDP-17-1234567"
m = re.match(r"^([A-Z]+-\d+)", ref_id)
if m:
jira_keys.add(m.group(1)) # "MDP-17"

return jira_keys # {"MDP-16", "MDP-17", "MDP-19", ...}
This ensures that when an investigation completes — whether brand new or linked — every associated Jira ticket gets a comment, including the ticket that just triggered it.

Cost Estimate

ResourceCost
API Gateway~$0 (free tier: 1M requests/month)
Lambda (bridge + writer)~$0 (free tier: 1M invocations/month)
EventBridge~$0 (free for default bus rules)
Secrets Manager~$0.40/month per secret
Total< $1/month

Limitations and Workarounds

DevOps Agent deduplication
DevOps Agent links new investigations to previous ones if content is similar. This is by design. The integration handles this correctly — when a ticket is linked, the Writer Lambda uses ListBacklogTasks to find all tickets associated with the primary investigation and posts a "linked" comment to every one of them, including the newly created ticket.
Generic webhook only supports HMAC
The DevOps Agent generic webhook requires HMAC authentication. Jira's native webhook format is incompatible (wrong header name, wrong encoding, missing timestamp), requiring the bridge Lambda.
EventBridge event has no Jira key
The aws.aidevops EventBridge event only contains task_id. We solve this by:
  1. Embedding the Jira key in the investigation's referenceId and title at trigger time
  2. On completion, calling GetBacklogTask + ListBacklogTasks to recover all associated Jira keys

Next Steps

  • Add Slack notification alongside Jira comment
  • Filter webhooks by Jira project or priority (JQL filter in Jira webhook config)
  • Extend to other ticketing systems using similar pattern or that does not support native integration

Resources

Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article