M365 Planner Skill
Manage Microsoft 365 Planner through Microsoft Graph API.
What's New in v1.2.3
- 🌍 English Documentation – Complete translation for international ClawHub availability
- 🔧 Portability – Env path now uses
os.homedir()instead of hardcoded paths - 🧹 Security Cleanup – Full audit for sensitive data (no IDs, names, domains)
- 📦 ClawHub-ready – Tarball created, node_modules excluded
What's New in v1.2.2
- 🔧 Portability – Env path now uses
os.homedir()instead of hardcoded/home/claw/.openclaw/.env - 🧹 Security Cleanup – Full audit for sensitive data (no IDs, names, domains)
- 📦 ClawHub-ready – Tarball created, node_modules excluded
What's New in v1.2.1
- ✅ Generic Scripts – No hardcoded Group-IDs or Plan names anymore
- ✅ Command-Line Parameters – All scripts accept IDs as arguments
- ✅ List Plans Improved – Shows all groups when no ID provided
- ✅ Flexible Cleanup – Works with any plans/buckets
- ✅ ClawHub-ready – No project-specific data included
What's New in v1.1.0
- ✅ Node.js Scripts – Standalone scripts without
mgcCLI - ✅ If-Match Header Support – Correct ETag handling for updates/deletes
- ✅ Group-Based API – Direct access via M365 Group-ID
- ✅ Recurring Tasks – Note about native Planner recurrence feature
- ✅ Cleanup Scripts – Automated task cleanup
Prerequisites
- Azure AD App Registration (see Setup below)
- Node.js v18+ with
@microsoft/microsoft-graph-clientandaxios - M365 Group (not Security Group or Distribution List!)
Quick Start
# Test connection
node scripts/test-connection.js
# List all plans
node scripts/list_plans.js
# List plans for specific group
node scripts/list_plans.js <group-id>
# Create plan
node scripts/create_plan.js "Project Name" <group-id>
# Create task
node scripts/create_task.js <plan-id> <bucket-id> "Task Title"
# Delete completed tasks
node scripts/cleanup_verlaengerungen.js <group-id> "<plan-name>" "<bucket-name>"
Setup: Azure AD App Registration
Step 1: Create App Registration
Azure Portal:
- https://portal.azure.com → Azure Active Directory → App registrations
- "New registration"
- Name:
M365-Planner-Integration - Supported account types:
Accounts in this organizational directory only - Redirect URI: None (Client Credentials Flow)
Or via Azure CLI:
az login
az ad app create --display-name "M365-Planner-Integration" --sign-in-audience "AzureADMyOrg"
Note the Application (client) ID from the output.
Step 2: Add API Permissions
Important: Use Application Permissions (not Delegated)!
Azure Portal:
- App → API permissions → Add a permission
- Microsoft Graph → Application permissions
- Add:
Group.Read.All(not Group.ReadWrite.All – sufficient for Planner)Tasks.ReadWrite.All
- Grant Admin Consent: Click "Grant admin consent for [Tenant]"!
Or via Azure CLI:
APP_ID="your-app-id"
# Group.Read.All
az ad app permission add \
--id $APP_ID \
--api 00000003-0000-0000-c000-000000000000 \
--api-permissions 5b567253-7703-48e2-861c-caed61531407=Role
# Tasks.ReadWrite.All
az ad app permission add \
--id $APP_ID \
--api 00000003-0000-0000-c000-000000000000 \
--api-permissions bdfbf15f-ee85-495a-99a9-ef9b2abb1dcb=Role
# Admin Consent
az ad app permission admin-consent --id $APP_ID
Step 3: Create Client Secret
Azure Portal:
- App → Certificates & secrets → Client secrets → New client secret
- Description:
OpenClaw Integration - Expires: 24 months (Maximum)
- Copy values immediately! – Only shown once
Or via Azure CLI:
az ad app credential reset \
--id $APP_ID \
--append \
--display-name "OpenClaw Integration"
Step 4: Configure Environment
Store credentials in ~/.openclaw/.env:
# Microsoft 365 Planner Credentials
M365_CLIENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
M365_CLIENT_SECRET="your-secret-value"
M365_TENANT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Secure permissions:
chmod 600 ~/.openclaw/.env
Step 5: Test Connection
node scripts/test-connection.js
Expected output:
✅ Access Token successfully received!
📋 Test: M365 Groups...
3 groups found:
- My Team ✅ M365/Planner-capable
✅ Connection successful!
Important Notes
M365 Groups vs. Security Groups
Planner ONLY works with M365 Groups!
- ✅ M365 Group – Has Exchange mailbox, Teams, Planner (recognizable by mail attribute)
- ❌ Security Group – Only for permissions, no Planner
- ❌ Distribution List – Only for email distribution, no Planner
Check groups:
node scripts/test-connection.js
Shows all groups with status "✅ M365/Planner-capable".
Create M365 Group (if none exists):
- Microsoft 365 Admin Center → Groups → Add a group
- Or Teams: Create new team (automatically creates M365 Group)
If-Match Header (ETag)
All update and delete operations require the If-Match header!
Planner uses Optimistic Concurrency Control. Requests fail without ETag.
Delete Example:
// Wrong ❌
await client.api(`/planner/tasks/${taskId}`).delete();
// Correct ✅
const task = await client.api(`/planner/tasks/${taskId}`).get();
await client.api(`/planner/tasks/${taskId}`)
.headers({ 'If-Match': task['@odata.etag'] })
.delete();
Update Example:
const task = await client.api(`/planner/tasks/${taskId}`).get();
await client.api(`/planner/tasks/${taskId}`)
.headers({ 'If-Match': task['@odata.etag'] })
.update({ percentComplete: 50 });
Group-Based API Endpoints
Do NOT use:
GET /planner/plans ❌ (requires complex filter)
Use:
GET /groups/{group-id}/planner/plans ✅
Example:
const plans = await client.api(`/groups/${groupId}/planner/plans`).get();
Recurring Tasks
Microsoft Planner supports native recurring tasks!
In Planner Web UI or Mobile App:
- Open task
- Click "Repeat"
- Choose frequency: Daily, Weekly, Monthly, Yearly, Custom
Example:
- "Domain renewal example.com" → Repeat yearly
- "Check backup" → Repeat weekly
⚠️ API Limitation: The Graph API does not support creating recurring tasks directly. Recurring tasks must be set up via Planner UI.
Common Operations
Plans
| Operation | Script |
|---|---|
| List all plans | node scripts/list_plans.js |
| Create plan | node scripts/create_plan.js <name> <group-id> |
| Delete plan | node scripts/delete_plan.js <plan-id> |
Buckets
| Operation | Script |
|---|---|
| List buckets | Integrated in list_plans.js |
| Create bucket | node scripts/create_bucket.js <plan-id> <name> |
| Delete bucket | node scripts/delete_bucket.js <bucket-id> |
Tasks
| Operation | Script |
|---|---|
| List tasks | Integrated in list_plans.js |
| Create task | node scripts/create_task.js <plan-id> <bucket-id> <title> |
| Update task | node scripts/update_task.js <task-id> --percent-complete 50 |
| Delete task | node scripts/delete_task.js <task-id> |
| Cleanup | node scripts/cleanup_verlaengerungen.js <group-id> "<plan-name>" "<bucket-name>" |
Helper Scripts
test-connection.js
Tests connection to Microsoft Graph:
- Request access token
- Display tenant information
- List available M365 Groups
- Check Planner capability
node scripts/test-connection.js
list_plans.js
Shows all plans in an M365 Group with:
- Buckets and their tasks
- Task status (completed/in progress/open)
- Percentage progress indicator
# Without argument: Shows all available groups
node scripts/list_plans.js
# With Group ID: Shows plans for specific group
node scripts/list_plans.js <group-id>
create_plan.js
Creates a new plan with default buckets:
- To Do
- In Progress
- Done
node scripts/create_plan.js "Project Alpha" <group-id>
cleanup_verlaengerungen.js
Cleans up completed tasks from a bucket:
- Deletes tasks with 100% progress
- Keeps open tasks
- Correct If-Match header handling
node scripts/cleanup_verlaengerungen.js <group-id> "<plan-name>" "<bucket-name>"
Example:
node scripts/cleanup_verlaengerungen.js abc-123 "My Project" "Completed"
Troubleshooting
Error: Insufficient privileges
Cause: Admin consent not granted
Solution:
az ad app permission admin-consent --id <app-id>
Or in Azure Portal: API permissions → Grant admin consent
Error: Group not found
Cause: Planner only works with M365 Groups
Solution:
- Check if it's an M365 Group (has mail attribute)
- Security Groups/Distribution Lists don't work
- Create new M365 Group (Teams or Admin Center)
Error: The If-Match header must be specified
Cause: Update/Delete without ETag
Solution:
// First get task for ETag
const task = await client.api(`/planner/tasks/${id}`).get();
// Then update/delete with If-Match header
await client.api(`/planner/tasks/${id}`)
.headers({ 'If-Match': task['@odata.etag'] })
.delete();
Error: This entity set must be queried with a filter
Cause: /planner/plans endpoint requires filter
Solution: Use group-based endpoint:
// Wrong ❌
const plans = await client.api('/planner/plans').get();
// Correct ✅
const plans = await client.api(`/groups/${groupId}/planner/plans`).get();
Error: Cannot find module '@microsoft/microsoft-graph-client'
Cause: Node.js packages not installed
Solution:
cd ~/.openclaw/workspace/skills/m365-planner
npm install
Dependencies
Install packages locally in skill directory:
cd ~/.openclaw/workspace/skills/m365-planner
npm install @microsoft/microsoft-graph-client axios
References
- Planner API Overview
- Setup Guide
- Common Patterns
- Microsoft Graph API Docs
- Planner REST API Reference
Changelog
v1.2.3 (2026-04-18)
- 🌍 English Documentation – Complete translation for international ClawHub availability
- 🔧 Portability – Env path uses
os.homedir()for cross-system compatibility - 🧹 Security Audit – No hardcoded IDs, names, or domains
v1.2.2 (2026-04-18)
- 🔧 Portability – Env path now uses
os.homedir()instead of hardcoded/home/claw/.openclaw/.env - 🧹 Security Cleanup – Full audit for sensitive data (no IDs, names, domains)
- 📦 ClawHub-ready – Tarball created, node_modules excluded
v1.2.1 (2026-04-18)
- ✅ Generic Scripts – No hardcoded Group-IDs or Plan names anymore
- ✅ Command-Line Parameters – All scripts accept IDs as arguments
- ✅ List Plans Improved – Shows all groups when no ID provided
- ✅ Flexible Cleanup – Works with any plans/buckets
- ✅ ClawHub-ready – No project-specific data included
v1.1.0 (2026-04-17)
- ✅ Node.js Scripts instead of mgc CLI
- ✅ If-Match Header Support for updates/deletes
- ✅ Group-based API Endpoints
- ✅ Test-Connection Script with M365 Group Detection
- ✅ List Plans Script with Bucket/Task overview
- ✅ Cleanup Script for completed tasks
- ✅ Documentation for recurring tasks (native Planner feature)
- ✅ Troubleshooting Section expanded
v1.0.0 (2023-01-19)
- Initial version with mgc CLI
- Azure AD Setup Guide
- Basic CRUD operations