Skip to content

feat: experimental support for Microsoft 365 Copilot Cowork custom skills #913

Description

Summary

Microsoft 365 Copilot Cowork (Frontier preview) discovers custom skills from <OneDrive>/Documents/Cowork/skills/<name>/SKILL.md. The format is identical to APM's existing agentskills.io SKILL.md spec, so APM users on Frontier could one-shot-deploy their APM skills to Cowork — today they copy files by hand.

This issue tracks adding a first-class, experimentally-gated cowork target so apm install --target cowork --global writes skills straight into the OneDrive-synced folder.

Upstream reference: https://learn.microsoft.com/en-us/microsoft-365/copilot/cowork/use-cowork#create-custom-skills

Design decisions (agreed)

Decision Choice
Experimental flag cowork in core/experimental.py::FLAGS (off by default)
Gating style Visible-but-disabled — target profile always in KNOWN_TARGETS, infra fields always present but inert; user-observable behaviour strictly flag-gated
OneDrive resolution Auto-detect macOS (~/Library/CloudStorage/OneDrive-*) and Windows (ONEDRIVE env); Linux env-var-only; APM_COWORK_SKILLS_DIR override
Scope User-scope only (--global); project-scope errors cleanly
Target model First-class cowork target, never auto-detected, opt-in only
Primitives Skills only; agents/instructions/hooks/prompts skipped with a single summary [!] warning
Limits Warn-only when > 50 skills or any SKILL.md > 1 MB; install proceeds
Frontier messaging Silent — docs only

Architectural changes (high level)

  • New experimental flag cowork in src/apm_cli/core/experimental.py.
  • New src/apm_cli/integration/cowork_paths.py — pure-function OneDrive resolver with validate_path_segments + ensure_path_within guards.
  • Optional user_root_resolver: Callable[[], Path | None] field on TargetProfile; only set by the cowork profile.
  • Carve-out in BaseIntegrator.validate_deploy_path / get_integration_prefixes for dynamic-root profiles.
  • cowork entry in KNOWN_TARGETS (skills-only primitive allow-list).
  • Gating in active_targets*: requires flag on, requires user scope, requires resolver to return a path; never auto-detected.
  • Cowork-only warn branch in SkillIntegrator for 50-skill and 1-MB caps.
  • New docs page docs/src/content/docs/integrations/cowork.md.

Non-goals

  • Publishing skills to M365 tenants via any API (Cowork has no public upload API).
  • Discovering or consuming existing Cowork skills as APM dependencies.
  • Cowork runtime features (schedules, approvals, side-panel metadata).
  • Linux auto-detection of OneDrive.
  • Skill-name-collision detection against Cowork's OOTB skills.

Acceptance

  • apm experimental enable cowork registers the flag.
  • With flag off, apm install --target cowork prints a targeted enable hint and is a no-op.
  • With flag on, apm install --target cowork --global deploys SKILL.md to the resolved OneDrive directory; non-skill primitives are skipped with one summary warning.
  • Without --global, project-scope is cleanly rejected.
  • APM_COWORK_SKILLS_DIR override is path-safety validated.
  • Full unit suite green; docs build green; APM Expert Review Panel pass.

Plan

Plan exists in session workspace and is being executed in worktree feat/cowork-skills off upstream/main. PR will be opened as draft against upstream/main once implementation, tests, and docs are complete and the review panel has signed off.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/multi-targetMulti-target deploy spec, target directory creation, agent surface routing.experimentalpriority/highHuman-set high priority; not scope approval, a release commitment or a required milestone.status/acceptedHuman scope approval; verify the issue's approval record and review contact before work.status/triagedAutomated advice completed; deduplication only. Not human approval; silence is not approval.theme/portabilityOne manifest, every target. Multi-target deploy, marketplace, packaging, install.type/featureNew capability, new flag, new primitive.

    Type

    No type

    Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions