Skip to main content

Manage governance workflow approvals (Inbox)

Connect docs via MCP

Use client.inbox in the Atlan Python SDK to programmatically inspect and bulk-approve or bulk-reject governance workflow tasks—the items you see in Atlan's Inbox.

Requires the Governance Workflows and Inbox feature

This system is enabled per tenant via Admin → Labs → Governance Workflows and Inbox. When it's on, new requests are handled by governance workflows and appear in the Inbox; the classic Requests module continues to hold any older requests. For the classic module, see Manage requests. A tenant can have items in both systems at the same time.

Understand three identifiers

Working with the Inbox involves three different GUIDs—knowing which one to use where saves a lot of confusion:

IdentifierWhat it meansWhere to use it
Task GUIDthe Inbox item itself (a Task asset)group_key in approve_all / reject_all to action that one task
Related-asset GUIDthe asset the request targetsgroup_key to action every pending task on that asset in one call
Workflow-request GUIDthe underlying approval recordclient.inbox.get() only—the detail view with status and approver routing
Finding the workflow-request GUID

The workflow-request GUID isn't a top-level task field—it's embedded in the task's task_actions fulfillment URL (.../approval-workflow-requests/<guid>). The discovery example below shows how to extract it. Passing a task GUID to get() fails—only the workflow-request GUID works there.

Discover pending tasks

Inbox tasks are Task assets, so you list them with a regular search:

List pending Inbox tasks
import re

from pyatlan.client.atlan import AtlanClient
from pyatlan.model.assets import Task
from pyatlan.model.fluent_search import CompoundQuery, FluentSearch

client = AtlanClient()

search = (
FluentSearch()
.where(CompoundQuery.active_assets())
.where(CompoundQuery.asset_type(Task)) # (1)
.include_on_results(Task.TASK_RECIPIENT) # (2)
.include_on_results(Task.TASK_EXECUTION_ACTION) # (3)
.include_on_results(Task.TASK_RELATED_ASSET_GUID)
.include_on_results(Task.TASK_ACTIONS)
).to_request()

for task in client.asset.search(search):
if task.task_execution_action != "PENDING":
continue
wf_request_guid = None
if task.task_actions: # (4)
match = re.search(
r"approval-workflow-requests/([0-9a-f-]{36})",
str(task.task_actions[0].task_action_fulfillment_url),
)
wf_request_guid = match.group(1) if match else None
print(task.guid, task.task_recipient, task.task_related_asset_guid, wf_request_guid)
  1. Inbox items are assets of type Task.
  2. The recipient is the user the task is waiting on—only this identity can action the task (see the warning below).
  3. Execution state: PENDING, APPROVED, REJECTED, or WITHDRAWN.
  4. Extracts the workflow-request GUID for use with client.inbox.get().

Inspect workflow request

To see a request's status and its approver routing:

Get a workflow request
request = client.inbox.get(guid=wf_request_guid) # (1)
print(request.status, request.approval_workflow_request_type)
print(request.approval_details) # (2)
  1. Use the workflow-request GUID (not the task GUID).
  2. approval_details shows the configured approvers and each one's decision—useful for understanding who a pending task is waiting on.

Bulk-approve or reject tasks

Approvals and rejections are group operations: you name a group with group_key, and every pending task in that group (addressed to you) is actioned in a single server-side call.

Approve one task, or all tasks on an asset
# a task GUID actions exactly that one task
response = client.inbox.approve_all(
group_key="24be8e31-4857-4f1a-b9e9-281db6c9f934", # (1)
comment="Approved via automation",
)
print(response.total_tasks) # 1

# an asset GUID actions EVERY pending task on that asset
response = client.inbox.approve_all(
group_key="48056772-a24d-4643-a880-affec0164e9f", # (2)
sub_type="DATA_ACCESS", # (3)
comment="Bulk approved",
)
print(response.total_tasks) # e.g. 2
  1. group_key = task GUID → a group of one.
  2. group_key = related-asset GUID → all pending tasks on that asset at once.
  3. Optionally narrow by task sub-type: DATA_ACCESS, CHANGE_MANAGEMENT, PUBLICATION_MANAGEMENT, or POLICY_APPROVAL (see ApprovalWorkflowRequestType). Use reject_all() with the same arguments to reject.
Processing is asynchronous

A successful call means the tasks were queued (total_tasks tells you how many). The state change lands a few seconds later—re-query the tasks and check task_execution_action if you need confirmation.

Who can action tasks

Bulk actions are strictly recipient-scoped

Only the user a task is addressed to (its task_recipient) can approve or reject it. An admin role doesn't override this. If none of a group's pending tasks are addressed to your token's identity, the API responds with error 1003 ("No pending tasks found for the specified group") even when the group visibly contains pending tasks for someone else. The same error also appears when every task in the group has already been actioned; check task_execution_action to tell the two cases apart.

Automation requires the approver to be your token's identity

The governance workflow builder currently supports only human users and groups as approvers—an API key's or OAuth client's service account can't be named as an approver. That means Inbox approvals can only be automated with a token whose identity is a configured approver (for example, a user bearer token). Note that user session tokens are short-lived (~15 minutes), so they aren't a durable path for unattended automation. If you need headless Inbox approval, raise this with your Atlan contact—supporting service accounts as workflow approvers is a known product ask.

Good to know

  • Async client: every method is also available on AsyncAtlanClient. Use await client.inbox.approve_all(...).
  • A requester can't approve their own request unless the workflow's approver configuration routes it back to them.
  • get() with an unknown GUID currently returns a server error rather than None; treat errors from get() as "not a workflow-request GUID."
Was this page helpful?