Jira Integration Reference
Complete reference for Jira platform integration with AOF.
Platform Support Statusโ
| Platform | Status | Notes |
|---|---|---|
| Jira Cloud | โ Stable | Fully tested with Atlassian Cloud |
| Jira Server | ๐งช Experimental | Compatible API, needs validation |
| Jira Data Center | ๐งช Experimental | Compatible API, needs validation |
Important:
- This documentation focuses on Jira Cloud, which is the primary tested platform
- Jira Server and Data Center use compatible REST APIs but may have version-specific differences
- Self-hosted deployments require additional network configuration (webhooks must reach AOF daemon)
Overviewโ
AOF provides deep Jira integration through webhook-based triggers and the Jira REST API, enabling agents to automate issue triage, sprint management, work logging, and cross-platform workflows with GitHub.
Key Capabilities:
- Automatic issue triage and categorization
- AI-powered bug analysis and estimation
- Sprint planning and backlog refinement
- Work logging and time tracking automation
- Multi-project coordination
- GitHub/Jira cross-reference sync
- Custom workflow automation
Architectureโ
Jira integration consists of three components:
- Jira Trigger - Receives webhook events from Jira
- Jira Platform Adapter - Parses events and manages API calls
- Agents/Flows - Process events and take actions
Jira Webhook โ AOF Daemon โ Trigger โ Agent/Flow โ Jira API
Configuration Referenceโ
Daemon Configurationโ
The DaemonConfig enables Jira as a platform and configures authentication. Event filtering and command routing are defined in Triggers, not here.
Configure Jira platform in daemon.yaml:
apiVersion: aof.dev/v1
kind: DaemonConfig
metadata:
name: aof-daemon
spec:
server:
port: 3000
host: "0.0.0.0"
cors: true
timeout_secs: 60
# Enable platforms
platforms:
jira:
enabled: true
base_url: https://yourcompany.atlassian.net # Jira Cloud URL
auth:
type: api_token # api_token, oauth2, or pat
email_env: JIRA_EMAIL # For API token auth
token_env: JIRA_API_TOKEN
webhook_secret_env: JIRA_WEBHOOK_SECRET
bot_name: aofbot # Optional: for @mentions
# Resource discovery
triggers:
directory: ./triggers/
watch: true
agents:
directory: ./agents/
fleets:
directory: ./fleets/
flows:
directory: ./flows/
enabled: true
runtime:
max_concurrent_tasks: 10
task_timeout_secs: 300
Platform Configuration Fieldsโ
| Field | Type | Required | Description |
|---|---|---|---|
enabled | bool | Yes | Enable Jira webhook endpoint (/webhook/jira) |
base_url | string | Yes | Jira instance URL (Cloud or self-hosted) |
auth.type | string | Yes | Authentication type: api_token, oauth2, or pat |
auth.email_env | string | Conditional | Required for api_token auth |
auth.token_env | string | Yes | Environment variable name for token/PAT |
webhook_secret_env | string | Yes | Environment variable name for webhook secret |
bot_name | string | No | Bot name for @mentions (default: "aofbot") |
Authentication Typesโ
API Token (Recommended for Cloud):
auth:
type: api_token
email_env: JIRA_EMAIL
token_env: JIRA_API_TOKEN
Personal Access Token (Server/Data Center):
auth:
type: pat
token_env: JIRA_PAT
OAuth 2.0 (Advanced):
auth:
type: oauth2
token_env: JIRA_OAUTH_TOKEN
# Additional OAuth config...
Self-Hosted Jira Configurationโ
For Jira Server or Data Center deployments:
platforms:
jira:
enabled: true
base_url: https://jira.yourcompany.com # Self-hosted URL
auth:
type: pat
token_env: JIRA_PAT
webhook_secret_env: JIRA_WEBHOOK_SECRET
# Optional: Proxy configuration
proxy:
http_proxy: http://proxy.company.com:8080
https_proxy: https://proxy.company.com:8080
no_proxy: localhost,127.0.0.1
# Optional: TLS configuration
tls:
verify: true
ca_cert_path: /etc/ssl/certs/company-ca.pem
Note: Event filtering, project filtering, and command routing are configured in Trigger files, not in DaemonConfig. This separation keeps daemon config minimal and allows per-trigger customization.
Trigger Configurationโ
Create trigger in triggers/jira-bug-triage.yaml:
apiVersion: aof.dev/v1
kind: Trigger
metadata:
name: jira-bug-triage
spec:
type: Jira
config:
webhook_secret_env: JIRA_WEBHOOK_SECRET
# Event filters
events:
- issue_created
- issue_updated
- comment_created
# Project filters
filters:
projects:
- "PROJ"
- "TEAM"
# Issue type filters
issue_types:
- "Bug"
- "Task"
- "Story"
# Status filters
statuses:
- "To Do"
- "In Progress"
- "Blocked"
# Priority filters (optional)
priorities:
- "High"
- "Critical"
# Label filters (optional)
labels:
- "needs-triage"
- "security"
# User filtering
allowed_users:
- "alice.developer"
- "bob.manager"
# Command routing
commands:
/triage:
agent: bug-triager
description: "Analyze and categorize this bug"
/estimate:
agent: story-estimator
description: "Estimate complexity and effort"
/analyze:
fleet: analysis-fleet
description: "Deep analysis of issue"
default_agent: jira-assistant
Trigger Configuration Fieldsโ
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be Jira |
config.webhook_secret_env | string | Yes | Environment variable for webhook secret |
config.events | array | Yes | Jira webhook events to listen for |
config.filters | object | No | Filter events by project, type, status, etc. |
config.allowed_users | array | No | Whitelist of Jira usernames |
commands | map | No | Command routing to agents/fleets |
default_agent | string | No | Default agent for unmatched events |
Multi-Project Configurationโ
AOF uses a single DaemonConfig + multiple Triggers architecture for multi-project Jira automation.
Architecture Overviewโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Jira Webhook (single URL: /webhook/jira) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ DaemonConfig (global) โ
โ - Enables Jira platform โ
โ - Points to triggers/ directory โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ bugs.yaml โ โ features.yaml โ โ support.yaml โ
โ projects: PROJ โ โ projects: FEAT โ โ projects: SUP โ
โ types: Bug โ โ types: Story โ โ types: Support โ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
Example: Per-Team Triggersโ
Directory structure:
config/
daemon.yaml # Global config
triggers/
jira-bugs.yaml # Bug triage team
jira-features.yaml # Feature team
jira-support.yaml # Support team
jira-devops.yaml # DevOps team
Bug triage trigger (triggers/jira-bugs.yaml):
apiVersion: aof.dev/v1
kind: Trigger
metadata:
name: bug-triage-bot
labels:
team: qa
spec:
type: Jira
config:
webhook_secret_env: JIRA_WEBHOOK_SECRET
events:
- issue_created
- issue_updated
- comment_created
filters:
projects:
- "PROJ"
- "API"
issue_types:
- "Bug"
statuses:
- "Open"
- "To Do"
- "Reopened"
commands:
/triage:
agent: bug-triager
/reproduce:
agent: bug-reproducer
/assign:
agent: bug-assigner
default_agent: bug-assistant
Feature planning trigger (triggers/jira-features.yaml):
apiVersion: aof.dev/v1
kind: Trigger
metadata:
name: feature-planning-bot
labels:
team: product
spec:
type: Jira
config:
webhook_secret_env: JIRA_WEBHOOK_SECRET
events:
- issue_created
- issue_updated
- sprint_started
- sprint_closed
filters:
projects:
- "FEAT"
- "PROD"
issue_types:
- "Story"
- "Epic"
statuses:
- "Backlog"
- "Ready for Dev"
commands:
/estimate:
agent: story-estimator
/refine:
fleet: refinement-fleet
/acceptance:
agent: acceptance-criteria-writer
default_agent: product-assistant
Support team trigger (triggers/jira-support.yaml):
apiVersion: aof.dev/v1
kind: Trigger
metadata:
name: support-bot
labels:
team: support
spec:
type: Jira
config:
webhook_secret_env: JIRA_WEBHOOK_SECRET
events:
- issue_created
- comment_created
filters:
projects:
- "SUP"
- "HELP"
issue_types:
- "Support"
- "Incident"
priorities:
- "High"
- "Critical"
commands:
/escalate:
flow: escalation-flow
/investigate:
fleet: support-fleet
default_agent: support-assistant
Webhook Routingโ
When a webhook arrives, AOF:
- Parses the project key from the event payload
- Matches against
filters.projectsin each Trigger - Routes to the first matching Trigger
- If no match, event is ignored (logged as unhandled)
Event Referenceโ
Supported Eventsโ
AOF supports all major Jira webhook events:
| Event Type | Action | Description |
|---|---|---|
issue_created | N/A | New issue created |
issue_updated | N/A | Issue fields updated (status, assignee, etc.) |
issue_deleted | N/A | Issue deleted |
comment_created | N/A | New comment posted |
comment_updated | N/A | Comment edited |
comment_deleted | N/A | Comment deleted |
sprint_created | N/A | New sprint created |
sprint_started | N/A | Sprint started |
sprint_closed | N/A | Sprint closed |
sprint_updated | N/A | Sprint details updated |
sprint_deleted | N/A | Sprint deleted |
worklog_created | N/A | Work logged on issue |
worklog_updated | N/A | Work log updated |
worklog_deleted | N/A | Work log deleted |
Event Detailsโ
issue_createdโ
Triggered when a new issue is created.
When it fires:
- User creates issue via UI
- Issue created via API
- Issue imported from CSV/external system
Payload fields:
issue- Full issue objectuser- User who created the issuechangelog- N/A (new issue)
issue_updatedโ
Triggered when any issue field changes.
When it fires:
- Status transition
- Assignee changed
- Fields updated (priority, labels, custom fields)
- Attachments added/removed
Payload fields:
issue- Updated issue objectuser- User who made the changechangelog- Array of field changes with old/new values
Common changelog items:
| Field | Description |
|---|---|
status | Status transition (e.g., "To Do" โ "In Progress") |
assignee | Assignee changed |
priority | Priority changed |
labels | Labels added/removed |
sprint | Sprint added/removed |
fixVersions | Fix versions changed |
description | Description updated |
summary | Title updated |
comment_createdโ
Triggered when a comment is posted on an issue.
When it fires:
- User posts comment via UI
- Comment added via API
- Bot or integration posts comment
Payload fields:
issue- Issue the comment is oncomment- Comment object with body, author, created timestampuser- User who posted the comment
sprint_startedโ
Triggered when a sprint begins.
When it fires:
- Sprint manually started by Scrum Master
- Sprint auto-started at scheduled time
Payload fields:
sprint- Sprint object (id, name, startDate, endDate, goal)board- Board the sprint belongs to
sprint_closedโ
Triggered when a sprint ends.
When it fires:
- Sprint manually completed
- Sprint auto-completed at end date
Payload fields:
sprint- Sprint objectboard- Board objectissues_completed- Count of issues completedissues_incomplete- Count of issues not completed
Webhook Payload Structureโ
AOF normalizes Jira webhook payloads into a consistent structure.
Common Fieldsโ
All Jira webhooks include these base fields:
{
"webhookEvent": "jira:issue_created",
"issue_event_type_name": "issue_created",
"user": {
"accountId": "5b10a2844c20165700ede21g",
"displayName": "Alice Developer",
"emailAddress": "alice@company.com"
},
"timestamp": 1640000000000
}
Issue Eventsโ
{
"webhookEvent": "jira:issue_updated",
"issue": {
"id": "10001",
"key": "PROJ-123",
"fields": {
"summary": "Fix login bug",
"description": "Users cannot log in with SSO",
"status": {
"name": "In Progress",
"statusCategory": {
"key": "indeterminate"
}
},
"issuetype": {
"name": "Bug",
"subtask": false
},
"priority": {
"name": "High"
},
"assignee": {
"accountId": "5b10a2844c20165700ede21g",
"displayName": "Alice Developer"
},
"reporter": {
"accountId": "5b10a2844c20165700ede22h",
"displayName": "Bob Manager"
},
"labels": ["security", "sso"],
"created": "2024-01-15T10:30:00.000+0000",
"updated": "2024-01-15T14:45:00.000+0000"
}
},
"changelog": {
"items": [
{
"field": "status",
"fieldtype": "jira",
"from": "10000",
"fromString": "To Do",
"to": "10001",
"toString": "In Progress"
}
]
}
}
Comment Eventsโ
{
"webhookEvent": "comment_created",
"comment": {
"id": "10200",
"body": "I can reproduce this on staging",
"author": {
"accountId": "5b10a2844c20165700ede21g",
"displayName": "Alice Developer"
},
"created": "2024-01-15T15:00:00.000+0000",
"updated": "2024-01-15T15:00:00.000+0000"
},
"issue": {
"key": "PROJ-123",
"fields": { ... }
}
}
Sprint Eventsโ
{
"webhookEvent": "sprint_started",
"sprint": {
"id": 42,
"name": "Sprint 10",
"state": "active",
"startDate": "2024-01-15T09:00:00.000Z",
"endDate": "2024-01-29T17:00:00.000Z",
"goal": "Complete authentication refactor"
},
"board": {
"id": 1,
"name": "Engineering Board",
"type": "scrum"
}
}
Context Variablesโ
When an agent is triggered by a Jira event, these variables are available in metadata:
Common Variablesโ
| Variable | Type | Description |
|---|---|---|
event_type | string | Event type (issue_created, etc.) |
timestamp | integer | Event timestamp (milliseconds) |
user_account_id | string | User account ID |
user_display_name | string | User display name |
user_email | string | User email address |
Issue Variablesโ
Available for all issue events:
| Variable | Type | Description |
|---|---|---|
issue_id | string | Issue ID |
issue_key | string | Issue key (PROJ-123) |
issue_summary | string | Issue title |
issue_description | string | Issue description |
issue_type | string | Issue type (Bug, Story, etc.) |
issue_status | string | Current status |
issue_priority | string | Priority (High, Medium, Low) |
issue_assignee_id | string | Assignee account ID |
issue_assignee_name | string | Assignee display name |
issue_reporter_id | string | Reporter account ID |
issue_reporter_name | string | Reporter display name |
issue_labels | array | Labels on issue |
issue_created | string | Creation timestamp |
issue_updated | string | Last update timestamp |
project_key | string | Project key |
project_name | string | Project name |
Comment Variablesโ
Available for comment events:
| Variable | Type | Description |
|---|---|---|
comment_id | string | Comment ID |
comment_body | string | Comment text |
comment_author_id | string | Author account ID |
comment_author_name | string | Author display name |
comment_created | string | Comment creation timestamp |
Sprint Variablesโ
Available for sprint events:
| Variable | Type | Description |
|---|---|---|
sprint_id | integer | Sprint ID |
sprint_name | string | Sprint name |
sprint_state | string | Sprint state (future, active, closed) |
sprint_start_date | string | Sprint start date |
sprint_end_date | string | Sprint end date |
sprint_goal | string | Sprint goal |
board_id | integer | Board ID |
board_name | string | Board name |
Changelog Variablesโ
Available for issue_updated events:
| Variable | Type | Description |
|---|---|---|
changelog_items | array | Array of changed fields |
Each changelog item has:
field- Field name (status, assignee, etc.)from_string- Old value (human-readable)to_string- New value (human-readable)
Usage in Agent Instructionsโ
spec:
instructions: |
You are analyzing issue {{ metadata.issue_key }}.
Issue Details:
- Title: {{ metadata.issue_summary }}
- Type: {{ metadata.issue_type }}
- Status: {{ metadata.issue_status }}
- Priority: {{ metadata.issue_priority }}
- Assignee: {{ metadata.issue_assignee_name }}
- Reporter: {{ metadata.issue_reporter_name }}
Description:
{{ metadata.issue_description }}
{% if metadata.comment_body %}
Latest Comment by {{ metadata.comment_author_name }}:
{{ metadata.comment_body }}
{% endif %}
{% if metadata.changelog_items %}
Recent Changes:
{% for item in metadata.changelog_items %}
- {{ item.field }}: {{ item.from_string }} โ {{ item.to_string }}
{% endfor %}
{% endif %}
API Actionsโ
Actions agents can perform on Jira via built-in tools.
Post Commentโ
Post a comment on an issue.
# In agent instructions
tools:
- jira_post_comment
# Usage
Post a comment to {{ metadata.issue_key }}:
"This issue has been triaged and assigned to the backend team."
Rust API:
platform.post_comment("PROJ-123", "Comment text").await?;
Parameters:
issue_key(string) - Issue key (PROJ-123)body(string) - Comment text (supports Jira markup)
Returns: Comment ID
Update Issueโ
Update issue fields.
# Usage
Update {{ metadata.issue_key }}:
- Set status to "In Progress"
- Set assignee to "alice.developer"
- Add labels ["backend", "urgent"]
Rust API:
use serde_json::json;
platform.update_issue("PROJ-123", json!({
"fields": {
"assignee": {"accountId": "5b10a2844c20165700ede21g"},
"labels": ["backend", "urgent"],
"priority": {"name": "High"}
}
})).await?;
Parameters:
issue_key(string) - Issue keyfields(object) - Fields to update
Common fields:
| Field | Value Format | Example |
|---|---|---|
assignee | {"accountId": "..."} | Assign to user |
priority | {"name": "High"} | Set priority |
labels | ["label1", "label2"] | Set labels |
description | String | Update description |
summary | String | Update title |
| Custom fields | Varies by field type | See Jira API docs |
Transition Issueโ
Change issue status (transition workflow).
# Usage
Transition {{ metadata.issue_key }} to "In Progress"
Rust API:
platform.transition_issue("PROJ-123", "31").await?;
Parameters:
issue_key(string) - Issue keytransition_id(string) - Transition ID (get from workflow)
Finding transition IDs:
curl -u email@example.com:api_token \
https://yourcompany.atlassian.net/rest/api/3/issue/PROJ-123/transitions
Add Labelโ
Add labels to an issue.
# Usage
Add labels ["needs-review", "security"] to {{ metadata.issue_key }}
Rust API:
platform.add_labels("PROJ-123", &["needs-review", "security"]).await?;
Parameters:
issue_key(string) - Issue keylabels(array) - Labels to add
Remove Labelโ
Remove a label from an issue.
# Usage
Remove label "needs-triage" from {{ metadata.issue_key }}
Rust API:
platform.remove_label("PROJ-123", "needs-triage").await?;
Parameters:
issue_key(string) - Issue keylabel(string) - Label to remove
Assign Userโ
Assign an issue to a user.
# Usage
Assign {{ metadata.issue_key }} to "alice.developer"
Rust API:
platform.assign_issue("PROJ-123", "5b10a2844c20165700ede21g").await?;
Parameters:
issue_key(string) - Issue keyaccount_id(string) - User account ID
Finding account IDs:
curl -u email@example.com:api_token \
https://yourcompany.atlassian.net/rest/api/3/user/search?query=alice
Log Workโ
Log time spent on an issue.
# Usage
Log 2 hours of work on {{ metadata.issue_key }}
Comment: "Fixed authentication bug"
Rust API:
use serde_json::json;
platform.log_work("PROJ-123", json!({
"timeSpent": "2h",
"comment": "Fixed authentication bug",
"started": "2024-01-15T09:00:00.000+0000"
})).await?;
Parameters:
issue_key(string) - Issue keytime_spent(string) - Time format (e.g., "2h 30m", "1d")comment(string, optional) - Work log commentstarted(string, optional) - Start timestamp
Time formats:
1w- 1 week2d- 2 days4h- 4 hours30m- 30 minutes1h 30m- Combined
Link Issuesโ
Create a link between two issues.
# Usage
Link {{ metadata.issue_key }} to PROJ-456 as "relates to"
Rust API:
use serde_json::json;
platform.link_issues(json!({
"type": {"name": "Relates"},
"inwardIssue": {"key": "PROJ-123"},
"outwardIssue": {"key": "PROJ-456"}
})).await?;
Parameters:
type(string) - Link type nameinward_issue(string) - Source issue keyoutward_issue(string) - Target issue key
Common link types:
| Type | Description |
|---|---|
Blocks | This issue blocks another |
Relates | General relationship |
Duplicates | Duplicate issue |
Causes | This issue causes another |
Clones | Cloned from another issue |
Securityโ
Webhook Verificationโ
AOF validates webhook requests using a shared secret.
How it works:
- Configure webhook secret in Jira webhook settings
- AOF validates incoming requests against configured secret
- Requests without valid signature are rejected
Configuration:
spec:
config:
webhook_secret_env: JIRA_WEBHOOK_SECRET # Required
Generate secure secret:
openssl rand -hex 32
Authentication Methodsโ
API Token (Jira Cloud - Recommended)โ
Create API token:
- Go to https://id.atlassian.com/manage-profile/security/api-tokens
- Click "Create API token"
- Copy token and store securely
Configure:
export JIRA_EMAIL="your-email@company.com"
export JIRA_API_TOKEN="your-api-token"
Permissions: Inherits permissions from your Jira Cloud account.
Personal Access Token (Self-Hosted)โ
For Jira Server/Data Center:
- Go to Profile โ Personal Access Tokens
- Create new token with required permissions
- Copy token immediately (shown only once)
Configure:
export JIRA_PAT="your-personal-access-token"
OAuth 2.0 (Advanced)โ
For programmatic access without user credentials:
- Register OAuth 2.0 app in Jira
- Obtain client ID and secret
- Implement OAuth flow
- Store refresh token
Configuration:
platforms:
jira:
auth:
type: oauth2
client_id_env: JIRA_OAUTH_CLIENT_ID
client_secret_env: JIRA_OAUTH_SECRET
token_env: JIRA_OAUTH_TOKEN
Project Filteringโ
Whitelist projects for security:
filters:
projects:
- "PROJ" # Specific project
- "TEAM" # Another project
- "PROD-*" # Pattern matching (if supported)
User Filteringโ
Restrict who can trigger automation:
config:
allowed_users:
- "alice.developer"
- "bob.manager"
- "qa-bot"
Events from users not in this list will be ignored.
Note: User filtering is based on Jira usernames/account IDs. Group-based authorization is planned for a future release.
Rate Limitingโ
Jira API Limitsโ
| Type | Limit | Notes |
|---|---|---|
| Jira Cloud | Varies by plan | ~100-300 req/sec depending on subscription |
| Jira Server | Configurable | Set by admin in Rate Limiting settings |
| Search API | 20 req/sec | Lower limit for JQL searches |
Jira Cloud rate limits:
- Free tier: ~100 requests/second
- Standard/Premium: ~200-300 requests/second
- Enterprise: Custom limits
Mitigation Strategiesโ
- Batch operations - Update multiple fields in single API call
- Use webhooks - React to events instead of polling
- Cache data - Store frequently accessed data locally
- Implement backoff - Retry with exponential backoff
- Use bulk APIs - Bulk update, bulk delete operations
Check rate limit:
# Jira Cloud
curl -u email@example.com:api_token \
-X GET "https://yourcompany.atlassian.net/rest/api/3/myself" \
-H "Accept: application/json"
Check response headers:
X-RateLimit-Limit- Rate limit ceilingX-RateLimit-Remaining- Requests left in windowRetry-After- Seconds until retry (if rate limited)
AOF handles retries automatically with exponential backoff when rate limit is hit.
Environment Variablesโ
# Jira Cloud (API Token)
export JIRA_EMAIL="your-email@company.com"
export JIRA_API_TOKEN="your-api-token"
export JIRA_WEBHOOK_SECRET="random-secret-key"
# Jira Server/Data Center (PAT)
export JIRA_PAT="your-personal-access-token"
export JIRA_WEBHOOK_SECRET="random-secret-key"
# LLM provider
export GOOGLE_API_KEY="xxxxx"
# OR
export ANTHROPIC_API_KEY="xxxxx"
Examplesโ
Auto-Triage Bugsโ
# triggers/jira-bug-triage.yaml
apiVersion: aof.dev/v1
kind: Trigger
metadata:
name: bug-triage
spec:
type: Jira
config:
webhook_secret_env: JIRA_WEBHOOK_SECRET
events:
- issue_created
filters:
projects: ["PROJ"]
issue_types: ["Bug"]
default_agent: bug-triager
# agents/bug-triager.yaml
apiVersion: aof.dev/v1
kind: Agent
metadata:
name: bug-triager
spec:
model: google:gemini-2.5-flash
instructions: |
Analyze bug {{ metadata.issue_key }}.
Issue: {{ metadata.issue_summary }}
Description: {{ metadata.issue_description }}
1. Determine severity based on description
2. Set priority (Critical/High/Medium/Low)
3. Add relevant labels (backend, frontend, database, etc.)
4. Suggest assignee based on component
5. Post analysis comment
tools:
- jira_update_issue
- jira_add_labels
- jira_post_comment
Story Point Estimationโ
# triggers/jira-estimation.yaml
apiVersion: aof.dev/v1
kind: Trigger
metadata:
name: story-estimation
spec:
type: Jira
config:
events:
- issue_created
filters:
projects: ["FEAT"]
issue_types: ["Story", "Task"]
commands:
/estimate:
agent: story-estimator
# agents/story-estimator.yaml
apiVersion: aof.dev/v1
kind: Agent
metadata:
name: story-estimator
spec:
model: google:gemini-2.5-flash
instructions: |
Estimate story points for {{ metadata.issue_key }}.
Story: {{ metadata.issue_summary }}
Description: {{ metadata.issue_description }}
Analyze complexity based on:
1. Technical complexity
2. Unknown factors
3. Dependencies
4. Testing requirements
Recommend story points (1, 2, 3, 5, 8, 13) and explain reasoning.
Post comment with analysis.
tools:
- jira_post_comment
Sprint Planning Automationโ
# triggers/jira-sprint.yaml
apiVersion: aof.dev/v1
kind: Trigger
metadata:
name: sprint-planning
spec:
type: Jira
config:
events:
- sprint_started
- sprint_closed
default_fleet: sprint-fleet
# fleets/sprint-fleet.yaml
apiVersion: aof.dev/v1
kind: Fleet
metadata:
name: sprint-fleet
spec:
agents:
- name: sprint-analyzer
role: coordinator
- name: velocity-tracker
role: specialist
- name: report-generator
role: specialist
workflow: |
On sprint start:
1. sprint-analyzer: Analyze sprint capacity and commitments
2. velocity-tracker: Calculate team velocity from previous sprints
3. report-generator: Generate sprint kickoff report
On sprint close:
1. sprint-analyzer: Review completed vs planned work
2. velocity-tracker: Update velocity metrics
3. report-generator: Generate retrospective report
GitHub/Jira Cross-Referenceโ
# agents/github-jira-sync.yaml
apiVersion: aof.dev/v1
kind: Agent
metadata:
name: github-jira-sync
spec:
model: google:gemini-2.5-flash
instructions: |
You sync GitHub PRs with Jira issues.
When PR is opened:
1. Extract Jira issue key from PR title (PROJ-123)
2. Post comment on Jira issue with PR link
3. Add "in-review" label to Jira issue
When PR is merged:
1. Transition Jira issue to "Done"
2. Post merge confirmation comment
3. Log work time based on PR size
tools:
- jira_post_comment
- jira_transition_issue
- jira_add_labels
- jira_log_work
Webhook Setupโ
1. Create Webhook in Jiraโ
Jira Cloudโ
- Go to Settings โ System โ WebHooks
- Click Create a WebHook
- Configure:
- Name: AOF Automation
- Status: Enabled
- URL:
https://your-domain.com/webhook/jira - Secret: Your
JIRA_WEBHOOK_SECRETvalue - Events: Select desired events or check "All issues"
- Exclude body: Uncheck (AOF needs full payload)
Jira Server/Data Centerโ
- Go to Settings โ System โ Advanced โ WebHooks
- Create webhook with same configuration as Cloud
- Ensure firewall allows webhook traffic to AOF daemon
2. Expose Endpointโ
For production:
# HTTPS required
https://your-domain.com/webhook/jira
For local testing: Use a tunnel service:
# Option 1: Cloudflared (no signup)
brew install cloudflared
cloudflared tunnel --url http://localhost:3000
# Option 2: ngrok (free account)
ngrok http 3000
Use tunnel URL as webhook URL in Jira.
3. Verify Webhookโ
- Test webhook in Jira webhook settings
- Check webhook delivery logs in Jira
- Verify AOF logs show received event
# Check logs
tail -f /var/log/aof/daemon.log
# Look for:
# INFO Jira webhook received: issue_created
# INFO Posted comment to PROJ-123
Troubleshootingโ
Webhook Not Triggeringโ
Symptoms: Jira webhook shows success but agent doesn't run
Solutions:
- Check webhook delivery logs in Jira admin panel
- Verify webhook secret matches
JIRA_WEBHOOK_SECRET - Check firewall allows Jira Cloud IPs (if using Cloud)
- Verify daemon is running:
aofctl serve --config daemon.yaml - Check logs:
RUST_LOG=debug aofctl serve
Authentication Failedโ
Symptoms: 401 Unauthorized in logs
Solutions:
- Verify API token/PAT is valid
- For API token: Confirm
JIRA_EMAILmatches token owner - Test credentials manually:
curl -u email@example.com:api_token \
https://yourcompany.atlassian.net/rest/api/3/myself - Check token hasn't expired (PATs expire in Server/DC)
Cannot Post Commentsโ
Symptoms: Agent runs but comments don't appear
Solutions:
- Verify token has correct permissions
- Check user has access to project
- Verify issue exists and is not deleted
- Test comment API manually:
curl -u email@example.com:api_token \
-X POST "https://yourcompany.atlassian.net/rest/api/3/issue/PROJ-123/comment" \
-H "Content-Type: application/json" \
-d '{"body": "Test comment"}'
Base URL Configurationโ
Symptoms: 404 Not Found or connection errors
Solutions:
- Verify
base_urlformat:- Jira Cloud:
https://yourcompany.atlassian.net - Self-hosted:
https://jira.yourcompany.com
- Jira Cloud:
- No trailing slash in URL
- For self-hosted: Verify DNS resolution and network access
Rate Limit Issuesโ
Symptoms: 429 Too Many Requests errors
Solutions:
- Check rate limit headers in API responses
- Reduce webhook event frequency (filter by project/type)
- Implement caching for frequently accessed data
- Contact Atlassian support to increase limits (Cloud)
Best Practicesโ
1. Filter Events Preciselyโ
โ Too broad:
events:
- issue_created
- issue_updated
- comment_created
โ Specific:
events:
- issue_created
- comment_created
filters:
projects: ["PROJ"]
issue_types: ["Bug"]
statuses: ["Open"]
2. Use Project Filtersโ
For production:
filters:
projects:
- "PROD"
- "API"
issue_types:
- "Bug"
- "Incident"
Prevents accidental automation on test projects.
3. Implement Approval Gatesโ
For destructive actions:
spec:
instructions: |
Before transitioning to Done:
1. Verify all subtasks are complete
2. Check PR is merged (if linked)
3. Ensure QA has signed off
4. Confirm no blocking issues
5. Request human approval if uncertain
4. Cache Jira Dataโ
Reduce API calls:
spec:
memory: "File:./jira-cache.json:1000"
instructions: |
Before making API calls, check memory cache for:
- User account IDs
- Transition IDs
- Custom field IDs
5. Use Structured Commentsโ
Post comments with clear structure:
spec:
instructions: |
Post comment with this format:
h3. AI Analysis
[Analysis summary]
h4. Recommended Actions
* Action 1
* Action 2
h4. Severity Assessment
Priority: [High/Medium/Low]
Labels: [suggested-labels]
6. Log Work Automaticallyโ
Track time spent on automated tasks:
spec:
instructions: |
After completing analysis:
1. Log work time based on complexity
2. Add comment explaining what was done
3. Update issue status if appropriate
Enterprise Considerationsโ
Self-Hosted Deploymentโ
Network requirements:
- Jira must be able to reach AOF daemon webhook endpoint
- Consider reverse proxy for SSL termination
- Firewall rules to allow Jira โ AOF traffic
Configuration:
platforms:
jira:
base_url: https://jira.company.internal
proxy:
http_proxy: http://proxy.company.com:8080
https_proxy: https://proxy.company.com:8080
tls:
verify: true
ca_cert_path: /etc/ssl/certs/company-ca.pem
High Availabilityโ
Run multiple AOF daemon replicas:
# Kubernetes deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: aof-daemon
spec:
replicas: 3
template:
spec:
containers:
- name: aof
image: ghcr.io/agenticdevops/aof:latest
Scaling Recommendationsโ
| Scale | Projects | Issues/day | Setup |
|---|---|---|---|
| Small | 1-10 | Up to 1000 | Single daemon |
| Medium | 10-50 | 1000-5000 | 2-3 replicas |
| Large | 50-200 | 5000-20000 | Sharded by project |
| Enterprise | 200+ | 20000+ | Message queue (planned) |
See Alsoโ
- Trigger Specification - Complete trigger reference
- Agent Specification - Agent configuration
- Daemon Configuration - Daemon setup
- GitHub Integration - GitHub automation
- Platform Policies - Cross-platform policies