创建内容由网络搜索丰富的 Jira 工单。按顺序遵循以下阶段。
设置
需要三个环境变量:
JIRA_BASE_URL — 你的 Atlassian 实例(例如 https://yourteam.atlassian.net)
JIRA_EMAIL — 与你的 Atlassian 账户关联的邮箱
JIRA_API_TOKEN — 来自 https://id.atlassian.com/manage-profile/security/api-tokens 的 API 令牌
所有 Jira API 调用通过 curl -u 使用基本认证并强制使用 HTTP/1.1:
curl --http1.1 -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" -H "Content-Type: application/json" "$JIRA_BASE_URL/rest/api/3/..."
阶段 1 — 解析参数
解析用户请求,提取以下字段:
| 字段 | 必填 | 描述 |
|---|
| project | 是 | Jira 项目键(如 ENG、OPS) |
| issuetype | 否 | Task、Bug、Story、Epic(默认:Task) |
| summary | 是 | 工单简短标题 |
| search_query | 否 | 用于丰富描述的网络搜索主题 |
| priority | 否 | Highest、High、Medium、Low、Lowest(默认:Medium) |
| assignee | 否 | Atlassian 账户邮箱或 ID |
| labels | 否 | 逗号分隔的标签 |
| components | 否 | 逗号分隔的组件名称 |
如果用户未提供项目键,请在继续之前询问。
阶段 2 — 网络研究(如适用)
如果用户要求研究,或者工单可以从上下文受益(例如,引用外部 API 的缺陷报告,关于集成第三方服务的故事):
- 使用
web_search 工具搜索相关主题。
- 使用
xurl 工具或 curl 获取关键页面以获取详情。
- 提取最相关信息:错误描述、API 文档、最佳实践、版本说明或解决方案方法。
将发现编译成结构化摘要:
### 研究摘要
- 来源: [URL]
- 关键发现: ...
- 相关细节: ...
如果不需要研究,跳过阶段 3。
阶段 3 — 编写工单内容
使用 Atlassian 文档格式(ADF)构建工单描述。结合:
- 用户的原始请求/上下文
- 阶段 2 的研究发现(如有)
- 验收标准(创建 Story 时)
- 重现步骤(创建 Bug 时)
保持描述简洁且可操作。
ADF 结构
Jira API v3 对描述字段使用 ADF。最小示例:
{
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [{ "type": "text", "text": "描述文本。" }]
}
]
}
更丰富的格式(标题、列表、链接):
{
"type": "doc",
"version": 1,
"content": [
{
"type": "heading",
"attrs": { "level": 3 },
"content": [{ "type": "text", "text": "摘要" }]
},
{
"type": "bulletList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [{ "type": "text", "text": "项目一" }]
}
]
}
]
},
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "来源: " },
{
"type": "text",
"text": "链接文本",
"marks": [{ "type": "link", "attrs": { "href": "https://example.com" } }]
}
]
}
]
}
阶段 4 — 验证项目和字段
在创建工单之前,验证项目存在并发现可用字段:
# 验证项目
curl --http1.1 -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" -H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/project/$PROJECT_KEY" | jq '{key, name, id}'# 列出项目的可用问题类型
curl --http1.1 -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" -H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/project/$PROJECT_KEY/statuses" | jq '.[].name'
如果项目或问题类型无效,报告错误并请用户更正。
阶段 5 — 创建工单
curl --http1.1 -s -X POST \
-u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/issue" \
-d '{
"fields": {
"project": { "key": "PROJECT_KEY" },
"summary": "工单摘要",
"issuetype": { "name": "Task" },
"priority": { "name": "Medium" },
"description": { ADF对象 },
"labels": ["标签1", "标签2"]
}
}'
提取响应:
# 解析响应的工单键和 URL
ISSUE_KEY=$(echo "$RESPONSE" | jq -r '.key')
ISSUE_URL="$JIRA_BASE_URL/browse/$ISSUE_KEY"
如果 API 返回错误,显示错误消息并建议更正。
阶段 6 — 报告
向用户呈现结果:
- 工单键: 例如
ENG-1234
- URL: 工单的直接链接
- 摘要: 设置的标题
- 包含研究: 是/否,并列出来源
注意事项
- Jira REST API v3 需要 ADF 格式的描述 — 纯文本或 markdown 将被拒绝。
- 速率限制:Jira Cloud 允许每个用户每分钟约 100 个请求。
- NemoClaw 中的
jira.yaml 网络策略预设已允许 *.atlassian.net、auth.atlassian.com 和 api.atlassian.com 在 443 端口。
- 要在 NemoClaw 的沙箱中使用此技能,请在沙箱策略中启用 Jira 预设。
示例
# 创建简单任务
/jira-ticket ENG "更新 API 速率限制文档"# 创建带网络研究的缺陷
/jira-ticket ENG --type Bug --search "Node.js fetch timeout ECONNRESET" "修复支付服务中的间歇性 ECONNRESET"
# 创建带优先级和标签的故事
/jira-ticket PLATFORM --type Story --priority High --labels "q2,backend" "为移动客户端添加 OAuth2 PKCE 流程"
Create Jira tickets whose content is enriched by web search. Follow these phases in order.
Setup
Three environment variables are required:
JIRA_BASE_URL — your Atlassian instance (e.g. https://yourteam.atlassian.net)
JIRA_EMAIL — the email tied to your Atlassian account
JIRA_API_TOKEN — an API token from https://id.atlassian.com/manage-profile/security/api-tokens
All Jira API calls use Basic auth via curl -u and force HTTP/1.1:
curl --http1.1 -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" -H "Content-Type: application/json" "$JIRA_BASE_URL/rest/api/3/..."
Phase 1 — Parse Arguments
Parse the user's request to extract:
| Field | Required | Description |
|---|
| project | yes | Jira project key (e.g. ENG, OPS) |
| issuetype | no | Task, Bug, Story, Epic (default: Task) |
| summary | yes | Short title for the ticket |
| search_query | no | Topic to web-search for enriching the description |
| priority | no | Highest, High, Medium, Low, Lowest (default: Medium) |
| assignee | no | Atlassian account email or ID |
| labels | no | Comma-separated labels |
| components | no | Comma-separated component names |
If the user does not provide a project key, ask for it before proceeding.
Phase 2 — Web Research (if applicable)
If the user asked for research, or if the ticket would benefit from context (e.g. a bug report referencing an external API, a story about integrating a third-party service):
- Use the
web_search tool to search for the relevant topic.
- Use the
xurl tool or curl to fetch key pages for details.
- Extract the most relevant information: error descriptions, API docs, best practices, version notes, or solution approaches.
Compile findings into a structured summary:
### Research Summary
- Source: [URL]
- Key findings: ...
- Relevant details: ...
If no research is needed, skip to Phase 3.
Phase 3 — Compose Ticket Content
Build the ticket description in Atlassian Document Format (ADF). Combine:
- The user's original request/context
- Research findings from Phase 2 (if any)
- Acceptance criteria (when creating Stories)
- Steps to reproduce (when creating Bugs)
Keep the description concise and actionable.
ADF Structure
Jira API v3 uses ADF for the description field. Minimal example:
{
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [{ "type": "text", "text": "Description text here." }]
}
]
}
For richer formatting (headings, bullet lists, links):
{
"type": "doc",
"version": 1,
"content": [
{
"type": "heading",
"attrs": { "level": 3 },
"content": [{ "type": "text", "text": "Summary" }]
},
{
"type": "bulletList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [{ "type": "text", "text": "Item one" }]
}
]
}
]
},
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "Source: " },
{
"type": "text",
"text": "link text",
"marks": [{ "type": "link", "attrs": { "href": "https://example.com" } }]
}
]
}
]
}
Phase 4 — Validate Project and Fields
Before creating the ticket, verify the project exists and discover available fields:
# Verify project
curl --http1.1 -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" -H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/project/$PROJECT_KEY" | jq '{key, name, id}'# List available issue types for the project
curl --http1.1 -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" -H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/project/$PROJECT_KEY/statuses" | jq '.[].name'
If the project or issue type is invalid, report the error and ask the user to correct it.
Phase 5 — Create the Ticket
curl --http1.1 -s -X POST \
-u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
-H "Content-Type: application/json" \
"$JIRA_BASE_URL/rest/api/3/issue" \
-d '{
"fields": {
"project": { "key": "PROJECT_KEY" },
"summary": "Ticket summary here",
"issuetype": { "name": "Task" },
"priority": { "name": "Medium" },
"description": { ADF_OBJECT },
"labels": ["label1", "label2"]
}
}'
Extract the response:
# Parse response for issue key and URL
ISSUE_KEY=$(echo "$RESPONSE" | jq -r '.key')
ISSUE_URL="$JIRA_BASE_URL/browse/$ISSUE_KEY"
If the API returns an error, display the error message and suggest corrections.
Phase 6 — Report
Present the result to the user:
- Issue key: e.g.
ENG-1234
- URL: direct link to the ticket
- Summary: the title that was set
- Research included: yes/no, with sources listed
Notes
- The Jira REST API v3 requires ADF for descriptions — plain text or markdown will be rejected.
- Rate limits: Jira Cloud allows ~100 requests per minute per user.
- The
jira.yaml network policy preset in NemoClaw already allows *.atlassian.net, auth.atlassian.com, and api.atlassian.com on port 443.
- To use this skill inside NemoClaw's sandbox, enable the Jira preset in your sandbox policy.
Examples
# Create a simple task
/jira-ticket ENG "Update API rate limiting docs"# Create a bug with web research
/jira-ticket ENG --type Bug --search "Node.js fetch timeout ECONNRESET" "Fix intermittent ECONNRESET in payment service"
# Create a story with priority and labels
/jira-ticket PLATFORM --type Story --priority High --labels "q2,backend" "Add OAuth2 PKCE flow for mobile clients"