From 76ad763155f791565d0980546b1a9687b33a13fc Mon Sep 17 00:00:00 2001 From: "Adrian Obando (from Dev Box)" Date: Wed, 22 Jul 2026 20:05:23 -0600 Subject: [PATCH 1/3] adding retrieve skill to work-iq --- .../skills/workiq-preview/SKILL.md | 57 +++-- .../references/retrieve-work-iq.md | 229 ++++++++++++++++++ 2 files changed, 272 insertions(+), 14 deletions(-) create mode 100644 plugins/workiq-preview/skills/workiq-preview/references/retrieve-work-iq.md diff --git a/plugins/workiq-preview/skills/workiq-preview/SKILL.md b/plugins/workiq-preview/skills/workiq-preview/SKILL.md index 2c3a62b..b900412 100644 --- a/plugins/workiq-preview/skills/workiq-preview/SKILL.md +++ b/plugins/workiq-preview/skills/workiq-preview/SKILL.md @@ -1,6 +1,6 @@ --- name: workiq-preview -description: WorkIQ - Microsoft 365 tool surface for agents. Use for any workplace question or write action where data lives in M365. Supports semantic `ask` plus structured tools (`fetch`, create/update/delete, actions, functions, path/schema discovery) for mail, meetings/calendar, documents/files, Teams chats/channels, OneDrive/SharePoint, and people. Read triggers, "what did [person] say", priorities/top of mind, meeting decisions/action items, summarize thread/chat, find emails/docs, list meetings/messages/files/channels, project status/updates, "what changed since". Write triggers, send/reply/forward email, create/update/accept/decline meetings, mark read, delete drafts/items, send/post/reply/react in Teams, set presence, upload/download via web URL. Discovery triggers, available endpoints/paths, fields, required/updatable properties, request body, operation parameters, schema/data model. When in doubt about workplace context, try WorkIQ first. Prefer `ask` for synthesis; use entity tools for exact reads/writes. +description: WorkIQ - Microsoft 365 tool surface for agents. Use for any workplace question or write action where data lives in M365. Supports semantic `ask` plus structured tools (`fetch`, create/update/delete, actions, functions, path/schema discovery) for mail, meetings/calendar, documents/files, Teams chats/channels, OneDrive/SharePoint, and people. Read triggers, "what did [person] say", priorities/top of mind, meeting decisions/action items, summarize thread/chat, find emails/docs, list meetings/messages/files/channels, project status/updates, "what changed since". Write triggers, send/reply/forward email, create/update/accept/decline meetings, mark read, delete drafts/items, send/post/reply/react in Teams, set presence, upload/download via web URL. Discovery triggers, available endpoints/paths, fields, required/updatable properties, request body, operation parameters, schema/data model. When in doubt about workplace context, try WorkIQ first. Prefer `retrieve` as the default for M365 search/find/lookup reads; use `ask` only when synthesis is truly needed; use entity tools for exact reads/writes. compatibility: > Uses the hosted WorkIQ MCP endpoint. No local package is required for MCP tool calls. @@ -8,7 +8,7 @@ compatibility: > # WorkIQ -WorkIQ connects AI agents to Microsoft 365 Copilot for workplace intelligence grounded in organizational data. This skill teaches the model how to use the full WorkIQ toolset: the agentic `ask` tool for semantic questions and the fast **entity tools** for direct structured access to M365 data (`fetch`, `create_entity`, `update_entity`, `delete_entity`, `do_action`, `call_function`, `search_paths`, `get_schema`). +WorkIQ connects AI agents to Microsoft 365 Copilot for workplace intelligence grounded in organizational data. This skill teaches the model how to use the full WorkIQ toolset: the agentic `ask` tool for semantic questions, the `retrieve` tool for structured M365 resource retrieval, and the fast **entity tools** for direct structured access to M365 data (`fetch`, `create_entity`, `update_entity`, `delete_entity`, `do_action`, `call_function`, `search_paths`, `get_schema`). ## ๐Ÿ›‘ STOP โ€” Read This Before Your First Tool Call @@ -28,22 +28,28 @@ See [Resolving tool names in your host](#resolving-tool-names-in-your-host) belo **USE WorkIQ for ANY workplace-related question.** If the answer might exist in Microsoft 365 data, try WorkIQ first. -**Choosing the right tool:** Use `ask` when the question requires **semantic understanding, synthesis, or reasoning** across M365 data ("what did someone say", "what's the status", "summarize"). Use `fetch` (or another entity tool) when the question is a **literal lookup of structured data** with a known shape ("list my meetings on Monday", "show me unread emails from X"). Entity tools return in under a second; `ask` typically takes 10โ€“60 seconds per call and broad questions can run several minutes. +**Choosing the right tool โ€” `retrieve` first for M365 reads.** + +1. **`retrieve` is the default for any search, find, lookup, or "what/who/where" question against M365 data** (emails, files, meetings, Teams messages, people). It returns structured per-source hits plus a grounding markdown summary and is faster than `ask` because it skips conversational synthesis. Use `retrieve` even for "what did X say", "summarize the thread", "find docs about Y", "status of Z" โ€” the grounding markdown is usually enough to answer directly. +2. **Use `ask` only when `retrieve` is insufficient** โ€” i.e., the user explicitly wants a synthesized/conversational narrative, multi-step reasoning across many sources, or an agentic answer that `retrieve`'s hits + markdown cannot express on their own. If `retrieve` returns useful hits, prefer citing them over escalating to `ask`. +3. **Use `fetch` (or another entity tool) for literal structured lookups with a known shape and path** ("list my meetings on Monday", "show me unread emails from X", "get event by ID"). Entity tools return in under a second and are the right tool once you know the exact path/ID. + +Latency: entity tools < 1 s; `retrieve` typically 10โ€“60 s; `ask` 10โ€“60 s and broad questions can run several minutes. **ALWAYS use WorkIQ when the user asks about:** | User Question Pattern | Example | Action | |-----------------------|---------|--------| -| What someone said/shared/communicated | "What did Rob say about the API design?" | `ask` | -| Someone's priorities/concerns/focus | "What's top of mind for Sarah?" | `ask` | -| Meeting content/decisions/action items | "What was decided in yesterday's standup?" | `ask` | -| Summarizing email threads or conversations | "Summarize the deadline thread with John" | `ask` | -| Synthesizing Teams chat activity | "What's the team's take on the release?" | `ask` | -| Finding documents by topic | "Where is the design doc for Project X?" | `ask` | -| Colleague expertise or ownership | "Who owns the billing system?" | `ask` | -| Organizational context / goals | "What are the team's Q1 goals?" | `ask` | -| Project status or updates | "What's the status of Project X?" | `ask` | -| Open-ended "any updates" / catch-up questions | "Any updates I should know about?" | `ask` | +| What someone said/shared/communicated | "What did Rob say about the API design?" | `retrieve` (escalate to `ask` only if synthesis needed) | +| Someone's priorities/concerns/focus | "What's top of mind for Sarah?" | `retrieve` (escalate to `ask` only if synthesis needed) | +| Meeting content/decisions/action items | "What was decided in yesterday's standup?" | `retrieve` (escalate to `ask` only if synthesis needed) | +| Summarizing email threads or conversations | "Summarize the deadline thread with John" | `retrieve` (escalate to `ask` only if synthesis needed) | +| Synthesizing Teams chat activity | "What's the team's take on the release?" | `retrieve` (escalate to `ask` only if synthesis needed) | +| Finding documents by topic | "Where is the design doc for Project X?" | `retrieve` | +| Colleague expertise or ownership | "Who owns the billing system?" | `retrieve` (escalate to `ask` only if synthesis needed) | +| Organizational context / goals | "What are the team's Q1 goals?" | `retrieve` (escalate to `ask` only if synthesis needed) | +| Project status or updates | "What's the status of Project X?" | `retrieve` (escalate to `ask` only if synthesis needed) | +| Open-ended "any updates" / catch-up questions | "Any updates I should know about?" | `retrieve` (escalate to `ask` only if synthesis needed) | | Listing meetings on a known date/range | "What meetings do I have Monday?" | `fetch` (`/me/calendarView`) | | Listing emails with concrete filters | "Show my unread emails from Rob this week" | `fetch` (`/me/messages`) | | Listing Teams chats / channels / members | "List the channels in the DevX team" | `fetch` | @@ -206,6 +212,27 @@ For detailed usage and examples, read `references/ask-work-iq.md`. --- +### `retrieve` โ€” Structured M365 resource retrieval + +The primary tool for search and retrieval. Search across the user's M365 data (emails, files, meetings, Teams messages, people) and return structured results with a model-friendly grounding summary. Unlike `ask`, which synthesizes a conversational answer, `retrieve` returns **raw retrieval hits** โ€” per-source references with rich metadata (resource type, URL, author, timestamps, sensitivity label) plus a grounding markdown โ€” optimized for programmatic consumption, RAG pipelines, and agent grounding. **Prefer retrieve over ask for searches and retrieval of M365 data** + +> **โฑ๏ธ Latency:** Typically 10โ€“60 seconds โ€” lower than `ask` because it skips conversational synthesis. Prefer `retrieve` over `ask` when you need structured hits rather than a synthesized answer. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `query` | string[] | Yes | One or more natural-language search queries. At least one non-empty entry required. | +| `strategy` | string | No | `copilot` (default โ€” M365 indexed content plus connected data sources, federated connectors, MCP tools) or `orchestratedSearch` (M365 indexed content only). Any other value is rejected. | +| `includeDeveloperCard` | boolean | No | When `true`, includes orchestration diagnostics in the response. Defaults to `false`. | +| `agentId` | string | No | Only `bizchat-as-gpt-scenario` is accepted; any other value is rejected. | + +```json +{ "query": ["design doc for authentication", "auth spec Project X"] } +``` + +For detailed usage, response structure, strategy guidance, and faceted metadata, read `references/retrieve-work-iq.md`. + +--- + ## Entity Tools Entity tools provide **fast, direct access to specific M365 data** via Work IQ APIs. They return structured results quickly but have **no intelligence** โ€” they don't interpret, synthesize, or reason about the data. Use them when you know exactly what you want and where it lives. @@ -214,7 +241,8 @@ Entity tools provide **fast, direct access to specific M365 data** via Work IQ A | Scenario | Use | |----------|-----| -| Open-ended question, semantic search, synthesis | `ask` (slow but smart) | +| Search / find / lookup M365 references (default for reads) | "Find emails about WorkIQ", "who talked about deployment rollback?" | `retrieve` (structured hits + grounding markdown) | +| Open-ended question requiring synthesis beyond `retrieve`'s markdown | Multi-source narrative, agentic reasoning | `ask` (slow but smart โ€” only when `retrieve` is insufficient) | | Fetch a known list, apply a filter, get structured data | entity tools (fast but literal) | **Recommended workflow:** for **well-known paths, go direct** โ€” call the read/write tool immediately (use the cheat sheet below). Only fall back to `search_paths` โ†’ `get_schema` โ†’ tool when the path is genuinely unknown or a write body shape is unfamiliar. Do **not** reflexively run `search_paths`/`get_schema` before every common operation. @@ -392,4 +420,5 @@ Read the relevant reference file for full parameter details and examples: - `references/update-entity-work-iq.md` โ€” if you need to update fields on an existing entity - `references/delete-entity-work-iq.md` โ€” if you need to delete an entity - `references/do-action-work-iq.md` โ€” if you need to send mail, accept/decline meetings, copy/move messages +- `references/retrieve-work-iq.md` โ€” if you need to retrieve structured M365 references (emails, files, meetings, Teams messages, people) for programmatic use, RAG, or agent grounding - `references/troubleshooting.md` โ€” if a tool call fails unexpectedly, returns an error, or behaves differently than documented diff --git a/plugins/workiq-preview/skills/workiq-preview/references/retrieve-work-iq.md b/plugins/workiq-preview/skills/workiq-preview/references/retrieve-work-iq.md new file mode 100644 index 0000000..651b865 --- /dev/null +++ b/plugins/workiq-preview/skills/workiq-preview/references/retrieve-work-iq.md @@ -0,0 +1,229 @@ +# retrieve + +Search across the user's M365 data (emails, files, meetings, Teams messages, people) and return structured results with a model-friendly grounding summary. Unlike `ask`, which synthesizes a conversational answer, `retrieve` returns **raw retrieval hits** โ€” per-source references with rich metadata (resource type, URL, author, timestamps, sensitivity label) plus a grounding markdown โ€” optimized for programmatic consumption, RAG pipelines, and agent orchestratedSearch. + +> **โฑ๏ธ Latency:** Typically 15โ€“60 seconds depending on strategy. Lower than `ask` because it skips conversational synthesis. Prefer `retrieve` over `ask` when you need structured hits rather than a synthesized answer, and prefer entity tools when you already know the exact resource path. +> +> **Grounding:** Base your answer only on what the response actually contains. If `retrieve` reports no accessible results or weak evidence, say soโ€” do not pad the answer with information the response does not support. + +## Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `query` | string[] | Yes | One or more natural-language search queries. Each string becomes a separate retrieval query. At least one non-empty, non-whitespace entry is required after stripping. | +| `strategy` | string | No | Retrieval strategy. `copilot` (default) or `orchestratedSearch`. Any other value is rejected. Case-insensitive. | +| `includeDeveloperCard` | boolean | No | When `true`, requests orchestration diagnostics (agent metadata, tool invocations, retrieval summary) from Sydney. Defaults to `false`. | +| `agentId` | string | No | Only `bizchat-as-gpt-scenario` is accepted; any other value is rejected without reaching Sydney. Omit to use the default. | + +## Strategies + +The strategy controls **where data comes from**, not how results are ranked or how the response is shaped. Both strategies return the same `RetrievalResponse` envelope โ€” the response parser does not need to change when switching. + +### `copilot` (default) + +M365 indexed content **plus** federated connectors, external connected data sources, plugins, MCP tools, and other supported enterprise systems. Omitting `strategy` selects `copilot`. + +Use `copilot` when: +- The request may need data beyond the M365 index (e.g., a Salesforce connector, ServiceNow, a connected enterprise system, or an MCP tool) +- Data location is unknown or requirements may expand beyond M365 indexed content +- You want the broadest possible coverage as a safe default + +### `orchestratedSearch` + +M365 indexed content **only** โ€” SharePoint, OneDrive, Teams chats and messages, Outlook mail, and other content in the Microsoft 365 semantic index. No connected connectors, external sources, plugins, or tools are invoked. + +Use `orchestratedSearch` when: +- The request can be satisfied entirely from M365 indexed data +- No federated connector, external data source, plugin, or MCP tool is required + +> **Decision rule: choose based on data location, not latency or complexity.** If all the required information is in the M365 index, use `orchestratedSearch`. If the request needs anything beyond the M365 index โ€” or you are unsure โ€” use `copilot`. + +## Response structure + +The tool returns two content forms: + +1. **Text block** (`content[0].text`) โ€” the `markdown` field verbatim. Contains the orchestratedSearch summary with inline citation markers like `[^h1]`. This is suitable for direct inclusion in a response without further processing. +2. **Structured content** (`structuredContent["application/vnd.ms-workiq.retrieval"]`) โ€” the full typed payload for programmatic consumers. + +### Envelope shape (`application/vnd.ms-workiq.retrieval`) + +```json +{ + "markdown": "## Found 3 relevant sources\n\n...[^h1]...[^h2]...", + "resultCount": 3, + "stoppedReason": "completed", + "retrievalHits": [ ... ] +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `markdown` | string | Model-friendly orchestratedSearch summary with inline citation markers (`[^id]`) that reference hits by their `id`. | +| `resultCount` | integer | Number of surviving hits after Sydney's shim/filter/trim pass. | +| `stoppedReason` | string | Terminal state: `completed`, `cancelled`, or `error`. | +| `retrievalHits` | RetrievalHit[] | Per-source references. May be absent when Sydney returns no hits. | + +### RetrievalHit + +Each element in `retrievalHits` represents one M365 source: + +| Field | Type | Description | +|-------|------|-------------| +| `id` | string | Hit ID that cross-references the markdown citations (`[^h1]` โ†’ `id: "h1"`). | +| `webUrl` | string? | URL the user can navigate to in order to view the source. | +| `resourceMetadata` | ResourceMetadata? | Per-resource metadata facets (see below). | +| `sensitivityLabel` | object? | MIP sensitivity label for the source: `id`, `displayName`, `isEncrypted`. Present only when Sydney supplies it. | +| `relevanceScore` | number? | Sydney relevance score. Present only when Sydney supplies it. | + +### ResourceMetadata facets + +Only the facet(s) matching the resource type are present on a given hit. Multiple facets may appear simultaneously. + +| Facet | Present for | Fields | +|-------|-------------|--------| +| `document` | Files, OneDrive/SharePoint documents | `title`, `authorName`, `occurrenceTime` (ISO-8601 last-modified) | +| `email` | Emails | `subject`, `senderName`, `sentTime` (ISO-8601) | +| `meeting` | Calendar meetings | `title`, `organizerName`, `startTime` (ISO-8601) | +| `video` | Videos | `title`, `durationSeconds` | +| `web` | Web pages, external links, connector content | `title`, `siteName` | +| `chat` | Teams chat/channel messages | `title` | +| `image` | Images | `title` | +| `general` | **Non-contractual fallback** for resource types without a dedicated facet | `title`, `authorName`, `occurrenceTime` | + + +### Runtime handling (large responses) + +Some MCP hosts (including the GitHub Copilot CLI) surface an MCP tool result as a **single concatenated blob** โ€” the `markdown` text block followed by the JSON `structuredContent`. When the combined payload exceeds the host's inline output cap (typically ~20 KB), the entire blob is spilled to a temporary file and the agent only sees a short preview. In that case: + +- **Do not** reparse the structured JSON to rebuild a summary โ€” the `snippet` / discussion fields are long and noisy, and doing so drops the built-in `[^h1]` citations. +- **Do** slice the spilled file to isolate the leading `markdown` segment and use it verbatim. The markdown ends immediately before the JSON tail, which starts with a line like: + + ``` + {"application/vnd.ms-workiq.retrieval":{"markdown":"โ€ฆ + ``` + + Everything above that line is the model-friendly summary already formatted with inline `[^id]` citations that map to `retrievalHits[*].id`. +- If you need one or two specific fields (e.g., `webUrl`, `sensitivityLabel`) from a particular hit, fetch just that hit's block from the JSON tail โ€” do not dump the whole structured payload back into the response. + +The markdown-first path is the intended contract; the structured payload is a supplementary machine-readable view, not a replacement for the markdown summary. + +## When to use `retrieve` vs `ask` + +> **Any question that can go to `ask` can also go to `retrieve`.** The difference is output shape: `ask` synthesizes a prose answer; `retrieve` returns structured hits for you (or a downstream agent) to process directly. + +| Scenario | Tool | +|----------|------| +| Need a synthesized, conversational answer | `ask` | +| Need structured per-source hits for programmatic use | `retrieve` | +| Building a RAG pipeline, orchestratedSearch step, or agent context | `retrieve` | +| Want inline metadata per result (subject, author, dates, URL) | `retrieve` | +| Feeding results into another agent or downstream tool | `retrieve` | +| Need access to connected data sources beyond M365 | `retrieve` (`strategy: copilot`) | +| Request satisfied entirely from M365 indexed content | `retrieve` (`strategy: orchestratedSearch`) | +| User wants a readable answer, not a structured list | `ask` | + +`ask` and `retrieve` are complementary, not substitutes โ€” `retrieve` surfaces the raw hits that `ask` would turn into prose. Use `ask` when Sydney should compose the final answer. Use `retrieve` when you or another agent will process the hits directly. + +## Examples + +### Documents and files (M365 only โ†’ `orchestratedSearch`) + +```json +{ + "query": ["authentication design spec", "auth architecture for Project X"], + "strategy": "orchestratedSearch" +} +``` + +### Emails about a topic + +```json +{ + "query": ["emails about the Q3 release deadline"], + "strategy": "orchestratedSearch" +} +``` + +### Meeting notes and decisions + +```json +{ + "query": ["decisions from the architecture review meeting last week"], + "strategy": "orchestratedSearch" +} +``` + +### Teams messages and chats + +```json +{ + "query": ["Teams discussion about the deployment rollback"], + "strategy": "orchestratedSearch" +} +``` + +### People and expertise + +```json +{ + "query": ["who owns the billing service", "authentication expert on the team"], + "strategy": "orchestratedSearch" +} +``` + +### M365 content plus a connected data source (โ†’ `copilot`) + +```json +{ + "query": ["SharePoint implementation plan and the Salesforce account records for Contoso"], + "strategy": "copilot" +} +``` + +### M365 plus an MCP tool or connected enterprise system + +```json +{ + "query": ["deployment plan and the current rollout state from the deployment tracker"], + "strategy": "copilot" +} +``` + +### Unknown data location โ€” safe default (`copilot`) + +```json +{ + "query": ["latest status on the token minting feature"], + "strategy": "copilot" +} +``` + +### Multi-query search (each string is a separate retrieval query) + +```json +{ + "query": [ + "SharePoint API permissions", + "Graph delegated scopes for files", + "consent requirements for Files.ReadWrite" + ] +} +``` + +## Interpreting the response + +1. **Check `stoppedReason` first.** If `error`, the response is a tool error โ€” the `markdown` field may contain a diagnostic message but should not be treated as orchestratedSearch content. +2. **Use the `markdown` block for grounding.** The inline citations (`[^h1]`) map to `retrievalHits[*].id` โ€” use them to cross-reference structured metadata. +3. **Access faceted metadata from `resourceMetadata`.** Check which facet is populated to determine the resource type, then read the typed fields (subject, title, sentTime, etc.). +4. **Honor `sensitivityLabel`.** When a hit carries a sensitivity label (especially `isEncrypted: true`), respect the classification and do not include the content verbatim in contexts that would violate the label. +5. **An empty `retrievalHits` with `stoppedReason: completed` is a valid "no results" response.** Report it as "nothing found" โ€” do not retry in a loop or fall back to `ask`. + +## Error states + +| Condition | Behaviour | +|-----------|-----------| +| `query` is null, empty, or all-whitespace | Tool error (no Sydney call). Fix: provide at least one non-empty query string. | +| `agentId` is set to anything other than `bizchat-as-gpt-scenario` | Tool error (no Sydney call). Fix: omit `agentId` or pass the supported value. | +| `strategy` is set to anything other than `copilot` or `orchestratedSearch` | Tool error (no Sydney call). Fix: omit `strategy` or use a supported value. | +| Sydney returns `stoppedReason: "error"` | `isError: true`, but `markdown` is still populated for diagnostics. Do not use `markdown` as orchestratedSearch content. | +| Network/auth failure | Tool error with classified message. Check connectivity and authentication. | From 88dad5ebe36ea4d4678ee99e728d95baac24e42c Mon Sep 17 00:00:00 2001 From: "Adrian Obando (from Dev Box)" Date: Thu, 23 Jul 2026 09:29:38 -0600 Subject: [PATCH 2/3] improve retrieve trigger --- .../skills/workiq-preview/SKILL.md | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/plugins/workiq-preview/skills/workiq-preview/SKILL.md b/plugins/workiq-preview/skills/workiq-preview/SKILL.md index b900412..d2ffee6 100644 --- a/plugins/workiq-preview/skills/workiq-preview/SKILL.md +++ b/plugins/workiq-preview/skills/workiq-preview/SKILL.md @@ -1,6 +1,6 @@ --- name: workiq-preview -description: WorkIQ - Microsoft 365 tool surface for agents. Use for any workplace question or write action where data lives in M365. Supports semantic `ask` plus structured tools (`fetch`, create/update/delete, actions, functions, path/schema discovery) for mail, meetings/calendar, documents/files, Teams chats/channels, OneDrive/SharePoint, and people. Read triggers, "what did [person] say", priorities/top of mind, meeting decisions/action items, summarize thread/chat, find emails/docs, list meetings/messages/files/channels, project status/updates, "what changed since". Write triggers, send/reply/forward email, create/update/accept/decline meetings, mark read, delete drafts/items, send/post/reply/react in Teams, set presence, upload/download via web URL. Discovery triggers, available endpoints/paths, fields, required/updatable properties, request body, operation parameters, schema/data model. When in doubt about workplace context, try WorkIQ first. Prefer `retrieve` as the default for M365 search/find/lookup reads; use `ask` only when synthesis is truly needed; use entity tools for exact reads/writes. +description: WorkIQ - Microsoft 365 tool surface for agents. Use for any workplace question or write action where data lives in M365. Supports `retrieve` for structured search, semantic `ask`, plus entity tools (`fetch`, create/update/delete, actions, functions, path/schema discovery) for mail, meetings, files, Teams, OneDrive/SharePoint, and people. Read triggers, "what did [person] say", priorities/top of mind, meeting decisions/action items, summarize thread/chat, find emails/docs, list meetings/messages/files/channels, project status, "what changed since". Write triggers, send/reply/forward email, create/update/accept/decline meetings, mark read, delete items, post/react in Teams, set presence. Discovery triggers, available endpoints/paths, fields, request body, schema. Prefer `retrieve` as the default for M365 search/find/lookup โ€” and always when the prompt is structured (JSON/YAML) or the user wants a structured/JSON response; use `ask` only when synthesis is needed; use entity tools for exact reads/writes. compatibility: > Uses the hosted WorkIQ MCP endpoint. No local package is required for MCP tool calls. @@ -12,12 +12,13 @@ WorkIQ connects AI agents to Microsoft 365 Copilot for workplace intelligence gr ## ๐Ÿ›‘ STOP โ€” Read This Before Your First Tool Call -The tools in this skill are documented by their **logical names** (`ask`, `fetch`, etc.), but your MCP host almost certainly exposes them under a **prefixed** name. +The tools in this skill are documented by their **logical names** (`retrieve`,`ask`, `fetch`, etc.), but your MCP host almost certainly exposes them under a **prefixed** name. **The MCP server is named `workiq-preview`. Tool prefixes are derived from the MCP server name โ€” never from the name of this skill or its containing folder.** โŒ **DO NOT** derive a prefix from this skill's name or folder. โŒ **DO NOT** call `ask` verbatim and assume it will work. +โœ… **DO** scan your available tools list for an entry whose name **ends with** `retrieve` and call that exact name. In Copilot CLI this will be `workiq-preview-retrieve`. โœ… **DO** scan your available tools list for an entry whose name **ends with** `ask` and call that exact name. In Copilot CLI this will be `workiq-preview-ask`. See [Resolving tool names in your host](#resolving-tool-names-in-your-host) below for the full resolution algorithm. If you skip this step, your first tool call will fail with "tool does not exist." @@ -31,7 +32,8 @@ See [Resolving tool names in your host](#resolving-tool-names-in-your-host) belo **Choosing the right tool โ€” `retrieve` first for M365 reads.** 1. **`retrieve` is the default for any search, find, lookup, or "what/who/where" question against M365 data** (emails, files, meetings, Teams messages, people). It returns structured per-source hits plus a grounding markdown summary and is faster than `ask` because it skips conversational synthesis. Use `retrieve` even for "what did X say", "summarize the thread", "find docs about Y", "status of Z" โ€” the grounding markdown is usually enough to answer directly. -2. **Use `ask` only when `retrieve` is insufficient** โ€” i.e., the user explicitly wants a synthesized/conversational narrative, multi-step reasoning across many sources, or an agentic answer that `retrieve`'s hits + markdown cannot express on their own. If `retrieve` returns useful hits, prefer citing them over escalating to `ask`. + - **Always prefer `retrieve` when the user asks in a structured format (e.g., the prompt itself is JSON, YAML, or a schema) or requests the response in a structured format (JSON, table, CSV, list of records, "return as JSON", "give me an array ofโ€ฆ", "schema-shaped output").** `retrieve`'s per-source hits map cleanly onto structured output; `ask` returns prose and is a poor fit for machine-readable responses. Only fall back to `ask` if `retrieve` cannot produce the required fields. +2. **Use `ask` only when `retrieve` is insufficient** โ€” i.e., the user explicitly wants a synthesized/conversational narrative, multi-step reasoning across many sources, or an agentic answer that `retrieve`'s hits + markdown cannot express on their own. If `retrieve` returns useful hits, prefer citing them over escalating to `ask`. Do **not** use `ask` when the user wants JSON/structured output โ€” use `retrieve`. 3. **Use `fetch` (or another entity tool) for literal structured lookups with a known shape and path** ("list my meetings on Monday", "show me unread emails from X", "get event by ID"). Entity tools return in under a second and are the right tool once you know the exact path/ID. Latency: entity tools < 1 s; `retrieve` typically 10โ€“60 s; `ask` 10โ€“60 s and broad questions can run several minutes. @@ -40,16 +42,16 @@ Latency: entity tools < 1 s; `retrieve` typically 10โ€“60 s; `ask` 10โ€“60 s and | User Question Pattern | Example | Action | |-----------------------|---------|--------| -| What someone said/shared/communicated | "What did Rob say about the API design?" | `retrieve` (escalate to `ask` only if synthesis needed) | -| Someone's priorities/concerns/focus | "What's top of mind for Sarah?" | `retrieve` (escalate to `ask` only if synthesis needed) | -| Meeting content/decisions/action items | "What was decided in yesterday's standup?" | `retrieve` (escalate to `ask` only if synthesis needed) | -| Summarizing email threads or conversations | "Summarize the deadline thread with John" | `retrieve` (escalate to `ask` only if synthesis needed) | -| Synthesizing Teams chat activity | "What's the team's take on the release?" | `retrieve` (escalate to `ask` only if synthesis needed) | +| What someone said/shared/communicated | "What did Rob say about the API design?" | `retrieve` | +| Someone's priorities/concerns/focus | "What's top of mind for Sarah?" | `retrieve` | +| Meeting content/decisions/action items | "What was decided in yesterday's standup?" | `retrieve` | +| Summarizing email threads or conversations | "Summarize the deadline thread with John" | `retrieve` | +| Synthesizing Teams chat activity | "What's the team's take on the release?" | `retrieve` | | Finding documents by topic | "Where is the design doc for Project X?" | `retrieve` | -| Colleague expertise or ownership | "Who owns the billing system?" | `retrieve` (escalate to `ask` only if synthesis needed) | -| Organizational context / goals | "What are the team's Q1 goals?" | `retrieve` (escalate to `ask` only if synthesis needed) | -| Project status or updates | "What's the status of Project X?" | `retrieve` (escalate to `ask` only if synthesis needed) | -| Open-ended "any updates" / catch-up questions | "Any updates I should know about?" | `retrieve` (escalate to `ask` only if synthesis needed) | +| Colleague expertise or ownership | "Who owns the billing system?" | `retrieve` | +| Organizational context / goals | "What are the team's Q1 goals?" | `retrieve` | +| Project status or updates | "What's the status of Project X?" | `retrieve` | +| Open-ended "any updates" / catch-up questions | "Any updates I should know about?" | `retrieve` | | Listing meetings on a known date/range | "What meetings do I have Monday?" | `fetch` (`/me/calendarView`) | | Listing emails with concrete filters | "Show my unread emails from Rob this week" | `fetch` (`/me/messages`) | | Listing Teams chats / channels / members | "List the channels in the DevX team" | `fetch` | @@ -169,7 +171,7 @@ If a WorkIQ MCP call fails because the user is not signed in, the token is stale ## Resolving tool names in your host -Throughout this skill (and its `references/*.md`), MCP tools are referred to by their **logical names** โ€” for example `ask`, `fetch`, `search_paths`, etc. +Throughout this skill (and its `references/*.md`), MCP tools are referred to by their **logical names** โ€” for example `retrieve` `ask`, `fetch`, `search_paths`, etc. > **โš ๏ธ Common pitfall:** Tool prefixes come from the **MCP server name** (`workiq-preview`) โ€” never from the name of this skill or its containing folder. Do not construct a prefix from the skill name. @@ -193,7 +195,7 @@ If you call the logical name verbatim and get a "tool does not exist" error, thi ### `ask` โ€” Agentic natural language M365 queries -The primary tool. Ask any workplace question in plain English. This is an **agentic tool** โ€” it orchestrates multi-step operations internally (searching emails, meetings, Teams chats, documents, people) to answer complex questions. Use it when you need intelligence, synthesis, or semantic understanding across M365 data. +The primary conversational tool. Ask any workplace question in plain English. This is an **agentic tool** โ€” it orchestrates multi-step operations internally (searching emails, meetings, Teams chats, documents, people) to answer complex questions. Use it when you need intelligence, synthesis, or semantic understanding across M365 data. > **โฑ๏ธ High latency:** A call typically takes **10โ€“60 seconds** as the agent performs multiple backend operations, and broad questions can run several minutes (the hard limit is ~300s). Avoid calling it in tight loops or for simple data retrieval โ€” use the entity tools below for that instead. If a question is broad, split it into scoped sub-questions rather than one mega-question. @@ -214,9 +216,9 @@ For detailed usage and examples, read `references/ask-work-iq.md`. ### `retrieve` โ€” Structured M365 resource retrieval -The primary tool for search and retrieval. Search across the user's M365 data (emails, files, meetings, Teams messages, people) and return structured results with a model-friendly grounding summary. Unlike `ask`, which synthesizes a conversational answer, `retrieve` returns **raw retrieval hits** โ€” per-source references with rich metadata (resource type, URL, author, timestamps, sensitivity label) plus a grounding markdown โ€” optimized for programmatic consumption, RAG pipelines, and agent grounding. **Prefer retrieve over ask for searches and retrieval of M365 data** +The primary tool for search and retrieval. Search across the user's M365 data (emails, files, meetings, Teams messages, people) and return structured results with a model-friendly grounding summary. Unlike `ask`, which synthesizes a conversational answer, `retrieve` returns **raw retrieval hits** โ€” per-source references with rich metadata (resource type, URL, author, timestamps, sensitivity label) plus a grounding markdown โ€” optimized for programmatic consumption, RAG pipelines, and agent grounding. **Prefer `retrieve` over `ask` for searches and retrieval of M365 data โ€” and always prefer it when the user's prompt is itself structured (JSON/YAML/schema) or asks for the response in a structured format (JSON, table, CSV, list of records).** -> **โฑ๏ธ Latency:** Typically 10โ€“60 seconds โ€” lower than `ask` because it skips conversational synthesis. Prefer `retrieve` over `ask` when you need structured hits rather than a synthesized answer. +> **โฑ๏ธ Latency:** Typically 10โ€“60 seconds โ€” lower than `ask` because it skips conversational synthesis. Prefer `retrieve` over `ask` whenever you need structured/JSON-shaped responses rather than a synthesized narrative. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| From 4486e8d12d8aa5e9aefb47f7316b0b45a377b265 Mon Sep 17 00:00:00 2001 From: "Adrian Obando (from Dev Box)" Date: Thu, 23 Jul 2026 16:38:30 -0600 Subject: [PATCH 3/3] updating skill --- .../skills/workiq-preview/SKILL.md | 19 +++-- .../references/retrieve-work-iq.md | 70 ++++++++++--------- 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/plugins/workiq-preview/skills/workiq-preview/SKILL.md b/plugins/workiq-preview/skills/workiq-preview/SKILL.md index d2ffee6..f44e31e 100644 --- a/plugins/workiq-preview/skills/workiq-preview/SKILL.md +++ b/plugins/workiq-preview/skills/workiq-preview/SKILL.md @@ -1,6 +1,6 @@ --- name: workiq-preview -description: WorkIQ - Microsoft 365 tool surface for agents. Use for any workplace question or write action where data lives in M365. Supports `retrieve` for structured search, semantic `ask`, plus entity tools (`fetch`, create/update/delete, actions, functions, path/schema discovery) for mail, meetings, files, Teams, OneDrive/SharePoint, and people. Read triggers, "what did [person] say", priorities/top of mind, meeting decisions/action items, summarize thread/chat, find emails/docs, list meetings/messages/files/channels, project status, "what changed since". Write triggers, send/reply/forward email, create/update/accept/decline meetings, mark read, delete items, post/react in Teams, set presence. Discovery triggers, available endpoints/paths, fields, request body, schema. Prefer `retrieve` as the default for M365 search/find/lookup โ€” and always when the prompt is structured (JSON/YAML) or the user wants a structured/JSON response; use `ask` only when synthesis is needed; use entity tools for exact reads/writes. +description: WorkIQ - Microsoft 365 tool surface for agents. Use for any workplace question or write action where data lives in M365. Supports `retrieve` for structured search (natural-language queries, structured hits), semantic `ask`, plus entity tools (`fetch`, create/update/delete, actions, functions, path/schema discovery) for mail, meetings, files, Teams, OneDrive/SharePoint, people. Read triggers, "what did [person] say", top of mind, meeting decisions/action items, summarize thread, find emails/docs, list meetings/messages/files/channels, project status, "what changed since". Write triggers, send/reply/forward email, create/update/accept meetings, mark read, delete items, post/react in Teams, set presence. Discovery triggers, endpoints/paths, fields, request body, schema. Prefer `retrieve` as default for M365 search/find/lookup โ€” always when caller is an agent/LLM/MCP/tool or a human wants structured/JSON output; use `ask` only when a human needs synthesized prose; use entity tools for exact reads/writes. compatibility: > Uses the hosted WorkIQ MCP endpoint. No local package is required for MCP tool calls. @@ -29,11 +29,14 @@ See [Resolving tool names in your host](#resolving-tool-names-in-your-host) belo **USE WorkIQ for ANY workplace-related question.** If the answer might exist in Microsoft 365 data, try WorkIQ first. -**Choosing the right tool โ€” `retrieve` first for M365 reads.** +**Choosing the right tool โ€” decide by *who is consuming the answer*, not by how the question is phrased.** -1. **`retrieve` is the default for any search, find, lookup, or "what/who/where" question against M365 data** (emails, files, meetings, Teams messages, people). It returns structured per-source hits plus a grounding markdown summary and is faster than `ask` because it skips conversational synthesis. Use `retrieve` even for "what did X say", "summarize the thread", "find docs about Y", "status of Z" โ€” the grounding markdown is usually enough to answer directly. - - **Always prefer `retrieve` when the user asks in a structured format (e.g., the prompt itself is JSON, YAML, or a schema) or requests the response in a structured format (JSON, table, CSV, list of records, "return as JSON", "give me an array ofโ€ฆ", "schema-shaped output").** `retrieve`'s per-source hits map cleanly onto structured output; `ask` returns prose and is a poor fit for machine-readable responses. Only fall back to `ask` if `retrieve` cannot produce the required fields. -2. **Use `ask` only when `retrieve` is insufficient** โ€” i.e., the user explicitly wants a synthesized/conversational narrative, multi-step reasoning across many sources, or an agentic answer that `retrieve`'s hits + markdown cannot express on their own. If `retrieve` returns useful hits, prefer citing them over escalating to `ask`. Do **not** use `ask` when the user wants JSON/structured output โ€” use `retrieve`. +Both `retrieve` and `ask` accept natural-language queries. The real question is whether the caller needs **conversational synthesis** (prose) or **structured hits** (data). Use that to pick. + +1. **`retrieve` is the default for any search, find, lookup, or "what/who/where" question against M365 data** (emails, files, meetings, Teams messages, people). It accepts the same natural-language queries as `ask`, but returns structured per-source hits plus a grounding markdown summary instead of a synthesized narrative. It is faster than `ask` because it skips conversational synthesis. + - **Prefer `retrieve` when conversational synthesis is not needed and a structured response is more useful.** This is almost always true when the caller is an **agent, LLM, MCP client, downstream tool, RAG pipeline, or any programmatic consumer** โ€” they want raw hits + citations to process themselves, not prose. It is also true when a human explicitly asks for structured output (JSON, table, CSV, list of records, "return as JSON", schema-shaped output) or hands you a structured prompt (JSON/YAML/schema). + - Use `retrieve` even for "what did X say", "summarize the thread", "find docs about Y", "status of Z" โ€” the grounding markdown is usually enough to answer directly, and the structured hits are ready to hand off to another agent or tool. +2. **Use `ask` only when the *end consumer is a human* who wants a synthesized, conversational answer** and `retrieve`'s hits + grounding markdown are not enough on their own โ€” e.g., multi-step reasoning across many sources, or an agentic narrative the caller cannot compose themselves. If `retrieve` returns useful hits, prefer citing them over escalating to `ask`. Do **not** use `ask` when the caller is another agent/tool or wants JSON/structured output โ€” use `retrieve`. 3. **Use `fetch` (or another entity tool) for literal structured lookups with a known shape and path** ("list my meetings on Monday", "show me unread emails from X", "get event by ID"). Entity tools return in under a second and are the right tool once you know the exact path/ID. Latency: entity tools < 1 s; `retrieve` typically 10โ€“60 s; `ask` 10โ€“60 s and broad questions can run several minutes. @@ -216,9 +219,11 @@ For detailed usage and examples, read `references/ask-work-iq.md`. ### `retrieve` โ€” Structured M365 resource retrieval -The primary tool for search and retrieval. Search across the user's M365 data (emails, files, meetings, Teams messages, people) and return structured results with a model-friendly grounding summary. Unlike `ask`, which synthesizes a conversational answer, `retrieve` returns **raw retrieval hits** โ€” per-source references with rich metadata (resource type, URL, author, timestamps, sensitivity label) plus a grounding markdown โ€” optimized for programmatic consumption, RAG pipelines, and agent grounding. **Prefer `retrieve` over `ask` for searches and retrieval of M365 data โ€” and always prefer it when the user's prompt is itself structured (JSON/YAML/schema) or asks for the response in a structured format (JSON, table, CSV, list of records).** +The primary tool for search and retrieval. Search across the user's M365 data (emails, files, meetings, Teams messages, people) and return structured results with a model-friendly grounding summary. `retrieve` accepts the same natural-language queries as `ask`, but instead of a synthesized conversational answer it returns **raw retrieval hits** โ€” per-source references with rich metadata (resource type, URL, author, timestamps, sensitivity label) plus a grounding markdown โ€” optimized for programmatic consumption, RAG pipelines, and agent-to-agent grounding. **Prefer `retrieve` over `ask` whenever conversational synthesis is not needed and a structured response is more useful** โ€” which is almost always true when the caller is another agent, LLM, MCP client, or external tool, and also true when a human explicitly asks for structured (JSON/table/CSV) output or provides a structured (JSON/YAML/schema) prompt. -> **โฑ๏ธ Latency:** Typically 10โ€“60 seconds โ€” lower than `ask` because it skips conversational synthesis. Prefer `retrieve` over `ask` whenever you need structured/JSON-shaped responses rather than a synthesized narrative. +> **โฑ๏ธ Latency:** Typically 10โ€“60 seconds โ€” lower than `ask` because it skips conversational synthesis. Prefer `retrieve` over `ask` for programmatic/structured consumers; reserve `ask` for humans who need a synthesized narrative. +> +> **๐Ÿ“„ Consuming the response:** The `markdown` field is the **preferred** output โ€” a model-friendly grounding summary with inline `[^id]` citations that map to `retrievalHits[*].id`. Emit it verbatim to the caller; do not paraphrase it or rebuild a summary from `retrievalHits`. Reach into the structured `retrievalHits` payload only for specific fields the markdown doesn't already expose (e.g., a raw `webUrl` or `sensitivityLabel` for one hit). | Parameter | Type | Required | Description | |-----------|------|----------|-------------| diff --git a/plugins/workiq-preview/skills/workiq-preview/references/retrieve-work-iq.md b/plugins/workiq-preview/skills/workiq-preview/references/retrieve-work-iq.md index 651b865..1a33869 100644 --- a/plugins/workiq-preview/skills/workiq-preview/references/retrieve-work-iq.md +++ b/plugins/workiq-preview/skills/workiq-preview/references/retrieve-work-iq.md @@ -1,17 +1,19 @@ # retrieve -Search across the user's M365 data (emails, files, meetings, Teams messages, people) and return structured results with a model-friendly grounding summary. Unlike `ask`, which synthesizes a conversational answer, `retrieve` returns **raw retrieval hits** โ€” per-source references with rich metadata (resource type, URL, author, timestamps, sensitivity label) plus a grounding markdown โ€” optimized for programmatic consumption, RAG pipelines, and agent orchestratedSearch. +Search across the user's M365 data (emails, files, meetings, Teams messages, people) and return structured results with a model-friendly grounding summary. `retrieve` accepts the same natural-language queries as `ask`, but instead of a synthesized conversational answer it returns **raw retrieval hits** โ€” per-source references with rich metadata (resource type, URL, author, timestamps, sensitivity label) plus a grounding markdown โ€” optimized for programmatic consumption, RAG pipelines, and agent-to-agent grounding. -> **โฑ๏ธ Latency:** Typically 15โ€“60 seconds depending on strategy. Lower than `ask` because it skips conversational synthesis. Prefer `retrieve` over `ask` when you need structured hits rather than a synthesized answer, and prefer entity tools when you already know the exact resource path. +> **When to reach for `retrieve` instead of `ask`:** pick based on **who is consuming the answer**, not on how the question is phrased. If the caller is another agent, LLM, MCP client, external tool, or a RAG/grounding pipeline, conversational synthesis is not useful โ€” return structured hits with `retrieve`. If a human explicitly asks for structured output (JSON, table, CSV, list of records) or hands you a structured prompt (JSON/YAML/schema), also use `retrieve`. Reserve `ask` for the case where a human needs a synthesized prose answer that `retrieve`'s hits + grounding markdown cannot express on their own. > -> **Grounding:** Base your answer only on what the response actually contains. If `retrieve` reports no accessible results or weak evidence, say soโ€” do not pad the answer with information the response does not support. +> **โฑ๏ธ Latency:** Typically 15โ€“60 seconds depending on strategy. Lower than `ask` because it skips conversational synthesis. Prefer entity tools when you already know the exact resource path. +> +> **Grounding:** Base your answer only on what the response actually contains. If `retrieve` reports no accessible results or weak evidence, say so โ€” do not pad the answer with information the response does not support. ## Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `query` | string[] | Yes | One or more natural-language search queries. Each string becomes a separate retrieval query. At least one non-empty, non-whitespace entry is required after stripping. | -| `strategy` | string | No | Retrieval strategy. `copilot` (default) or `orchestratedSearch`. Any other value is rejected. Case-insensitive. | +| `strategy` | string | No | Retrieval strategy. `copilot` (default) or `grounding`. Any other value is rejected. Case-insensitive. | | `includeDeveloperCard` | boolean | No | When `true`, requests orchestration diagnostics (agent metadata, tool invocations, retrieval summary) from Sydney. Defaults to `false`. | | `agentId` | string | No | Only `bizchat-as-gpt-scenario` is accepted; any other value is rejected without reaching Sydney. Omit to use the default. | @@ -28,23 +30,25 @@ Use `copilot` when: - Data location is unknown or requirements may expand beyond M365 indexed content - You want the broadest possible coverage as a safe default -### `orchestratedSearch` +### `grounding` M365 indexed content **only** โ€” SharePoint, OneDrive, Teams chats and messages, Outlook mail, and other content in the Microsoft 365 semantic index. No connected connectors, external sources, plugins, or tools are invoked. -Use `orchestratedSearch` when: +Use `grounding` when: - The request can be satisfied entirely from M365 indexed data - No federated connector, external data source, plugin, or MCP tool is required -> **Decision rule: choose based on data location, not latency or complexity.** If all the required information is in the M365 index, use `orchestratedSearch`. If the request needs anything beyond the M365 index โ€” or you are unsure โ€” use `copilot`. +> **Decision rule: choose based on data location, not latency or complexity.** If all the required information is in the M365 index, use `grounding`. If the request needs anything beyond the M365 index โ€” or you are unsure โ€” use `copilot`. ## Response structure The tool returns two content forms: -1. **Text block** (`content[0].text`) โ€” the `markdown` field verbatim. Contains the orchestratedSearch summary with inline citation markers like `[^h1]`. This is suitable for direct inclusion in a response without further processing. +1. **Text block** (`content[0].text`) โ€” the `markdown` field verbatim. Contains the grounding summary with inline citation markers like `[^h1]`. This is suitable for direct inclusion in a response without further processing. 2. **Structured content** (`structuredContent["application/vnd.ms-workiq.retrieval"]`) โ€” the full typed payload for programmatic consumers. +> **โœ… Preferred consumption path: `markdown`.** The `markdown` field is the intended, first-class output of `retrieve`. It is already model-friendly, carries inline `[^id]` citations that map to `retrievalHits[*].id`, and is what downstream agents, prompts, and human readers should consume by default. **Use `markdown` verbatim whenever possible** โ€” do not reformat, re-summarize, or paraphrase it, and do not rebuild a summary from the structured payload. Only reach into `retrievalHits` / `structuredContent` when you need a specific field the markdown doesn't already expose (e.g., a raw `webUrl`, a `sensitivityLabel`, or a `relevanceScore` for a particular hit). + ### Envelope shape (`application/vnd.ms-workiq.retrieval`) ```json @@ -58,7 +62,7 @@ The tool returns two content forms: | Field | Type | Description | |-------|------|-------------| -| `markdown` | string | Model-friendly orchestratedSearch summary with inline citation markers (`[^id]`) that reference hits by their `id`. | +| `markdown` | string | Model-friendly grounding summary with inline citation markers (`[^id]`) that reference hits by their `id`. | | `resultCount` | integer | Number of surviving hits after Sydney's shim/filter/trim pass. | | `stoppedReason` | string | Terminal state: `completed`, `cancelled`, or `error`. | | `retrievalHits` | RetrievalHit[] | Per-source references. May be absent when Sydney returns no hits. | @@ -109,29 +113,31 @@ The markdown-first path is the intended contract; the structured payload is a su ## When to use `retrieve` vs `ask` -> **Any question that can go to `ask` can also go to `retrieve`.** The difference is output shape: `ask` synthesizes a prose answer; `retrieve` returns structured hits for you (or a downstream agent) to process directly. +> **Both tools accept natural-language queries.** They are not distinguished by how you phrase the question โ€” they are distinguished by **who consumes the answer** and **whether conversational synthesis is needed**. `ask` returns synthesized prose; `retrieve` returns structured hits with a grounding markdown. + +**Rule of thumb:** if the caller is not a human reading prose, use `retrieve`. -| Scenario | Tool | -|----------|------| -| Need a synthesized, conversational answer | `ask` | -| Need structured per-source hits for programmatic use | `retrieve` | -| Building a RAG pipeline, orchestratedSearch step, or agent context | `retrieve` | -| Want inline metadata per result (subject, author, dates, URL) | `retrieve` | -| Feeding results into another agent or downstream tool | `retrieve` | -| Need access to connected data sources beyond M365 | `retrieve` (`strategy: copilot`) | -| Request satisfied entirely from M365 indexed content | `retrieve` (`strategy: orchestratedSearch`) | -| User wants a readable answer, not a structured list | `ask` | +| Caller / scenario | Tool | Why | +|---|---|---| +| Another agent, LLM, MCP client, or external tool consuming the answer | `retrieve` | Structured hits are directly consumable; prose has to be re-parsed and loses citations | +| RAG pipeline, grounding step, or agent-to-agent handoff | `retrieve` | Per-source metadata + IDs are the native input format | +| Human explicitly asks for structured output (JSON, table, CSV, list of records) | `retrieve` | Hits map cleanly onto the requested shape | +| Prompt itself is structured (JSON / YAML / schema) | `retrieve` | Signal that the caller is programmatic or expects programmatic output | +| Need inline per-result metadata (subject, author, dates, URL, sensitivity label) | `retrieve` | Facets are surfaced on each hit | +| Need access to connected data sources beyond M365 | `retrieve` (`strategy: copilot`) | Federated connectors + MCP tools included | +| Request satisfied entirely from M365 indexed content | `retrieve` (`strategy: grounding`) | M365 index only, no external calls | +| Human end-user wants a synthesized, conversational answer that hits + grounding markdown alone can't express | `ask` | Only case where prose synthesis is worth the extra latency | -`ask` and `retrieve` are complementary, not substitutes โ€” `retrieve` surfaces the raw hits that `ask` would turn into prose. Use `ask` when Sydney should compose the final answer. Use `retrieve` when you or another agent will process the hits directly. +`ask` and `retrieve` are complementary, not substitutes โ€” `retrieve` surfaces the raw hits that `ask` would turn into prose. Whenever conversational synthesis is not needed, prefer `retrieve` even if the question sounds like natural language (e.g., "what did Rob say about auth?", "summarize the deployment thread", "who owns billing?"). Fall back to `ask` only when a human end-user needs the synthesis itself. ## Examples -### Documents and files (M365 only โ†’ `orchestratedSearch`) +### Documents and files (M365 only โ†’ `grounding`) ```json { "query": ["authentication design spec", "auth architecture for Project X"], - "strategy": "orchestratedSearch" + "strategy": "grounding" } ``` @@ -140,7 +146,7 @@ The markdown-first path is the intended contract; the structured payload is a su ```json { "query": ["emails about the Q3 release deadline"], - "strategy": "orchestratedSearch" + "strategy": "grounding" } ``` @@ -149,7 +155,7 @@ The markdown-first path is the intended contract; the structured payload is a su ```json { "query": ["decisions from the architecture review meeting last week"], - "strategy": "orchestratedSearch" + "strategy": "grounding" } ``` @@ -158,7 +164,7 @@ The markdown-first path is the intended contract; the structured payload is a su ```json { "query": ["Teams discussion about the deployment rollback"], - "strategy": "orchestratedSearch" + "strategy": "grounding" } ``` @@ -167,7 +173,7 @@ The markdown-first path is the intended contract; the structured payload is a su ```json { "query": ["who owns the billing service", "authentication expert on the team"], - "strategy": "orchestratedSearch" + "strategy": "grounding" } ``` @@ -212,9 +218,9 @@ The markdown-first path is the intended contract; the structured payload is a su ## Interpreting the response -1. **Check `stoppedReason` first.** If `error`, the response is a tool error โ€” the `markdown` field may contain a diagnostic message but should not be treated as orchestratedSearch content. -2. **Use the `markdown` block for grounding.** The inline citations (`[^h1]`) map to `retrievalHits[*].id` โ€” use them to cross-reference structured metadata. -3. **Access faceted metadata from `resourceMetadata`.** Check which facet is populated to determine the resource type, then read the typed fields (subject, title, sentTime, etc.). +1. **Check `stoppedReason` first.** If `error`, the response is a tool error โ€” the `markdown` field may contain a diagnostic message but should not be treated as grounding content. +2. **`markdown` is the preferred consumption path โ€” use it verbatim.** It is already a model-friendly grounding summary with inline `[^h1]` citations that map to `retrievalHits[*].id`. Emit it directly to the caller (agent, tool, or user) without paraphrasing, re-summarizing, or rebuilding it from `retrievalHits`. If the caller needs raw structured hits, forward `structuredContent` alongside โ€” but the answer itself should still be `markdown`. +3. **Only descend into `retrievalHits` for targeted lookups** the markdown doesn't already expose โ€” e.g., a specific `webUrl`, `sensitivityLabel`, `relevanceScore`, or `resourceMetadata` facet for one hit. Cross-reference by `id` (`[^h1]` โ†’ `retrievalHits[*].id === "h1"`). 4. **Honor `sensitivityLabel`.** When a hit carries a sensitivity label (especially `isEncrypted: true`), respect the classification and do not include the content verbatim in contexts that would violate the label. 5. **An empty `retrievalHits` with `stoppedReason: completed` is a valid "no results" response.** Report it as "nothing found" โ€” do not retry in a loop or fall back to `ask`. @@ -224,6 +230,6 @@ The markdown-first path is the intended contract; the structured payload is a su |-----------|-----------| | `query` is null, empty, or all-whitespace | Tool error (no Sydney call). Fix: provide at least one non-empty query string. | | `agentId` is set to anything other than `bizchat-as-gpt-scenario` | Tool error (no Sydney call). Fix: omit `agentId` or pass the supported value. | -| `strategy` is set to anything other than `copilot` or `orchestratedSearch` | Tool error (no Sydney call). Fix: omit `strategy` or use a supported value. | -| Sydney returns `stoppedReason: "error"` | `isError: true`, but `markdown` is still populated for diagnostics. Do not use `markdown` as orchestratedSearch content. | +| `strategy` is set to anything other than `copilot` or `grounding` | Tool error (no Sydney call). Fix: omit `strategy` or use a supported value. | +| Sydney returns `stoppedReason: "error"` | `isError: true`, but `markdown` is still populated for diagnostics. Do not use `markdown` as grounding content. | | Network/auth failure | Tool error with classified message. Check connectivity and authentication. |