As posted a few months ago, Microsoft has modernized the Planner task comments with chat-based comments. These new comments support @mention, rich-text formatting, and other integrations like Loop components, but (unfortunately) no screenshots, now in all Planner plans.
Users can now fully manage the new chat-based comments via Microsoft Graph.
I first checked this in March, when the new comments were available in my tenant. There was an internal message endpoint, but I could not find a Graph endpoint. In the meantime, the Graph endpoint plannerTaskChatMessage is available.
The new chat-based comments can now be listed, created, updated, and deleted, and reactions can be added to them using a personal account. Currently, the endpoint is limited to delegated permissions, so a personal account is required instead of an app. Overall, this endpoint is already very good. The missing app permissions are the only notable limitation.
For my demo, I have a budget task with new, empty task comments.

I prepared 8 PowerShell samples that cover almost all operations for the new task message endpoint.
The task ID is always required to work with comments. To start, load the task details with PowerShell.
Import-Module Microsoft.Graph.Authentication
Connect-MgGraph -Scopes Tasks.ReadWrite
$PlannerID = "<PlanID>"
$TaskName = "Budget 2027"
$Url = "https://graph.microsoft.com/beta/planner/plans/$PlannerID/tasks"
$PlannerTasks = Invoke-MgGraphRequest -Method Get -Uri $Url
$Task = $PlannerTasks.value | ?{$_.title -eq $TaskName }Content
1) Adding a new plain text comment
The simplest comment is straightforward to add, see Create.
$Body = @"
{
"content": "This is a new task comment added via Microsoft Graph API"
}
"@
$Url = "https://graph.microsoft.com/beta/planner/tasks/$($Task.id)/messages"
$TaskMessage = Invoke-MgGraphRequest -Method Post -Uri $Url -Body $Body -ContentType "application/json"
$TaskMessage
Successfully added.

2) Adding a new rich text comment
Rich text comments follow the same structure as plain text comments, with HTML formatting applied to the comment body.
$Body = @"
{
"content": "<div>This is a new task comment added via Microsoft Graph API. Visit <a href=\"https://blog-en.topedia.com\">Topedia Blog</a> for more information.</div>"
}
"@
$Url = "https://graph.microsoft.com/beta/planner/tasks/$($Task.id)/messages"
$TaskMessage = Invoke-MgGraphRequest -Method Post -Uri $Url -Body $Body -ContentType "application/json"
$TaskMessage
Added without an issue.

3) Adding a new comment and mentioning one user
Another variant: a rich text comment mentioning one user.
Three notes:
- The mentioned user must be a member of the plan; otherwise, the endpoint returns an error.

- The user object ID from Entra ID is required; nothing else.
- For @mention, the position number is important to understand. The position marks where the user is mentioned. With a single user, the position is always 0 (= first position).
The @mention syntax always uses the Skype schema in HTML format, where the item ID corresponds to the mention index position in the comment body.
<span itemid=\"0\" itemtype=\"https://schema.skype.com/Mention/Person\"></span>
Now, adding a new comment is straightforward.
In my sample, the position parameter and the item ID both use index 0. These two values are linked.
$MentionedUserId = "c0c96496-8623-4953-afea-f535f78a1cf1" # Replace with actual user Entra ID object ID
$BodyWithMention = @"
{
"content": "
<div>This is a new task comment added via Microsoft Graph API.<br>
<span itemid=\"0\" itemtype=\"https://schema.skype.com/Mention/Person\"></span> Visit <a href=\"https://blog-en.topedia.com\">Topedia Blog</a> for more information.</div>",
"mentions": [
{
"mentioned": "$MentionedUserId",
"mentionType": "user",
"position": 0
}
]
}
"@
$Url = "https://graph.microsoft.com/beta/planner/tasks/$($Task.id)/messages"
$TaskMessage = Invoke-MgGraphRequest -Method Post -Uri $Url -Body $BodyWithMention -ContentType "application/json"
Comment added as expected.

4) Adding a new comment and mentioning multiple users
Another variant: a comment mentioning two or more users.
The index marks the position where each user is mentioned: 0 is the first user, 1 the second, 2 the third, and so on. For multiple users, both the item ID and the position parameter must be updated and kept in sync.
$MentionedUserId1 = "c0c96496-8623-4953-afea-f535f78a1cf1"
$MentionedUserId2 = "76c348e6-fe71-47cc-9f07-f571c8072ebb"
$BodyWithMention = @"
{
"content": "
<div>This is a new task comment added via Microsoft Graph API.<br>
<span itemid=\"0\" itemtype=\"https://schema.skype.com/Mention/Person\"></span> Visit <a href=\"https://blog-en.topedia.com\">Topedia Blog</a> for more information.</div><br>
CC <span itemid=\"1\" itemtype=\"https://schema.skype.com/Mention/Person\"></span>",
"mentions": [
{
"mentioned": "$MentionedUserId1",
"mentionType": "user",
"position": 0
},
{
"mentioned": "$MentionedUserId2",
"mentionType": "user",
"position": 1
}
]
}
"@
$Url = "https://graph.microsoft.com/beta/planner/tasks/$($Task.id)/messages"
$TaskMessage = Invoke-MgGraphRequest -Method Post -Uri $Url -Body $BodyWithMention -ContentType "application/json"Comment added as expected.

5) Adding reactions to a comment
All official emojis from Teams messages are available for comments. The internal type is required.
The following requirements:
- Type must be submitted without spaces.
- Type must be submitted in lowercase.
- Only one reaction can be added or removed per request.
Below is a sample. You need the name, which is the reaction type.

Adding a reaction to my previous comment, see setReaction.
$Body = @"
{
"reactionType": "thewave1"
}
"@
$Url = "https://graph.microsoft.com/beta/planner/tasks/$($Task.id)/messages/$($TaskMessage.id)/setReaction"
Invoke-MgGraphRequest -Method Post -Uri $Url -Body $Body -ContentType "application/json"
My wave reaction was added.

If the internal type is unknown, add a reaction manually in the Planner UI and use sample 6 to list all comments. The existing reactions are listed by type, including who added them and when.

6) Listing all comments
At least one comment must exist before listing is possible, as the system creates the associated chat thread with the first comment.

Retrieving all task comments, including paging; see list messages.
$Url = "https://graph.microsoft.com/beta/planner/tasks/$($Task.id)/messages"
$AllTaskMessages = @()
do {
$Response = Invoke-MgGraphRequest -Method Get -Uri $Url
$AllTaskMessages += $Response.value
$Url = $Response.'@odata.nextLink'
} while ($Response.'@odata.count' -ne 0)
$AllTaskMessages7) Updating a comment
The existing comment is overwritten with the updated text. To do so, retrieve the message ID of the target comment and submit a PATCH request with the new content, see update message.
$TaskMessage = $AllTaskMessages | ?{ $_.content -eq "This is a new task comment added via Microsoft Graph API" }
$Body = @"
{
"content": "<div>This is a new task comment added via Microsoft Graph API.<br>
<br>
<b>Updated message</b><br>
FYI to mention <span itemid=\"0\" itemtype=\"https://schema.skype.com/Mention/Person\"></span></div>",
"mentions": [
{
"mentioned": "$MentionedUserId1",
"mentionType": "user",
"position": 0
}
]
}
"@
$Url = "https://graph.microsoft.com/beta/planner/tasks/$($Task.id)/messages/$($TaskMessage.id)"
$TaskMessage = Invoke-MgGraphRequest -Method Patch -Uri $Url -Body $Body -ContentType "application/json"
Comment has been updated.

8) Deleting a comment
List all comments to identify the correct one, then delete it using the message ID, see delete message.
# Filter messages to find the one from 21:23 (using createdDateTime as a reference)
$TaskMessage = $AllTaskMessages | ? {
$_.createdDateTime -and ([DateTime]$_.createdDateTime).ToString("yyyy-MM-ddTHH:mm") -eq "2026-05-28T19:23"
}
# Delete the comment
$Url = "https://graph.microsoft.com/beta/planner/tasks/$($Task.id)/messages/$($TaskMessage.id)"
Invoke-MgGraphRequest -Method Delete -Uri $Url
Comment from 21:23 has been deleted.

Note that deleting a comment does not remove it entirely.
The comment remains visible in the task (not for the user), it’s tagged as deleted, but the content is removed.

