Skip to content

Microsoft 365 files, emails and events as first-class citations - #1718

Merged
Paul Lizer (paullizer) merged 5 commits into
microsoft:paullizer-react-v2-uifrom
paullizer:paullizer-m365-source-citations
Oct 8, 2026
Merged

Paul Lizer (paullizer) merged 5 commits into
microsoft:paullizer-react-v2-uifrom
paullizer:paullizer-m365-source-citations

Conversation

@paullizer

@paullizer Paul Lizer (paullizer) commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Answers that use SharePoint/OneDrive files, emails or calendar events through the Microsoft 365 actions (agent chat, workflows and Orchestrate) now cite them inline like workspace documents. Clicking a chip opens a source card with Open in SharePoint / OneDrive / Outlook; nothing is downloaded, and the reader's own sign-in decides access.
  • Email and event lists always use one fixed text layout: a header ("10 most recent emails, all unread, newest first:"), then one numbered line per item with subject, sender or time span, and the citation. Times are shown in the reader's browser time zone.
  • The conversation drawer's Documents pane gains SharePoint & OneDrive, Email and Calendar sections (owner only) with Open online; the workspace list is unchanged. The classic UI links cited titles safely.
  • Records are bounded (no bodies or file content; https Graph links only) and are produced only by the Microsoft 365 plugins from Graph data, captured before tool-result truncation. Look-alike JSON from other tools (HTTP, OpenAPI, MCP) can't create a Microsoft 365 citation or link.

Linked issue

Refs #1715 (companion PR A: in-chat Microsoft 365 approvals and orchestration retries; no tracking issue)

Release Notes & Latest Features

  • New Feature
  • Bug Fix
  • UI Enhancement
  • Breaking Change
  • Internal only

Is this visible to end users?

  • Yes
  • No

Is this admin-facing (Admin Settings, governance, deployment, config)?

  • Yes
  • No

Should this become a Latest Feature card?

  • Yes
  • No
  • Already added

Screenshot needed for the card?

  • Yes
  • No
  • Attached

(Suggested card; not added in this PR. Follow-up via .github/prompts/update-latest-features.prompt.md.)

Version bump

Testing / validation

  • python -m pytest functional_tests\test_m365_source_citations.py -q -p no:cacheprovider: 34 passed
  • python -m pytest ui_tests\test_v2_m365_source_citations.py -q -p no:cacheprovider: 4 passed (V2 chips, source card and link attributes, missing-record card, Documents pane at desktop and phone widths, classic links, no /api/get_citation calls)
  • Isolated venv (python -m venv --system-site-packages + pip install -U pyopenssl → 26.4.0; the shared interpreter's pyOpenSSL 25.3.0 breaks Semantic Kernel imports), PYTHONPATH=application\single_app;functional_tests:
    python -m pytest functional_tests\test_m365_source_citations.py functional_tests\test_m365_chat_preflight_order.py functional_tests\test_m365_provider_core.py functional_tests\test_orchestration_m365_actions.py functional_tests\test_orchestration_m365_file_actions.py functional_tests\test_chat_cited_source_tracking.py functional_tests\test_workflow_result_masking.py -q -p no:cacheprovider: 253 passed
  • npm run build in application\v2_ui (tsc -b && vite build): passed (existing chunk-size warning only)
  • python .\functional_tests\test_docs_app_surface_coverage.py: 7/7 passed; python .\functional_tests\test_docs_site_quality.py: 6/6 passed (inventory regenerated; unchanged, since no settings, actions or controls were added)
  • python -m pytest functional_tests\route_tests\test_route_blueprint_policy_inventory.py functional_tests\route_tests\test_route_policy_test_coverage.py -q: 17 passed (no routes added or changed)
  • python scripts\check_xss_sinks.py --base-sha fa3422dee --head-sha HEAD <34 changed application files>: passed
  • python scripts\check_broken_access_control.py --base-sha fa3422dee --head-sha HEAD <21 changed Python files>: passed
  • git diff --check: clean
  • Regression comparison: 317 related functional and UI test files (M365, orchestration, collaboration, citation, chat content, workflow, export and history areas) were run one file per process on this branch and on a clean checkout of the base (fa3422dee). Failures were identical on both, all environmental (Cosmos-bound config imports, pyOpenSSL, node_modules missing in the base checkout), and no new failures. test_m365_chat_preflight_order.py AST-loads _set_authorized_chat_request_context, so it now gets the new time-zone helper in its namespace and asserts the recorded zone. test_m365_provider_core.py now allows the added citation_id/citation keys.
  • After merging the updated base (Fix Microsoft 365 sign-in session race and auto-create the workflow key #1716) into this branch:
    • npm run typecheck: passed
    • Docs checks: 7/7 and 6/6 passed
    • python -m pytest functional_tests\test_m365_source_citations.py functional_tests\test_m365_chat_preflight_order.py functional_tests\test_m365_connections.py functional_tests\test_m365_routes.py ui_tests\test_v2_m365_source_citations.py -q: 126 passed, 1 failed. The failure is test_m365_routes.py::test_real_notification_helper_only_targets_subject_and_deduplicates, which fails the same way on the pure base 81e78a34d (ImportError for functions_group in this local environment), so it isn't caused by this PR.
  • An independent code review found five issues, all fixed here with tests: records could be built from any tool's look-alike output; the 100-record cap applied before cited flags; shared orchestration copies didn't refresh m365_citations; workflow answers didn't attach them; and an out-of-range Graph date could fail the tool. While fixing these I also found that the final-event normalizers (document action, compatibility, workflow result and saved analysis) dropped m365_citations; that's fixed too. The two CodeQL findings (an empty except without a comment, an unused import) are fixed in bc43ab5.

Documentation

  • Release notes updated, or not needed (### **(v0.261.303)** → New Features)
  • Feature documentation updated, or not needed (docs/explanation/features/M365_SOURCE_CITATIONS.md; action references for Email, Calendar, SharePoint and OneDrive; docs/reference/chat-controls.md)
  • Fix documentation updated, or not needed

Security checklist

  • New Flask routes include @swagger_route(security=get_auth_security()) (no new routes)
  • Settings sent to non-admin frontends use sanitize_settings_for_user() (no settings sent)
  • Browser JavaScript is served from local SimpleChat static assets only; no CDN-hosted JS
  • No secrets, keys, connection strings, or local-only artifacts are included

Notes for reviewers

  • Trust boundary: annotate_* returns an M365CitedResult (a dict subclass whose records are an attribute, so they're never serialized to the model). The invocation logger keeps only those records, and nothing parses records back out of a result's shape.

  • Display time zone: uses the browser's IANA zone, which both UIs now send as time_zone, rather than the mailbox zone. Mailbox settings need the Calendar action's permission, and Outlook often uses Windows zone names. Orchestration uses the turn's zone when workflow proposals or results are configured; otherwise it uses UTC (documented).

  • Where annotation happens: in get_my_messages/get_my_events after coverage, not in _shape_graph_result, because both use the paginated path. This covers the M365 Email/Calendar actions and the legacy Microsoft Graph action.

  • Owner-only aggregate: used_m365_items in conversation metadata is filtered to the requesting owner; shared viewers get none. Per-message m365_citations travel wherever agent_citations already do, and the M365 history-sharing gate counts them.

  • Merging with PR A (Decide Microsoft 365 approvals in the chat and tidy orchestration retries #1715): Fix Microsoft 365 sign-in session race and auto-create the workflow key #1716 already took 0.261.302 on the base, so PR A needs a new patch number. Whichever of PR A and this PR merges second should take the next free number and put its release-notes section on top. A trial merge with PR A conflicts only in:

    • config.py
    • release_notes.md
    • the MessageInspector.tsx import block (keep PR A's normalizeOrchestrationAttempt and openOrchestrationRecovery imports and this PR's m365ChipLabel, m365SecondaryLine import)

    Everything else merges automatically.

SharePoint/OneDrive files, emails, and calendar events returned by the M365
actions (agent chat, workflows, and Orchestrate) now get deterministic m365-
citation ids, model-facing citation markers, and a fixed list layout. Answers
render them as citation chips with a source card and an Open in
SharePoint/OneDrive/Outlook link, and the conversation drawer Documents pane
lists them with Open online.

- functions_m365_citations: ids, normalizers, https-only URLs, marker and
  display formatting, fail-safe annotation, trusted capture, message and
  conversation aggregation
- Graph mail/event and M365 file tool results carry citation, citation_id,
  citation_instructions, and presentation fields; the annotators return an
  M365CitedResult whose records only the Microsoft 365 plugins can produce
- Invocation logger keeps those records as m365_items before truncation;
  look-alike JSON from other tools never becomes a citation or link
- Chat, workflow, and orchestration answers persist m365_citations with cited
  flags (cited and read items kept first at the 100-record limit); every final
  chat event carries them; the conversation keeps an owner-only
  used_m365_items aggregate rebuilt with used documents
- Collaboration, shared orchestration copies, export, content-safety
  retraction, and the M365 history sharing gate carry the new field
- V2 chips, source card, Documents pane sections, inspector sources; classic
  UI renders m365 ids as safe links or plain text
- Version 0.261.303, docs, release notes, functional and UI tests

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread application/single_app/functions_m365_citations.py Fixed
Comment thread ui_tests/test_v2_m365_source_citations.py Fixed
Paul Lizer (paullizer) and others added 4 commits October 8, 2026 15:02
- Explain why a logging failure in the citation annotation fallback is ignored
- Remove an unused json import from the M365 citation UI test

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolve the version and release-notes conflicts with microsoft#1716: keep VERSION
0.261.303 and keep both release-note sections, v0.261.303 above v0.261.302.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 8, 2026
microsoft#1716 shipped as 0.261.302, the version this branch used, and the open
Microsoft 365 citations PR (microsoft#1718) holds 0.261.303. Move this branch to
0.261.304: config.py, its own release-notes section above v0.261.302, and
the version headers and "Since" notes in its code, tests and docs.

The fix doc also lists the sharing-preferences link and guardrail pin added
when the base was merged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@paullizer
Paul Lizer (paullizer) merged commit 9268a9a into microsoft:paullizer-react-v2-ui Oct 8, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants