SuperAPI AI Directory

boards-query

Office & productivity

View repository

Updated 10-15 21:11

About this skill

Work item queries (WIQL and saved queries)

This Skill only reads: it executes the conditions provided by the user or a saved query, then presents the results using the query's own fields. For fixed-format "My work" reports, use boards-my-workinstead; to modify the work items found, use boards-work-item-write。

Project selection

  • If the user provides a project name (for example, "Contoso project"), use it directly and do not call the project list API.

  • If not provided, ask the user to provide it once.

  • If still not provided, list the projects for the user to choose from:

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/_apis/projects?%24top=500&api-version=7.1"
    
  • Do not continue until the user provides or selects a project.

Teamis optional: only include the team in the URL when the query uses @CurrentIteration, and the user is not referring to the project's default team ({project}/{team}/_apis/...). If the user does not mention a team, omit it; in that case @CurrentIteration resolves against the project's default team.

Connection and authentication

Always use curl to call the Azure DevOps REST API directly, with authentication parameters included in each command.

  • Organization: read the environment variable AZURE_DEVOPS_ORG(organization name, for example contoso). If it is not set, ask the user once; if the user provides a URL, extract the organization name from https://dev.azure.com/{org} or https://{org}.visualstudio.com .
  • Token: send the PAT with Basic authentication:-u ":$AZURE_DEVOPS_PAT"; if only AZURE_DEVOPS_EXT_PATis set (the variable used by the Azure CLI azure-devops extension), use that instead. When using a Microsoft Entra ID token instead, switch to -H "Authorization: Bearer $AZURE_DEVOPS_TOKEN". If neither is set, ask the user to set AZURE_DEVOPS_PAT in their own terminal and retry, then stop. Read tokens only from environment variables: do not ask the user to paste tokens into the conversation, and do not print or write them to files.
  • PAT permission scopes:Work Items (Read)、Project and Team (Read)。
  • Encoding: URL-encode the project, team name, and query path in the path (including folder and query names containing Chinese), as well as keywords for query searches (write spaces as %20); in the query string, write $ as %24(for example %24top) to avoid shell expansion.
  • Errors: HTTP 401, 403, 203, or an HTML login page response means the token is invalid, expired, or lacks permissions; report it and stop. HTTP 404 means the organization, project, team, or query path is incorrect. The message of an HTTP 400 will point out the problem with the WIQL (for example, the TF51005 field does not exist, or theVS403721 team has no current Iteration scheduled); show the original text to the user and help fix it.
  • Windows PowerShell: call curl.exe(not the curl alias), and write the environment variable as $env:AZURE_DEVOPS_PAT; PowerShell does not support <<'EOF', so first write the JSON body to a temporary file, then send it with --data-binary "@body.json" .

WIQL quick reference

Requirement Syntax
Current user [System.AssignedTo] = @Me
Project in URL [System.TeamProject] = @project
Relative dates [System.ChangedDate] >= @Today - 7; also @StartOfWeek、@StartOfMonth
Team's current, previous sprint [System.IterationPath] = @CurrentIteration、@CurrentIteration - 1(the team is determined by the URL)
Team's area [System.AreaPath] IN (@TeamAreas('[Contoso]\\Contoso Team'))
Below hierarchy [System.AreaPath] UNDER 'Contoso\\Web'
Requirement level type [System.WorkItemType] IN GROUP 'Microsoft.RequirementCategory'
Text [System.Title] CONTAINS WORDS 'login'; tag [System.Tags] CONTAINS 'api'
  • Link queryUse FROM WorkItemLinks, conditions are divided into [Source].、[Target]. and [System.Links.LinkType], and finally add the mode:
    • MODE (Recursive): tree (queryType is tree), can only be combined with System.LinkTypes.Hierarchy-Forward。
    • MODE (MustContain): direct link (queryType is oneHop), only keeps sources that have targets matching the conditions.
  • Strings in WIQL use single quotes, backslashes in JSON are written as \\; always use heredoc for the body.
  • Query results are capped at 20,000 items; exceeding it will besilently truncated, with no error returned; WIQL itself is capped at 32,000 characters. When the count is exactly at the limit, remind the user that the results may be incomplete and suggest adding conditions.

Rules

1. Run an ad-hoc WIQL

  1. Write the user's requirement as WIQL,SELECT list the fields to display, and add ORDER BY. Show the WIQL to the user before executing.

  2. Execute (when there is a team, change the URL to {project}/{team}/_apis/wit/wiql):

    curl -sS -u ":$AZURE_DEVOPS_PAT" -X POST -H "Content-Type: application/json" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wit/wiql?%24top=200&api-version=7.1" \
      --data-binary @- <<'EOF'
    {"query": "SELECT [System.Id], [System.Title], [System.State], [System.AssignedTo] FROM WorkItems WHERE [System.TeamProject] = @project AND [System.WorkItemType] = 'Bug' AND [System.ChangedDate] >= @Today - 7 ORDER BY [System.ChangedDate] DESC"}
    EOF
    

    %24top=200 first fetch the first 200 items; remove it when the user wants all of them (still subject to the 20,000 item limit). For link queries, %24top counts the rows of workItemRelations , which cuts off the tree; do not add it unless the result is very large.

  3. Fill in the data and present it according to "Getting field values" below.

Example: "Query Bugs changed in the last 7 days in the Contoso project", "List the tree of all child items under Feature 101"

Link query example (each Feature and all its child items at every level):

{"query": "SELECT [System.Id], [System.Title], [System.State] FROM WorkItemLinks WHERE ([Source].[System.TeamProject] = @project AND [Source].[System.WorkItemType] = 'Feature') AND ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward') AND ([Target].[System.TeamProject] = @project) MODE (Recursive)"}

2. Find and run a saved query

  1. When the user gives a full path (for example "Shared Queries/Sprint/Active Bugs"), use it directly; each segment of the path must be URL-encoded:

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wit/queries/Shared%20Queries/{folder}/{name}?%24expand=wiql&api-version=7.1"
    

    The response has id、queryType(flat、tree、oneHop) and wiql. The root folders are Shared Queries(shared queries) and My Queries(my queries, only the token owner's own are visible).

  2. When only a name or keyword is given, search by name:

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wit/queries?%24filter={keyword}&%24expand=minimal&%24top=50&api-version=7.1"
    

    When multiple are found, list path for the user to choose.

  3. To browse the list, get the query tree (%24depth max 2;hasChildren is true but has no children folder, then expand with that folder path plus ?%24depth=2 ):

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wit/queries?%24depth=2&%24expand=minimal&api-version=7.1"
    

    isFolder is true are folders, the rest are queries.

  4. Run a query by ID (when the query uses @CurrentIteration and the user specifies a team, add to the URL {team}):

    curl -sS -u ":$AZURE_DEVOPS_PAT" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wit/wiql/{queryId}?api-version=7.1"
    

    You can also add &%24top=200. The response format is the same as rule 1.

  5. Fill in the data and present it according to "Getting field values" below; in the title, note the query's path。

Example: "Run the shared query 'Active Bugs'", "List which shared queries the Contoso project has"

Getting field values

WIQL only returns IDs; field values must be fetched separately:

  1. Collect IDs:queryResultType is workItem take workItems[].id; is workItemLink when taking workItemRelations[] of source.id and target.id(remove duplicates). If there are no IDs, state that there are no matching work items, then stop.

  2. The field uses the response columns[].referenceName(that is, the queried SELECT field), with at most 200 IDs each time; if more, split into batches:

    curl -sS -u ":$AZURE_DEVOPS_PAT" -X POST -H "Content-Type: application/json" \
      "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/wit/workitemsbatch?api-version=7.1" \
      -d '{"ids":[101,102],"fields":["System.Id","System.Title","System.State","System.AssignedTo"],"errorPolicy":"Omit"}'
    

    Fields with empty values do not appear in fields , and are displayed as blank. Identity fields (for example, System.AssignedTo) are objects; display displayName。

  3. in the order returned by WIQL (that is the result of ORDER BY ); batch responses are sorted by ID and do not preserve the requested order.

Present the results

  • First display the executed WIQL or query path, and the count (when there is %24top or the 20,000 item limit is reached, note that there may be more).
  • General query: present as a table, with fields and order according to columns[](use columns[].namefor headers). The ID is a clickable link [{ID}](https://dev.azure.com/{organization}/{project}/_workitems/edit/{ID})({project} must be URL-encoded); dates are displayed as YYYY/MM/DD, times are converted to the user's local time zone, and UTC is indicated when it cannot be determined.
  • Tree query:source is null ; rows that are root nodes, and the subsequent rows whose source.id points to them are child items; output in the order of workItemRelations[] , indicating the level before the title column with indentation or └─ .
  • Direct link query: one row per source, with matching targets listed indented below, noting the link type (rel)。