workbench Docs

Other services

Asana

Connect Asana so an agent can create, read, update, complete, and comment on tasks across projects.

The Asana integration covers the task loop. It can find a project, list or create tasks in it, read one back by gid, update or complete it, and comment on it. Everything is addressed by gid, so most workflows start with asana_list_projects or asana_search_users.

At a glance#

Plugin idasana
AuthOAuth 2.0
Tools8
Authorization URLhttps://app.asana.com/-/oauth_authorize
Token URLhttps://app.asana.com/-/oauth_token
Proxy basehttps://app.asana.com/api/1.0

Set up the OAuth app#

The console steps are Asana's UI, not this server's

Menu names, labels, and page URLs below come from Asana's console and change without notice. If what you see differs, follow Asana's own documentation — the values this server needs (the callback URL and the scopes in the tables below) are unaffected.

Create the app#

Open app.asana.com/0/my-appsCreate new app. Name it, accept the API terms, create.

Add the redirect URL#

App → OAuth tab → Redirect URLs:

text
https://<your-workbench-host>/api/auth/plugin/asana/callback

Asana permits http for localhost, so add http://localhost:3000/api/auth/plugin/asana/callback for development.

Keep Full permissions#

Leave the app on Full permissions, which is what the default scope maps to. Do not switch it to granular scopes unless you also change the manifest — see the gotcha below.

Copy the credentials#

Same OAuth tab: Client ID, and Client secret via reveal.

Distribute, if others will connect#

Manage Distribution → choose Limited or Public. New apps are private to the creator's account.

Scopes#

ScopeWhat it is for
defaultAsana's full-permissions scope: the token can do anything the connecting user can do

Server configuration#

bash
ASANA_CLIENT_ID=...
ASANA_CLIENT_SECRET=...

Connect#

Portal: Connections → Connect on the Asana card.

Agent:

text
connect({ integration: "asana" })
wait_for_connection({ connectionId })

Tools#

ToolPurpose
asana_list_projectsProjects as { gid, name } rows, optionally scoped to a workspace
asana_list_tasksTasks in a project as slim rows with completion, due date, and assignee
asana_create_taskCreate a task in a project and return its gid
asana_get_taskOne task by gid, notes truncated to 2000 characters, with permalink
asana_update_taskUpdate fields, and complete or reopen via completed
asana_add_commentAdd a plain-text comment (story) to a task
asana_list_teamsTeams in an organization as { gid, name } rows
asana_search_usersResolve users to gids for assignment

Notes and gotchas#

Granular-scope mode must match the manifest exactly

The manifest requests the single scope default. Asana's app settings offer a full-permissions mode and a granular-scope mode, and default belongs to the full-permissions mode. Switching the app to granular scopes while the manifest still requests default fails the authorize call. The reverse fails too. If you need granular scopes, change the manifest to match. Asana's OAuth documentation describes the two modes.

Completing a task is an update, not a separate call: asana_update_task with completed: true. Passing false reopens it.

List tools return 10 rows by default. Raise limit when you expect more, rather than assuming a short list is the whole project.

The server refreshes an expired access token automatically and keeps the existing refresh token when Asana returns none. Token lifetimes are Asana's to set — see Asana's OAuth documentation for the current values.

A 402 response means the endpoint requires a paid Asana plan. Asana also rate-limits per token, and the ceiling depends on the plan. The current figures are in Asana's API documentation.