# Asana API Operations to Create, Update, and Find Subtasks: A Go Implementation Guide

> Learn how to create, update, and find Asana subtasks using Go. Explore the `client.CreateTask`, `subtask.Update`, and `task.Subtasks` operations within a practical GitHub Action implementation.

- Repository: [Keita Kitamura/github-asana-request-review-action](https://github.com/keitap/github-asana-request-review-action)
- Tags: api-reference
- Published: 2026-03-05

---

**TLDR:** The `keitap/github-asana-request-review-action` uses `client.CreateTask` to create subtasks, `subtask.Update` to update them, and `task.Subtasks` to find them, wrapped in three helper functions defined in [`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go).

Managing code review workflows between GitHub and Asana requires precise subtask operations through the Asana API. The open-source `keitap/github-asana-request-review-action` implements dedicated Go functions to create, update, and find subtasks using the official Asana Go SDK. This guide breaks down the specific API operations and implementation details found in the source code.

## Creating Subtasks with client.CreateTask

The action creates review subtasks via the `AddCodeReviewSubtask` function defined at lines 73-86 of [`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go). This function constructs a `CreateTaskRequest` struct containing the parent task ID, assignee, followers, due date, and formatted HTML notes.

### The AddCodeReviewSubtask Implementation

```go
func AddCodeReviewSubtask(client *asana.Client, taskID string, prID int,
    requester *Account, reviewer *Account, dueDate asana.Date,
    pr *github.PullRequestEvent) (*asana.Task, error) {
    req := &asana.CreateTaskRequest{
        Parent:    taskID,
        Assignee:  reviewer.AsanaUserGID,
        Followers: []string{requester.AsanaUserGID},
        TaskBase: asana.TaskBase{
            Name:      fmt.Sprintf(`✍️ Code review: #%d %s`, prID, reviewer),
            HTMLNotes: createReviewRequestDescText(requester, pr),
            DueOn:     &dueDate,
        },
    }
    return client.CreateTask(req)
}

```

## Updating Subtasks with subtask.Update

To modify existing subtasks, the action uses `UpdateCodeReviewSubtask` at lines 88-96 of [`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go). This function sends an `UpdateTaskRequest` to modify specific fields without affecting other subtask properties.

### The UpdateCodeReviewSubtask Function

```go
func UpdateCodeReviewSubtask(client *asana.Client,
    subtask *asana.Task, requester *Account,
    pr *github.PullRequestEvent) error {
    update := &asana.UpdateTaskRequest{
        TaskBase: asana.TaskBase{
            HTMLNotes: createReviewRequestDescText(requester, pr),
        },
    }
    return subtask.Update(client, update)
}

```

## Finding Subtasks with task.Subtasks

The search operation uses `FindSubtaskByName` at lines 98-115 of [`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go). This function retrieves up to 100 subtasks from a parent task and filters them by name substring.

### The FindSubtaskByName Logic

```go
func FindSubtaskByName(client *asana.Client,
    taskID string, findString string) (*asana.Task, error) {
    task := &asana.Task{ID: taskID}
    subtasks, _, err := task.Subtasks(client, &asana.Options{Limit: 100})
    if err != nil {
        return nil, err
    }
    for _, s := range subtasks {
        if strings.Contains(s.Name, findString) {
            return s, nil
        }
    }
    return nil, nil
}

```

## Integration with the Main Handler

These helper functions are invoked by the main event handler in [`handler.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/handler.go) when processing GitHub pull request events. The `Account` struct defined in [`account.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/account.go) provides the necessary Asana user GIDs for assignee and follower fields.

## Summary

- **Create**: Uses `client.CreateTask` via `AddCodeReviewSubtask` in [`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go) (lines 73-86) to create subtasks with parent relationships, assignees, and due dates.
- **Update**: Uses `subtask.Update` via `UpdateCodeReviewSubtask` in [`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go) (lines 88-96) to modify HTML notes of existing subtasks.
- **Find**: Uses `task.Subtasks` via `FindSubtaskByName` in [`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go) (lines 98-115) to retrieve and filter subtasks by name substring with a limit of 100 results.
- All operations depend on the `Account` struct from [`account.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/account.go) for user GID management.

## Frequently Asked Questions

### Which Asana API operations are used to create, update, and find subtasks?

The action uses `client.CreateTask` for creation, `subtask.Update` for updates, and `task.Subtasks` for retrieval. These are wrapped in the `AddCodeReviewSubtask`, `UpdateCodeReviewSubtask`, and `FindSubtaskByName` functions respectively, all defined in [`asana.go`](https://github.com/keitap/github-asana-request-review-action/blob/main/asana.go).

### How does the action prevent duplicate review subtasks?

Before creating a new subtask, the code calls `FindSubtaskByName` to search existing subtasks by reviewer login name. If a matching subtask exists, the action updates it rather than creating a duplicate.

### What parameters are required when creating a code review subtask?

The `AddCodeReviewSubtask` function requires the Asana client, parent task ID, PR number, requester account, reviewer account, due date, and the pull request event object. These parameters populate the `CreateTaskRequest` struct with assignee GIDs, follower IDs, and formatted task metadata.

### How does the UpdateCodeReviewSubtask function handle partial updates?

It constructs an `UpdateTaskRequest` containing only the `HTMLNotes` field in the `TaskBase` struct. The Asana SDK's `subtask.Update` method sends this partial object, leaving other fields unchanged.