---
type: Playbook
id: https://w3id.org/ktl/knowledge/playbooks/docent-in-m365-copilot
title: The docent in Microsoft 365 Copilot
description: How a person gets ktl-docent-m365, the docent packed with a snapshot of the bundle as a Microsoft 365 Copilot custom skill, from a release or by building it, adds it to a declarative agent, checks the first answer and keeps it current, what to do when a step fails, and why only the read-only roles go there.
genre: how-to
resource: docs/m365.md
sources:
  - resource: docs/m365.md
  - resource: skills/ktl-sidecar/references/m365.md
  - resource: skills/ktl-sidecar/templates/m365/ktl-docent-m365.md
  - resource: skills/ktl-sidecar/templates/m365/knowledge-m365.sh
generated:
  by: process:ktl-librarian
  at: "2026-10-26T20:05:58Z"
status: draft
isPartOf:
  - https://w3id.org/ktl/knowledge/playbooks/ktl-sidecar-skill
references:
  - https://w3id.org/ktl/knowledge/playbooks/ktl-docent-skill
  - https://w3id.org/ktl/knowledge/playbooks/ktl-librarian-skill
  - https://w3id.org/ktl/knowledge/playbooks/releasing
  - https://w3id.org/ktl/knowledge/glossary/trust-label
relatedTo:
  - https://w3id.org/ktl/knowledge/explanation/three-lines-of-defence
  - https://w3id.org/ktl/knowledge/explanation/domain-schemas
verified:
  - by: process:ktl-librarian
    at: "2026-10-29T00:48:33Z"
---

# Overview

**ktl-docent-m365** is the docent as a custom skill for a Microsoft 365 Copilot declarative agent. It is not a skill of its own: it puts [ktl-docent](ktl-docent-skill.md) into Copilot. Copilot runs a skill with no repository, shell or network, so the skill carries a **snapshot** of the bundle and answers from it. Every answer names the snapshot (repository, revision, build date) and the trust label of each concept it used, in the same words ktl-docent uses. It cannot check a value at its source or write `.lokf/feedback.md`. So it says so, and hands the reader a ready-to-paste Miss or Disagreement line to file in the repository instead.

Getting it running takes three steps, in this order: get the zip, add it to an agent, then ask it something and check that the answer names the snapshot. The short route installs nothing.

# 1. Get the zip

**From a release.** The release workflow attaches `ktl-docent-m365-<tag>-<repository>.zip` beside the bundle zip on every release whose bundle changed. `<repository>` is the repository's name, or the name its `KNOWLEDGE_RELEASE_NAME` variable sets. A release with no such asset means one of two things:

- the bundle did not change since the last release that carries one, and the reader takes the zip from that earlier release;
- the repository's sidecar has no `.lokf/m365/`, and its releases carry the bundle zip alone.

**Or build it.** A repository on another forge, or on none, runs the builder the release workflow runs, on its bundle folder. It needs bash and `zip`:

```bash
.lokf/m365/knowledge-m365.sh --repo-url https://github.com/me/my-repo --ref v1.2.0 .lokf/knowledge ./dist
```

It writes `dist/ktl-docent-m365/` (with `SKILL.md`, `SNAPSHOT.md` and `knowledge/`) and `dist/ktl-docent-m365.zip`. In a git clone only tracked files are copied, and hidden files such as `.obsidian/` are left out. With `SOURCE_DATE_EPOCH` set, one input gives one zip. The build writes nothing and exits 1 if a skill breaks one of Copilot's limits:

- `SKILL.md` over 20,000 characters;
- folders more than 3 deep;
- file types Copilot does not accept;
- more than 350 files;
- more than 10 MB, the toolkit's limit on the whole app package;
- symbolic links.

Agent Builder's own limit is a 50 MB zip, which `skills/ktl-sidecar/references/m365.md` gives from Microsoft's page on custom skills, preview as of 2026-09.

# 2. Add it to an agent

Custom skills are in preview, only for tenants in Microsoft's Frontier program and not with Information Barriers, so the page has the reader check that first. Without the preview, both routes fail with errors that do not say why. Two routes take the same zip, and the page recommends **Agent Builder** unless the reader already develops agents with the toolkit.

With Agent Builder, nothing is installed: create or open an agent in Microsoft 365 Copilot and add the zip as a skill. If Agent Builder says skill attachments require the full Copilot Studio experience, the reader copies the agent to Copilot Studio and adds the zip there. That needs a Copilot Studio licence or trial.

With the **Agents Toolkit CLI** (`atk`, for developers, on Node.js):

1. Log in, scaffold or reuse a declarative agent, and change into its folder.
2. Export `TEAMSFX_AGENT_SKILLS=true` and `ATK_FRONTIER=true`. Skills are hidden without the variable its version reads: `TEAMSFX_AGENT_SKILLS` in the 1.1.17 release, `ATK_FRONTIER` from the 1.1.18 betas on.
3. Run `atk add skill --from <zip> -i false`, then `atk provision --env dev` and `atk preview --env dev`, in the same shell. Without the variable, the toolkit packs the agent without the skill's files.

The page says to skip `atk validate` for now, because it rejects the `agent_skills` entry the toolkit itself wrote. Whichever route the reader takes, an agent cannot yet have skills and embedded files together.

# 3. Ask it something

Ask the agent a question the bundle answers, such as what a service does or who owns it. The answer names the snapshot, its version and build date, and each concept it rests on with a [trust label](../glossary/trust-label.md). An answer with no snapshot in it did not come from the skill.

When the docent cannot answer, or two concepts disagree, it ends with one line to paste into the repository's `.lokf/feedback.md`, and `SNAPSHOT.md` says where to send it. The docent never records the gap itself. A Miss line starts with the reader's question in quotes. It says whether a concept looked relevant from `index.md` and did not answer, or nothing relevant was listed. A Disagreement line says which version the answer gave, or that it gave both. Filed in the repository, the line reaches [ktl-librarian](ktl-librarian-skill.md), which turns it into a concept or a question for the curator.

# Keep it current

The snapshot does not update itself. After each release that changes the bundle, take the new zip and add it again. The workflow packs the skill only when the bundle changed, so a release with new instructions and the same bundle carries no new zip. For that tag, run the workflow by hand with `force`.

# If something goes wrong

- **The release has no `ktl-docent-m365-…` asset.** The bundle did not change since the last release that carries one, or the repository's sidecar has no `.lokf/m365/`.
- **The build exits 1.** The skill breaks one of Copilot's limits, the output names which, and nothing is written.
- **The build says `zip not found`.** The folder is built but not zipped: install `zip`, or zip the folder by hand before adding it.
- **`atk add skill` is not a command** (`UnknownCommandError`). Export both `TEAMSFX_AGENT_SKILLS=true` and `ATK_FRONTIER=true`.
- **`atk add skill` says `InvalidProjectError`.** It ran outside the agent's project: change into the folder `atk new` created, or pass `--folder`.
- **`atk validate` says `property name must be valid` for `agent_skills`.** The newest published manifest schema, v1.8, has no such property yet, and the toolkit's own `add skill` wrote the entry, so the zip is not at fault. Skip it, and let `provision` decide.
- **`atk provision` fails at `teamsApp/validateAppPackage` with `Unrecognized member 'agent_skills'`.** Microsoft's service refused the entry: check that the tenant has custom skills. `teamsApp/create` has already registered an app by then, which the reader deletes in the Teams Developer Portal if they give up.
- **Agent Builder says skill attachments require the full Copilot Studio experience.** Copy the agent to Copilot Studio and add the zip there. If Copilot Studio says sign-up is disabled, only an admin can grant the licence.
- **Agent Builder or the toolkit refuses the skill for another reason.** The agent may already have embedded files. That is a preview limit, not a fault in the zip.

# Which roles go to Copilot

`.lokf/m365/` holds one instructions file per read-only role, named after the skill it becomes: `ktl-docent-m365.md`, not `SKILL.md`, so no installer lists it. The builder packs each file into its own zip. An auditor, the third line, would be `ktl-auditor-m365.md` beside it, with no change to the builder, workflow or checks. The sidecar and librarian need a repository and a shell, so they have no Copilot form. The curator has none yet. It needs a write action the agent can call and an identity that is not a forge login. The curator's `references/domain-schemas.md` holds the shape of that identity record (see [domain-schemas](../explanation/domain-schemas.md)).

A host's copy under `.lokf/m365/` is what its releases pack, so a host that edits it changes what its readers' Copilot follows. Its trust labels must match ktl-docent's, and the repository checks enforce that.

## Open questions

- 2026-10-03, process:ktl-librarian: Microsoft's page on custom skills (updated 2026-09-04) says the Agents Toolkit takes a skill directory and that `.zip` isn't supported. `skills/ktl-sidecar/references/m365.md` says `atk add skill --from` takes a zip from any path, as checked against the toolkit's source, and this concept follows it. Which holds for the toolkit a reader installs?
- 2026-10-19, process:ktl-librarian: the limits list already gives Agent Builder's 50 MB zip beside the toolkit's 10 MB app package, as `skills/ktl-sidecar/references/m365.md` line 18 does. Whether `atk add skill --from` takes a zip stays open: `skills/ktl-sidecar/references/m365.md` says it does, from the toolkit's source up to the 1.1.18 betas, Microsoft's page says it takes a directory only, and no file in the repository records the test that would settle it.
