Skip to content

Jira Integration

Automatically create and track Jira issues for AI governance alerts. TruthVouch can sync hallucinations, policy violations, and verification failures as actionable Jira tickets with automatic status updates.

Setup

1. Generate Jira API Token

In Jira Cloud:

  1. Go to account.atlassian.com → Security
  2. Create API token
  3. Copy token (store securely)

For Jira Server/Data Center:

  • Use username and password or personal access token

2. Configure TruthVouch

Terminal window
truthvouch config jira \
--cloud-url https://your-domain.atlassian.net \
--email your-email@company.com \
--api-token your-api-token \
--project-key OPS

Or with Jira Server:

Terminal window
truthvouch config jira \
--server-url https://jira.company.com \
--username admin \
--password your-password \
--project-key OPS

3. Verify Connection

Terminal window
truthvouch config jira --test
# Output: ✓ Connected successfully to Jira

Auto-Create Issues

Basic Alert to Ticket

from truthvouch.integrations.jira import JiraIssueHandler
handler = JiraIssueHandler(
cloud_url="https://your-domain.atlassian.net",
email="your-email@company.com",
api_token="your-api-token"
)
# Create issue from alert
issue = handler.create_issue_from_alert(
alert={
"title": "Hallucination Detected",
"description": "Query: 'Is the Earth flat?'",
"severity": "critical",
"confidence": 0.05
},
project_key="OPS",
issue_type="Bug"
)
print(f"Created: {issue.key}") # Output: OPS-1234

Custom Issue Mapping

# Map alert fields to Jira fields
issue = handler.create_issue(
project_key="OPS",
issue_type="Task",
fields={
"summary": "Verify: Earth is flat claim",
"description": "Hallucination detected with 5% confidence",
"priority": "High",
"labels": ["hallucination", "science"],
"assignee": {"emailAddress": "ops@company.com"},
"components": [{"name": "AI-Firewall"}],
"customfield_10000": "critical" # Custom field
}
)

Bi-Directional Sync

Sync Alert to Ticket

from truthvouch.integrations.jira import JiraSyncHandler
sync = JiraSyncHandler(
cloud_url="https://your-domain.atlassian.net",
email="your-email@company.com",
api_token="your-api-token"
)
# When TruthVouch detects alert
alert = {
"id": "alert_123",
"title": "High Hallucination Rate",
"severity": "high",
"count": 5,
"in_last_hour": True
}
# Create or update ticket
ticket = sync.sync_alert(
alert=alert,
project_key="OPS",
issue_type="Incident"
)

Sync Ticket Update to TruthVouch

@app.route("/jira/webhook", methods=["POST"])
def handle_jira_event():
"""Handle Jira webhook events."""
event = request.get_json()
# When ticket status changes
if event["webhookEvent"] == "jira:issue_updated":
issue = event["issue"]
# Update TruthVouch alert status
if issue["fields"]["status"]["name"] == "Done":
tv_client.alerts.acknowledge(
alert_id=issue["key"],
status="resolved"
)
elif issue["fields"]["status"]["name"] == "In Progress":
tv_client.alerts.acknowledge(
alert_id=issue["key"],
status="in_progress"
)
return {"status": "ok"}, 200

Automated Rules

Create Issues for Specific Alerts

# Create a Jira issue for every critical hallucination
handler.configure_rule(
name="Critical Hallucinations → Jira",
trigger="confidence < 0.5",
action={
"type": "create_jira_issue",
"project_key": "OPS",
"issue_type": "Bug",
"priority": "Highest",
"assignee": "on-call-rotation",
"template": "hallucination_bug"
}
)
# Create Jira for policy violations with auto-assign
handler.configure_rule(
name="Policy Violation → Jira",
trigger="policy_violation = true",
action={
"type": "create_jira_issue",
"project_key": "COMPLIANCE",
"issue_type": "Task",
"priority": "High",
"assignee": "compliance-team",
"due_date": "+2d" # Due in 2 days
}
)

Issue Templates

Define reusable templates:

from truthvouch.integrations.jira import JiraTemplate
# Define template
template = JiraTemplate(
name="Hallucination Bug",
project_key="OPS",
issue_type="Bug",
fields={
"summary": "Hallucination: {{alert.title}}",
"description": """
h2. Issue
{{alert.description}}
h2. Details
* Confidence: {{alert.confidence}}%
* Query: {{alert.query}}
* Response: {{alert.response}}
* Category: {{alert.category}}
h2. Action Items
* Review output
* Verify against knowledge base
* Update system prompts if needed
* Monitor for similar issues
[View in TruthVouch|{{alert.dashboard_url}}]
""",
"priority": "High",
"labels": ["hallucination", "ai-safety"],
"components": [{"name": "AI-Engine"}]
}
)
# Use template to create issues
issue = handler.create_issue_from_template(
template="hallucination_bug",
context=alert_data
)

Querying and Reporting

# Find all open hallucination issues
issues = handler.search(
jql='project = OPS AND type = Bug AND labels = hallucination AND status != Done'
)
print(f"Open hallucination issues: {len(issues)}")
for issue in issues:
print(f"- {issue.key}: {issue.fields.summary}")
print(f" Created: {issue.fields.created}")
print(f" Assignee: {issue.fields.assignee.displayName}")

Report Generation

# Generate report on verification issues
def generate_jira_verification_report(days: int = 7):
issues = handler.search(
jql=f'project = OPS AND created >= -{days}d AND labels = verification'
)
report = {
"period": f"Last {days} days",
"total_issues": len(issues),
"by_status": {},
"by_priority": {},
"by_assignee": {}
}
for issue in issues:
status = issue.fields.status.name
priority = issue.fields.priority.name if issue.fields.priority else "Unknown"
assignee = issue.fields.assignee.displayName if issue.fields.assignee else "Unassigned"
report["by_status"][status] = report["by_status"].get(status, 0) + 1
report["by_priority"][priority] = report["by_priority"].get(priority, 0) + 1
report["by_assignee"][assignee] = report["by_assignee"].get(assignee, 0) + 1
return report

Field Mapping

Common Field Patterns

field_mapping = {
# TruthVouch Alert → Jira Issue
"alert.severity": "priority",
"alert.title": "summary",
"alert.description": "description",
"alert.category": "labels",
"alert.affected_system": "components",
"alert.created": "created",
"on_call_user": "assignee"
}
# Custom mapping for healthcare
healthcare_mapping = {
**field_mapping,
"alert.patient_impact": "customfield_10001",
"alert.regulatory_requirement": "customfield_10002"
}

Automation and Escalation

Jira Automation Rule

In Jira Automation:

Rule: "Escalate to On-Call"
When: Issue created AND project = OPS AND priority >= High
Then:
- Assign to: On-call rotation
- Set due date: Now + 2 hours
- Add label: urgent
- Send notification: #on-call Slack channel

Escalation Handler

@app.route("/escalate", methods=["POST"])
def escalate_issue():
"""Escalate Jira issue to on-call."""
issue_key = request.get_json()["issue_key"]
issue = handler.get_issue(issue_key)
# Update priority
handler.update_issue(issue_key, {
"priority": {"name": "Highest"},
"labels": ["escalated", "urgent"]
})
# Notify on-call via Slack
slack_client.chat_postMessage(
channel="#on-call",
text=f"Escalated: <https://jira.company.com/browse/{issue_key}|{issue.fields.summary}>"
)
return {"status": "escalated"}, 200

Integration with Webhooks

Bidirectional Flow

TruthVouch Alert
Webhook to Jira Integration
Create/Update Jira Issue
Jira Automation Rules Trigger
Notify Team
Issue Resolution
Webhook back to TruthVouch
Update Alert Status

Webhook Handler

from truthvouch.webhooks import WebhookHandler
handler = WebhookHandler(api_key="your-api-key")
@app.route("/truthvouch/webhook", methods=["POST"])
def receive_alert():
"""Receive alert from TruthVouch."""
if not handler.verify_signature(request):
return {"error": "Invalid signature"}, 401
alert = request.get_json()
# Create Jira issue
jira_issue = jira_handler.create_issue_from_alert(
alert=alert,
project_key="OPS"
)
# Acknowledge alert
handler.acknowledge_alert(
alert_id=alert["id"],
action="jira_issue_created",
reference=jira_issue.key
)
return {"jira_key": jira_issue.key}, 200

Best Practices

Issue Quality

  • Include context from TruthVouch (confidence, citations)
  • Add deep links to dashboard for review
  • Use templates for consistency
  • Assign to appropriate team members

Ticket Management

  • Don’t create duplicate issues for same alert
  • Batch related alerts into single epic
  • Link related issues with “blocks” relationship
  • Archive resolved issues after 30 days

Automation

  • Use automation rules to reduce manual steps
  • Set appropriate SLAs per severity
  • Auto-escalate if not updated in 24h
  • Close resolved issues automatically

Troubleshooting

Q: Issues not creating

  • Verify API token is valid
  • Check project key exists
  • Ensure issue type is available in project
  • Check custom fields exist

Q: Field mapping issues

  • Validate custom field IDs
  • Check field is visible in screen
  • Verify field is in issue type
  • Test manually in Jira first

Q: Webhook sync failing

  • Verify webhook URL is correct
  • Check TruthVouch can reach Jira
  • Implement idempotency (same request twice = same result)
  • Add request logging

Next Steps