Install
$ agentstack add skill-microsoft-agent365-skills-add-workiq-tools ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Add WorkIQ Tools (A365 CLI + SDK)
> Trigger phrases — any of these will activate this skill automatically: > - "add workiq tools to this agent" > - "add work intelligence tools" > - "give this agent access to m365 data" > - "give my agent access to email and calendar" > - "add sharepoint access to this agent" > - "add work iq mail to this agent" > - "add work iq calendar to this agent" > - "let this agent read emails and calendar events" > - "wire up workiq MCP servers"
Overview
This skill adds WorkIQ MCP tool servers to an existing A365 agent using the A365 CLI.
WorkIQ tools give your agent pre-built access to M365 work data via MCP. The capability categories below describe what each catalog server does — but always pull the exact CLI argument names from a365 develop list-available. V2 catalog names look like mcp_MailTools, mcp_CalendarTools, etc., and they evolve over time.
- Mail — Read, send, and manage email
- Calendar — Read/create events, check availability
- Teams — Read channel messages, list teams
- SharePoint — Search documents, read files, list sites
- OneDrive — Manage OneDrive files
- Word — Read and write Word documents
- User/Presence — Get user profile and presence
- Copilot — Chat with Microsoft 365 Copilot
- Dataverse and Dynamics 365 — CRUD and domain actions
How it works:
a365 develop list-available— shows the catalog of available MCP serversa365 develop add-mcp-servers— adds selected servers toToolingManifest.json- Agent code is wired to load those tools at runtime via
GetMcpToolsAsync - Permissions are applied separately by a developer or Global Administrator
All changes are additive and idempotent — rerunning is safe.
Phase 0A — Workspace Triage and Detection Cache
Step 1 — Triage the workspace
Run in parallel:
- Glob
**/*.csproj,package.json,requirements.txt,pyproject.toml,src/**/*.ts,**/*.cs,**/*.py→hasProjectFiles. - Read
.a365-workspace-detection.local.json→cacheState(freshifdetectedAt
Options:
- Switch the agent to a supported framework via /agent365:make-ai-teammate.
- (Advanced) Author your own MCP wrapper modeled on the Claude SDK sample's DIY scaffold:
https://github.com/microsoft/Agent365-Samples/blob/main/python/claude/sample-agent/mcptoolregistration_service.py — out of scope for this skill.
Mark all tasks cancelled and end the session. Do **not** proceed to Phase 0C.
---
## Phase 0C — Create and Display Task List
**Show this checklist to the user BEFORE running Phase 1.** Use whichever mechanism the runtime supports — the user must see the list before any CLI command or code edit happens, and items must be updated as work progresses:
- **Claude Code:** call `TaskCreate` for each item below; it's already in `allowed-tools` and renders natively as a checklist with status icons. Use `TaskUpdate` to mark in_progress / completed.
- **VS Code Copilot Chat / GitHub Copilot CLI:** `allowed-tools` is ignored — emit a markdown checklist directly in chat (`- [ ] Detect agent type…`) and edit the list to flip items to `- [x]` as each phase completes.
**Either way: exactly one task in_progress at a time; complete it before moving on.**
TaskCreate: "Detect agent type and check prerequisites" TaskCreate: "Show available WorkIQ tools catalog" TaskCreate: "Add WorkIQ MCP servers via CLI" TaskCreate: "Wire MCP tool service in agent code" TaskCreate: "Offer Word @mention handler (if applicable)" TaskCreate: "Guide permissions handoff" TaskCreate: "Set up dev token for testing" TaskCreate: "Validate build"
---
## Phase 1 — Detect Agent Type and Check Prerequisites
**Mark task in progress: "Detect agent type and check prerequisites"**
### 1.1 Detect agent type
1. **Read** `${CLAUDE_PLUGIN_ROOT}/shared/agent-detection.md` for detection heuristics.
2. Run detection:
- **Glob** `**/*.csproj` + **Grep** `AgentApplication` in `**/*.cs` → .NET AgentFramework
- **Glob** `**/package.json` + `.ts`/`.js` files present → Node.js
- **Glob** `**/*.py` or `requirements.txt` / `pyproject.toml` → Python
3. Load reference patterns:
- If .NET: **Read** `${CLAUDE_PLUGIN_ROOT}/skills/add-workiq-tools/references/dotnet-workiq.md`
- If Node.js: **Read** `${CLAUDE_PLUGIN_ROOT}/skills/add-workiq-tools/references/nodejs-workiq.md`
- If Python: **Read** `${CLAUDE_PLUGIN_ROOT}/skills/add-workiq-tools/references/python-workiq.md`
### 1.2 Check prerequisites
Run both checks in one step:
```bash
a365 --version; a365 develop list-configured 2>/dev/null || echo "a365 CLI not found — will install"
If a365 is missing:
dotnet tool install -g Microsoft.Agents.A365.DevTools.Cli
a365 --version; a365 develop list-configured
Report the current state to the user — which servers are already in ToolingManifest.json.
1.3 Check for AGENTICAPPID
Following agent-detection.md AGENTICAPPID detection order:
- Check
.env/.env.exampleforAGENTIC_APP_ID= - Check
appsettings.jsonforAgenticAppId - Check
a365.generated.config.jsonforagentBlueprintId
If not found, note this — user will need to run a365 setup at some point. Do not block.
Mark task complete: "Detect agent type and check prerequisites"
Phase 2 — Show Available WorkIQ Tools Catalog
Mark task in progress: "Show available WorkIQ tools catalog"
2.1 List available servers
a365 develop list-available
> Note: a365 develop list-available does not require a365.config.json — it reads the environment from A365_ENVIRONMENT env var (defaults to prod). The output now includes a Version column showing V1 or V2 for each server.
Show the output to the user. The catalog includes WorkIQ servers (mail, calendar, Teams, SharePoint, OneDrive, Word, user/presence, Copilot) and Dataverse/Dynamics 365.
2.2 Ask which tools to add
If the user provided specific tool names as the skill argument, use those and skip the question.
Otherwise, parse the a365 develop list-available output to extract the server names, then present them as numbered options. Also check a365 develop list-configured output (from Phase 1.2) to mark already-installed servers so the developer can see what's new vs already present.
AskUserQuestion:
question: |
Which WorkIQ tool servers would you like to add?
(Servers already in ToolingManifest.json are marked ✅)
. All of the above
. Let me type specific names
options:
For each option: if the server name appears in the a365 develop list-configured output, append (✅ already configured) to the label. Include it in the list anyway — user may want to re-add or upgrade version.
Mark task complete: "Show available WorkIQ tools catalog"
Phase 3 — Add WorkIQ MCP Servers via CLI
Mark task in progress: "Add WorkIQ MCP servers via CLI"
3.1 Add selected servers
Run a365 develop add-mcp-servers with the selected server names. Run the command once with all selected names space-separated:
# Substitute the exact mcpServerName values from your `list-available` output.
# Example shown using the current V2 catalog names — yours may differ if the catalog evolved.
a365 develop add-mcp-servers "mcp_MailTools" "mcp_CalendarTools"
# If running from a different directory, use --project-path:
a365 develop add-mcp-servers "mcp_MailTools" "mcp_CalendarTools" --project-path ""
(Adjust the server names to match whichever servers the user selected from the live catalog. The CLI does case-insensitive trim-comparison, but the names must otherwise match the catalog's mcpServerName exactly.)
This command creates ToolingManifest.json if it does not exist, or adds the selected servers to it if it does.
> ⚠️ This command only writes ToolingManifest.json — it does NOT grant permissions. > Permissions are handled separately in Phase 5.
3.2 Verify the manifest was updated
a365 develop list-configured
Confirm each selected server now appears in the output. The Version column shows V1 or V2 based on the server's scope pattern.
If a server was already configured, that is expected — the CLI is idempotent.
Mark task complete: "Add WorkIQ MCP servers via CLI"
Phase 4 — Wire MCP Tool Service in Agent Code
Mark task in progress: "Wire MCP tool service in agent code"
The wiring pattern depends on both programmingLanguage and agentStack from the detection cache (loaded in Phase 0A Step 2; framework support guard in Phase 0B has already hard-stopped any unsupported pair). Pick the branch from the routing table:
| programmingLanguage | agentStack | Branch | |----------------------|--------------|--------| | DotNet | Agent Framework | §4.1 — .NET Agent Framework | | DotNet | Semantic Kernel | §4.2 — .NET Semantic Kernel | | DotNet | Azure AI Foundry | §4.3 — .NET Azure AI Foundry (best-effort; no published sample) | | NodeJS | LangChain | §4.4 — Node.js LangChain | | NodeJS | OpenAI | §4.5 — Node.js OpenAI | | NodeJS | Claude | §4.6 — Node.js Claude SDK | | Python | Agent Framework | §4.7 — Python Agent Framework | | Python | OpenAI | §4.8 — Python OpenAI | | Python | Google ADK | §4.9 — Python Google ADK | | Python | Semantic Kernel | §4.10 — Python Semantic Kernel (best-effort; no published sample) | | Python | Azure AI Foundry | §4.11 — Python Azure AI Foundry (best-effort; no published sample) |
> Detailed code patterns for each branch live in the language-specific reference docs: > - .NET: ${CLAUDE_PLUGIN_ROOT}/skills/add-workiq-tools/references/dotnet-workiq.md > - Node.js: ${CLAUDE_PLUGIN_ROOT}/skills/add-workiq-tools/references/nodejs-workiq.md > - Python: ${CLAUDE_PLUGIN_ROOT}/skills/add-workiq-tools/references/python-workiq.md
For every branch:
- Mark new code with
// A365 WorkIQ — added by add-workiq-tools skill(.NET / Node.js) or# A365 WorkIQ — added by add-workiq-tools skill(Python). For best-effort branches use… best-effort wiring (verify against SDK source before production)instead. - Grep for the framework's wiring symbol (
GetMcpToolsAsync/AddToolServersToAgentAsync/addToolServersToAgent/add_tool_servers_to_agent/McpToolRegistrationService) before editing — skip the wiring step if already present.
⚠️ Preserve-observability rule (applies to ALL §4.x branches that edit the message-handler file)
instrument-observability writes anchors into the same files §4.x will touch — for .NET / Python the WorkIQ call goes into the same method body that the observability skill wraps with BaggageBuilder + InvokeAgentScope (.NET OnMessageAsync, Python process_user_message); for Node.js Claude SDK both skills edit src/client.ts. A naïve Edit with a too-broad old_string will silently delete the observability wrapping. Before any Edit call inside §4.x, follow this checklist:
- Grep the target file for the observability anchor symbols:
- .NET (
AgentApplicationsubclass):BaggageBuilder,InvokeAgentScope,InferenceScope,Agent365ObservabilityContext - Node.js (
src/agent.tsandsrc/client.ts):BaggageBuilder,BaggageBuilderUtils,InvokeAgentScope,InferenceScope,AgenticTokenCacheInstance,preloadObservabilityToken - Python (
agent.py):BaggageBuilder,populate_baggage,InvokeAgentScope,with builder.build(),AgenticTokenCache
- If any of those symbols are present, scope your
Editold_stringas narrowly as possible — anchor on the single statement immediately before/after the new line, never a multi-statement block, never the method signature alone, never the full method body. Examples:
- ✅ Good: anchor on the
var response = await chatClient.GetResponseAsync(...)line and insertGetMcpToolsAsyncimmediately above it. - ❌ Bad: anchor on
protected override async Task OnMessageAsync(...)plus the entire body — the replacement will obliterate theusing var baggageScope = ...andusing var invokeScope = ...blocks observability put there.
- After the
Editcompletes, re-grep the file for the same observability anchors. If any disappeared, the edit clobbered observability — revert the edit and re-apply with a narrower anchor. Do not proceed to the next file.
- If
instrument-observabilityhas NOT run yet in this project (no anchor symbols anywhere), wire WorkIQ normally — there is nothing to preserve. The compositehas_obssignal in the parent skill (make-ai-teammatePhase 0A.3) is what tells you which case you're in; the cache reflects it.
This rule is enforced by validate-add-workiq-tools.js at session end: if has_obs = true was in the cache at session start, the validator re-checks for the observability anchors and fails the session if they were removed.
§4.1 .NET Agent Framework
- Grep
Microsoft.Agents.A365.Toolingin**/*.csproj. If missing:
``bash dotnet add package Microsoft.Agents.A365.Tooling dotnet add package Microsoft.Agents.A365.Tooling.Extensions.AgentFramework ``
- Read
dotnet-workiq.md— sections "Program.cs — Service Registration" and "Agent Class — GetMcpToolsAsync (Agent Framework)". - Edit
Program.cs: add the two-lineAddSingleton+AddSingletonform (matches the verifiedAgent365-SamplesAF sample).builder.Services.AddMcpServices()exists as a one-liner alternative but registers both as Scoped — the AF sample uses Singleton lifetimes to matchAgentApplication's singleton agent host and avoid captive-dependency issues. Skip if already present. - Edit the
AgentApplicationsubclass: add theGetMcpToolsAsynccall insideOnMessageAsync(Agent Framework's per-turn handler) — notOnMessageActivityAsync(older docs in this repo had that wrong; the verified sample usesOnMessageAsync).
§4.2 .NET Semantic Kernel
> SK API differs from AF. SK uses AddToolServersToAgentAsync (mutates Kernel, void return), called during agent initialization — not per-message. Do not copy the AF pattern.
- Install:
``bash dotnet add package Microsoft.Agents.A365.Tooling dotnet add package Microsoft.Agents.A365.Tooling.Extensions.SemanticKernel ``
- Read
dotnet-workiq.md— section "Agent Class — AddToolServersToAgentAsync (Semantic Kernel)". - Edit the agent-initialization code: call
AddToolServersToAgentAsync(kernel, userAuthorization, authHandlerName, turnContext, bearerToken?)after theKernelis built and before the first run.
§4.3 .NET Azure AI Foundry (BEST-EFFORT — no published sample)
Tell the user verbatim: "Microsoft publishes the Microsoft.Agents.A365.Tooling.Extensions.AzureAIFoundry package but no sample exists for it. Skill installs the package and stops — wire the call manually after reading the SDK source."
- Install:
``bash dotnet add package Microsoft.Agents.A365.Tooling.Extensions.AzureAIFoundry ``
- Direct the user to the SDK source: https://github.com/microsoft/Agent365-dotnet/tree/main/src/Tooling/Extensions/AzureAIFoundry
- Do not generate wiring code. Mark this branch complete with a best-effort note in the final summary.
§4.4 Node.js LangChain
- Grep
agents-a365-toolingin**/package.json. If missing:
``bash npm install @microsoft/agents-a365-tooling @microsoft/agents-a365-tooling-extensions-langchain ``
- Read
nodejs-workiq.md— section "LangChain — Wiring (VERIFIED)". - Edit
src/client.ts(or wherever thegetClientfactory lives). Add module-leveltoolService = new McpToolRegistrationService()singleton and the per-turn call insidegetClient. Capture the return value — LangChain rebuilds the agent becausecreateAgent's tools are immutable. - After
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: microsoft
- Source: microsoft/agent365-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.