Create Jira Tickets from AI Escalations
Connecting Keeptrusts escalations to Jira creates a traceable workflow from policy violation to resolution. This guide covers webhook-to-Jira automation, ticket templates, priority mapping, SLA tracking, and reporting dashboards.
Use this page when
- You want to auto-create Jira tickets from Keeptrusts AI governance escalations.
- You need priority mapping from escalation severity to Jira priority levels.
- You are building a webhook-to-Jira middleware (Lambda, Worker) with custom field population.
- You want bi-directional sync so resolving a Jira ticket also resolves the Keeptrusts escalation.
Primary audience
- Primary: Technical Engineers
- Secondary: AI Agents, Technical Leaders
Architecture overview
Keeptrusts Gateway
→ policy violation → escalation created
→ /v1/webhooks → middleware (Lambda, Worker)
→ Jira REST API → create issue
→ AI Governance project
→ priority mapped from severity
→ custom fields populated
→ SLA timer started
Prerequisites
- Jira Cloud or Data Center instance
- Jira project for AI governance issues (e.g., "AIGOV")
- Jira API token or OAuth 2.0 credentials
- Keeptrusts organization with webhook permissions
Jira project setup
Create an AI governance project
- In Jira, create a new project using the Kanban or Scrum template
- Project key:
AIGOV - Add custom fields:
- Escalation ID (text) — Keeptrusts escalation identifier
- Policy Name (text) — triggering policy
- Model (text) — target LLM model
- Gateway ID (text) — originating gateway
- Console URL (URL) — link to Keeptrusts Console
Issue types
| Type | Usage |
|---|---|
| Bug | False positive — policy incorrectly blocked a legitimate request |
| Task | Genuine violation — requires human review and resolution |
| Story | Policy improvement — update policy based on escalation pattern |
Webhook-to-Jira middleware
AWS Lambda implementation
import { SSMClient, GetParameterCommand } from '@aws-sdk/client-ssm';
const ssm = new SSMClient({});
export async function handler(event) {
const body = JSON.parse(event.body);
const jiraToken = await getSecret('/keeptrusts/jira-api-token');
const jiraUrl = process.env.JIRA_URL;
const projectKey = process.env.JIRA_PROJECT_KEY || 'AIGOV';
const priority = mapPriority(body);
const issuePayload = {
fields: {
project: { key: projectKey },
summary: `AI Escalation: ${body.policy_name} — ${body.action} (${body.model})`,
description: buildDescription(body),
issuetype: { name: body.action === 'block' ? 'Bug' : 'Task' },
priority: { name: priority },
labels: ['ai-governance', 'keeptrusts', body.policy_name],
customfield_10100: body.escalation_id,
customfield_10101: body.policy_name,
customfield_10102: body.model,
customfield_10103: body.gateway_id,
},
};
const response = await fetch(`${jiraUrl}/rest/api/3/issue`, {
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(`${process.env.JIRA_EMAIL}:${jiraToken}`).toString('base64')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(issuePayload),
});
const result = await response.json();
return {
statusCode: response.ok ? 201 : 500,
body: JSON.stringify({ issue_key: result.key }),
};
}
function buildDescription(event) {
return `h2. AI Governance Escalation
||Field||Value||
|Policy|${event.policy_name}|
|Action|${event.action}|
|Model|${event.model}|
|Gateway|${event.gateway_id}|
|User|${event.user_id}|
|Time|${event.timestamp}|
|Escalation ID|${event.escalation_id}|
[View in Keeptrusts Console|https://console.keeptrusts.com/escalations/${event.escalation_id}]
h3. Investigation Steps
# Open the console link above
# Review the event context and conversation history
# Determine if the violation is genuine or a false positive
# Update this ticket with findings
# Resolve the escalation in Keeptrusts`;
}
function mapPriority(event) {
if (event.action === 'block') return 'Highest';
if (event.action === 'escalate') return 'High';
if (event.action === 'redact') return 'Medium';
return 'Low';
}
async function getSecret(name) {
const cmd = new GetParameterCommand({ Name: name, WithDecryption: true });
const result = await ssm.send(cmd);
return result.Parameter.Value;
}
Configure Keeptrusts webhook
curl -X POST https://api.keeptrusts.com/v1/webhooks \
-H "Authorization: Bearer $KEEPTRUSTS_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://abc123.execute-api.us-east-1.amazonaws.com/prod/jira-bridge",
"description": "Create Jira tickets from escalations",
"event_types": ["escalation.created"],
"active": true
}'
Priority mapping
| Keeptrusts Action | Policy Category | Jira Priority | SLA |
|---|---|---|---|
block | Content safety | Highest | 1 hour |
block | Compliance | Highest | 2 hours |
escalate | Review required | High | 4 hours |
redact | Data protection | Medium | 24 hours |
log | Audit trail | Low | 1 week |
SLA tracking
Jira SLA configuration
- Go to Project Settings → SLA
- Create SLAs:
- Time to First Response: Highest = 15 min, High = 1 hour, Medium = 4 hours
- Time to Resolution: Highest = 1 hour, High = 4 hours, Medium = 24 hours
Automation rules
Create Jira automation rules for SLA management:
Trigger: Issue created with label "ai-governance"
Condition: Priority is "Highest"
Action:
- Add watcher: @ai-governance-lead
- Send Slack notification to #ai-critical
- Start SLA timer
Resolution workflow
Status transitions
Open → In Progress → Under Review → Resolved → Closed
↘ False Positive → Closed
Resolution automation
When a Jira ticket is resolved, update the Keeptrusts escalation:
// Jira webhook → Keeptrusts API
if (event.webhookEvent === 'jira:issue_updated' && event.issue.fields.status.name === 'Resolved') {
const escalationId = event.issue.fields.customfield_10100;
await fetch(`https://api.keeptrusts.com/v1/escalations/${escalationId}/resolve`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.KEEPTRUSTS_API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
resolution: event.issue.fields.resolution.name,
notes: `Resolved via Jira ${event.issue.key}`,
}),
});
}
Reporting dashboard
Jira JQL queries
-- All open AI governance tickets
project = AIGOV AND status != Closed ORDER BY priority DESC
-- Escalations by policy (last 30 days)
project = AIGOV AND created >= -30d ORDER BY created DESC
-- SLA breaches
project = AIGOV AND "Time to Resolution" = breached()
-- False positives (for policy tuning)
project = AIGOV AND resolution = "False Positive" AND created >= -30d
Dashboard gadgets
| Gadget | Configuration |
|---|---|
| Pie chart | Group by priority — shows severity distribution |
| Created vs. Resolved | Two-dimensional filter — tracks escalation velocity |
| SLA Success Rate | Filter by SLA name — shows compliance percentage |
| Recently Created | JQL filter — latest escalations at a glance |
Troubleshooting
| Issue | Cause | Fix |
|---|---|---|
| Tickets not created | Jira API token expired | Rotate the token and update Lambda secrets |
| Wrong priority assigned | Mapping logic error | Check mapPriority() function in middleware |
| Custom fields not populated | Field IDs incorrect | Look up field IDs with GET /rest/api/3/field |
| Duplicate tickets | Deduplication not implemented | Add escalation_id uniqueness check before creation |
For AI systems
- Canonical terms: Keeptrusts escalation,
/v1/webhooks,escalation.createdevent,/v1/escalations/{id}/resolve, Jira REST API, webhook middleware, priority mapping. - Key config: Jira project key
AIGOV, custom fields (Escalation ID, Policy Name, Model, Gateway ID), webhookevent_types: ["escalation.created"]. - Integration pattern: Keeptrusts webhook → Lambda/Worker middleware → Jira REST API
POST /rest/api/3/issue. - Best next pages: ServiceNow compliance, PagerDuty incident response, Slack & Teams alerting.
For engineers
- Prerequisites: Jira Cloud/Data Center with REST API access, Jira API token or OAuth 2.0 credentials, Keeptrusts organization with webhook permissions.
- Validate: Create a test escalation, verify Jira ticket appears with correct priority and custom fields, confirm bi-directional resolution sync.
- Custom fields: Look up field IDs with
GET /rest/api/3/field— IDs likecustomfield_10100vary per Jira instance. - Deduplication: Use
escalation_idas a unique key to prevent duplicate tickets on webhook retries.
For leaders
- Traceability: Every AI policy violation becomes a tracked work item with SLA timers, creating an auditable resolution history.
- False positive feedback loop: Tickets resolved as "False Positive" inform policy tuning — track them with JQL for continuous improvement.
- SLA compliance: Map escalation severity to response/resolution SLAs; track breach rates in Jira dashboards.
- Ownership clarity: AIGOV project assigns violations to the right team based on policy name and gateway source.
Next steps
- Integrate with ServiceNow for compliance workflows
- Automate incidents with PagerDuty for on-call routing
- Set up Slack & Teams alerts for real-time notifications