From recipe-skills
Jira integration recipes for Workato. Enables AI agents to generate valid recipe JSON for Jira operations including searching issues by JQL, creating and updating issues, and querying sprint data.
How this skill is triggered — by the user, by Claude, or both
Slash command
/recipe-skills:jira-recipesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> **⚠️ DEPENDENCY: Load the `workato-recipes` base skill first if not already loaded.**
⚠️ DEPENDENCY: Load the
workato-recipesbase skill first if not already loaded. This skill requires the base Workato knowledge for triggers, control flow, datapills, formulas, and recipe structure.
This skill provides Jira-specific knowledge for generating Workato recipes. It extends the workato-recipes base skill and focuses on Jira-specific patterns.
.recipe.json files to understand local patternstemplates/search-issues-by-jql.json as referencejira-search-sprint-003, return-success-jira-004ENG, MOB, PROJ)search_issues_by_JQL is case-sensitive (uppercase JQL)Use this skill when building Workato recipes that:
Prerequisites:
workato-recipes base skill loadedEvery Jira recipe requires the jira provider in the config section:
{
"keyword": "application",
"provider": "jira",
"skip_validation": false,
"account_id": {
"zip_name": "connectors/jira.connection.json",
"name": "My Jira Connection",
"folder": "connectors"
}
}
Combined with API endpoint trigger:
"config": [
{
"keyword": "application",
"provider": "workato_api_platform",
"skip_validation": false,
"account_id": null
},
{
"keyword": "application",
"provider": "jira",
"skip_validation": false,
"account_id": {
"zip_name": "connectors/jira.connection.json",
"name": "My Jira Connection",
"folder": "connectors"
}
}
]
The Jira connector provides 17 native actions and 11 triggers. See lint-rules.json for the authoritative list of valid action and trigger names.
new_event — fires on any configured Jira event (issue created, updated, etc.).new_issue, updated_issue — poll for new or updated issues.new_issue_batch, updated_issue_batch — poll for batches of new/updated issues.issue_created_bulk, issue_created_or_updated_bulk — for high-volume processing.updated_comment_webhook, updated_issue_webhook, updated_worklog_webhook — real-time triggers for specific change types.deleted_object — triggers on object deletion.Issue CRUD:
create_issue — Create a new issue. Key inputs: project_key, issue_type, summary. See detail below.get_issue — Get full issue details by ID or key. See detail below.update_issue — Update issue fields. Requires issue_id_or_key. See detail below.update_issue_status — Transition issue to a different workflow state.assign_issue — Assign an issue to a user.Search:
search_issues_by_JQL — Primary search action. Full JQL flexibility, battle-tested. Name is case-sensitive (uppercase JQL). See detail below.search_issues — Simpler field-filter search without JQL. Less flexible.Comments: create_comment, update_comment, get_issue_comments
Users: find_user (by query string), search_assignable_users (users assignable to an issue), create_user
Attachments: upload_attachment, get_attachment
Metadata: get_changelog (issue change history), get_object_schema
Uncovered operations: Use __adhoc_http_action for Jira operations not covered by native actions: workflow transitions, sprint/board management, project listing, custom field management, tempo/time tracking, and advanced operations.
Use when: Finding issues using JQL queries — sprints, filters, project scoping.
CRITICAL: The action name is case-sensitive. It MUST be search_issues_by_JQL (uppercase JQL).
{
"provider": "jira",
"name": "search_issues_by_JQL",
"as": "jira_search",
"keyword": "action",
"input": {
"jql": "='project = \"' + _dp('{...project_key...}') + '\" AND sprint in openSprints()'"
},
"extended_input_schema": [],
"extended_output_schema": [
{
"label": "Issues",
"name": "issues",
"type": "array",
"of": "object",
"properties": [
{ "control_type": "text", "label": "Key", "name": "key", "type": "string" },
{ "control_type": "text", "label": "Summary", "name": "summary", "type": "string" },
{ "control_type": "text", "label": "Status", "name": "status", "type": "string" },
{ "control_type": "text", "label": "Assignee", "name": "assignee", "type": "string" },
{ "control_type": "number", "label": "Story Points", "name": "story_points", "type": "number" }
]
}
]
}
Key rules:
jql is the native field name (NOT query) — maps to "JQL query string" in the Workato UIextended_input_schema MUST be [] — jql is a connector internal; including it in EIS creates a duplicate field= formula mode (bare _dp(), no #{} wrapper)extended_output_schema defines the issue fields you want to access via datapills{
"provider": "jira",
"name": "create_issue",
"as": "create_jira_issue",
"keyword": "action",
"input": {
"project_key": "ENG",
"issue_type": "Story",
"summary": "#{summary_datapill}",
"description": "#{description_datapill}"
}
}
Expected fields: project_key, issue_type, summary, description, priority, assignee, labels
{
"provider": "jira",
"name": "update_issue",
"as": "update_jira_issue",
"keyword": "action",
"input": {
"issue_id_or_key": "ENG-123",
"summary": "#{summary_datapill}"
}
}
{
"provider": "jira",
"name": "get_issue",
"as": "get_jira_issue",
"keyword": "action",
"input": {
"issue_id_or_key": "ENG-123"
}
}
JQL queries in Workato are built using = formula mode. This means bare _dp() calls — no #{} interpolation.
The jql input field uses formula mode (= prefix) to concatenate strings and datapills:
"jql": "='project = \"' + _dp('{...project_key...}') + '\" AND sprint in openSprints()'"
Breaking this down:
= — enters formula mode'project = \"' — literal string with escaped double quotes for JQL values+ _dp('{...}') + — concatenates the datapill value'\" AND sprint in openSprints()' — more literal JQL.present?Use the ternary pattern to add optional clauses:
"jql": "='project = \"' + _dp('{...project_key...}') + '\"' + (_dp('{...sprint_name...}').present? ? ' AND sprint = \"' + _dp('{...sprint_name...}') + '\"' : ' AND sprint in openSprints()')"
This pattern:
sprint_name was providedIMPORTANT: No outer () wrapping the entire formula. The = is followed directly by the expression. Wrapping breaks condition LHS parsing in child actions.
See: patterns/jql-query-syntax.md for complete reference.
Jira actions do NOT use the ["body"] wrapper in datapill paths. This is consistent with other native connectors (Salesforce, Stripe).
// CORRECT for Jira
"path": ["issues"]
"path": ["issues", {"path_element_type": "current_item"}, "key"]
// WRONG for Jira — Do NOT use
"path": ["body", "issues"]
Issues array (for .to_json serialization):
"#{_dp('{\"pill_type\":\"output\",\"provider\":\"jira\",\"line\":\"jira_search\",\"path\":[\"issues\"]}')}"
Issue count (using path_element_type: "size"):
"=_dp('{\"pill_type\":\"output\",\"provider\":\"jira\",\"line\":\"jira_search\",\"path\":[\"issues\",{\"path_element_type\":\"size\"}]}')"
Issues array as JSON string (for return_response):
"=_dp('{\"pill_type\":\"output\",\"provider\":\"jira\",\"line\":\"jira_search\",\"path\":[\"issues\"]}').to_json"
Individual issue field (inside foreach):
"path": ["issues", {"path_element_type": "current_item"}, "key"]
"path": ["issues", {"path_element_type": "current_item"}, "summary"]
"path": ["issues", {"path_element_type": "current_item"}, "status"]
Search for issues and return as JSON string with count:
// Step: Jira search
{
"provider": "jira",
"name": "search_issues_by_JQL",
"as": "jira_search",
"input": {
"jql": "='project = \"ENG\" AND sprint in openSprints()'"
},
"extended_input_schema": [],
"extended_output_schema": [...]
}
// Step: Return response
{
"provider": "workato_api_platform",
"name": "return_response",
"input": {
"http_status_code": "200",
"response": {
"issues_json": "=_dp('{...path:[\"issues\"]}').to_json",
"total_issues": "=_dp('{...path:[\"issues\",{\"path_element_type\":\"size\"}]}')"
}
}
}
Key: Use .to_json to serialize the issues array into a string for return. Use path_element_type: "size" for the count — NOT .size formula method.
Always validate required inputs before making Jira API calls:
{
"keyword": "if",
"input": {
"conditions": [{
"operand": "present",
"lhs": "#{_dp('{...path:[\"request\",\"project_key\"]}')}",
"uuid": "cond-project-key-001"
}]
},
"block": [
// Jira search goes here
]
}
Wrap Jira actions in try/catch to handle API failures:
{
"keyword": "try",
"block": [
// Jira actions...
]
},
{
"keyword": "catch",
"provider": null,
"as": "catch_jira_error",
"input": { "max_retry_count": "0", "retry_interval": "2" },
"block": [
{
"provider": "workato_api_platform",
"name": "return_response",
"input": {
"http_status_code": "500",
"response": {
"error_message": "#{_dp('{\"pill_type\":\"output\",\"provider\":\"catch\",\"line\":\"catch_jira_error\",\"path\":[\"message\"]}')}"
}
}
}
]
}
Key: Catch datapills use "provider":"catch" — NOT "provider":null.
jql Is a Connector InternalThe jql field is Jira's native parameter for the search_issues_by_JQL action. It must NEVER appear in extended_input_schema.
Correct:
{
"input": {
"jql": "='project = \"ENG\"'"
},
"extended_input_schema": []
}
Wrong — causes duplicate field in UI:
{
"input": {
"jql": "='project = \"ENG\"'"
},
"extended_input_schema": [
{ "name": "jql", "type": "string", ... }
]
}
Empty extended_input_schema: [] is correct for search_issues_by_JQL because the only input (jql) is a connector internal. If future actions require user-facing fields that are NOT connector internals, those would go in EIS — but for search, [] is the right answer.
| Error | Cause | Solution |
|---|---|---|
| "Select an app and action" in UI | Action name is wrong or case-incorrect | Use exactly search_issues_by_JQL (uppercase JQL) |
| Duplicate JQL field in UI | jql included in extended_input_schema | Remove jql from EIS; set extended_input_schema: [] |
| "Field not recognized" | Using query instead of jql | The native field name is jql, not query |
| JQL parse error | Missing double quotes around values in JQL string | Use \"value\" inside formula mode strings |
| Empty results | JQL formula not in = mode | Prefix JQL value with = for formula mode |
| Datapill not found | ["body"] wrapper in path | Jira is a native connector — no ["body"] wrapper |
See validation-checklist.md for Jira-specific validation, which references the base checklist in workato-recipes/validation-checklist.md.
See templates/ directory:
search-issues-by-jql.json - Search issues by JQL with conditional sprint filter, try/catch, multi-status responsesworkato-recipes - Recipe structure, triggers, control flow, formulastemplates/ directorypatterns/ directorynpx claudepluginhub workato-devs/recipe-skills --plugin recipe-skillsCreates structured, bite-sized implementation plans from specs or requirements before writing code. Useful for breaking down multi-step tasks into testable steps with file structure and task boundaries.