Skip to content

Add new sample: da-pnp-samples-guide (declarative agent that discovers PnP DA samples)#163

Draft
sebastienlevert wants to merge 4 commits into
pnp:mainfrom
sebastienlevert:sample/da-pnp-samples-guide
Draft

Add new sample: da-pnp-samples-guide (declarative agent that discovers PnP DA samples)#163
sebastienlevert wants to merge 4 commits into
pnp:mainfrom
sebastienlevert:sample/da-pnp-samples-guide

Conversation

@sebastienlevert

Copy link
Copy Markdown
Collaborator

New sample: da-pnp-samples-guide

A declarative agent for Microsoft 365 Copilot that helps developers discover declarative agent samples in this repository, walks them through cloning and adapting them, and guides them on how to bootstrap their own agent inspired by them. The agent is itself a sample, shipped alongside the samples it teaches you to find.

What it shows

  • Declarative agent manifest v1.7 with 6 conversation starters (each with title + text), a WebSearch capability scoped to this repo, and one API plugin action.
  • API plugin manifest v2.4 wired to a hand-stripped subset of the public, unauthenticated GitHub REST API:
    • searchRepositories
    • searchCode (always scoped with repo:pnp/copilot-pro-dev-samples)
    • getRepo
    • getRepoContent
    • getRepoReadme
  • Adaptive Cards tailored per function (list view for searches, detail view for repo metadata, open-on-GitHub action button on every card).
  • Documented handling of the 60 req/hour per-IP unauthenticated rate limit with fallback guidance baked into description_for_model and instruction.txt.
  • Standard PnP M365Agent/ layout, Teams app manifest v1.24, Microsoft 365 Agents Toolkit v1.9 provision pipeline.

How to try it

git clone https://github.com/pnp/copilot-pro-dev-samples.git
cd copilot-pro-dev-samples/samples/da-pnp-samples-guide/M365Agent
wiqd agent provision --env dev

Then open Microsoft 365 Copilot, pick "Copilot PnP Samples Guide", and try a starter like "Find me a sample that uses Code Interpreter".

Validation

  • wiqd agent validate --mode static → ✔ No issues found
  • wiqd agent package --env dev → ✔ Agent packaged (8.7 KB .zip)

Why no GitHub MCP?

The official https://api.githubcopilot.com/mcp/ server requires OAuth (verified — returns 401 anonymously). The API-plugin path keeps this sample runnable with zero credentials. If/when a public, anonymous GitHub MCP server lands, this sample is a clean migration candidate to RemoteMCPServer runtime.

Known follow-ups

  • Placeholder icons: color.png, outline.png, and large.png are auto-generated solid-blue PnP placeholders. Happy to swap in proper branded icons before merge if there is a preferred design.
  • No screenshots yet: assets/screenshot-discovery.png and assets/screenshot-clone.png are referenced in the README but not captured. Will add once provisioned into a tenant.
  • Authors: registered under sebastienlevert in samples.json since I am the one submitting. Open to adjusting attribution if PnP convention suggests otherwise.

Inspiration

Built while writing a blog post (https://themanifest.dev/) about how teams find ideas for their next declarative agent in this very repo. The post sends readers here; this sample sends them back. The recursion is intentional.


Closes nothing — net-new sample.

sebastienlevert and others added 3 commits June 12, 2026 19:13
A declarative agent for Microsoft 365 Copilot that helps developers discover declarative agent samples in this repository, walks through cloning and adapting them, and guides them on bootstrapping their own agent.

The agent uses:
- Declarative agent manifest v1.7 with 6 conversation starters
- API plugin manifest v2.4 wired to a hand-stripped subset of the public, unauthenticated GitHub REST API (searchRepositories, searchCode, getRepo, getRepoContent, getRepoReadme). Auth: None.
- WebSearch capability scoped to this repo as a low-cost grounding fallback.
- Rate-limit handling for the 60 req/hour per IP unauthenticated GitHub API limit, with fallback guidance baked into description_for_model and instruction.txt.

Validated with 'wiqd agent validate --mode static'. Packaged with 'wiqd agent package --env dev' (8.7 KB).

Follows the existing PnP M365Agent/ project layout (Teams app manifest v1.24, M365 Agents Toolkit v1.9 provision pipeline). Authors registered as sebastienlevert in samples.json.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The v2.1 plugin schema accepts an empty 'localization': {} block, but the v2.4 DevPortal validator rejects it during teamsApp/validateAppPackage. Discovered when provisioning to a tenant.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GitHub's GET /search/code endpoint requires authentication (returns 401 anonymous), so the original agent could not actually discover samples in the dev tenant.

Replaced it with two narrowly-scoped operations that read the structured sample registry at .github/samples.json (~100 KB, fully anonymous):

- getSamplesRegistry: GET /repos/pnp/copilot-pro-dev-samples/contents/.github/samples.json (the primary discovery tool)
- listSamples: GET /repos/pnp/copilot-pro-dev-samples/contents/samples (fallback for brand-new samples not yet in the registry)

The registry provides each sample's name, title, shortDescription, longDescription, metadata (PLATFORM, LANGUAGE, API-PLUGIN, GRAPH-CONNECTOR), thumbnails, authors, and Folder name. Client-side filtering on these fields covers every discovery scenario the original search/code path was supposed to handle, and does so with zero auth.

Updates:
- github-openapi.json: dropped /search/code; added getSamplesRegistry and listSamples; kept searchRepositories, getRepo, getRepoContent, getRepoReadme
- ai-plugin.json: dropped searchCode function block; added getSamplesRegistry and listSamples with Adaptive Cards; rewrote top-level description_for_model with explicit routing rules
- declarativeAgent.json: kept 6 starters, tuned the API-plugin starter to steer toward registry metadata filtering
- instruction.txt: rewrote the discovery strategy block; documents the registry-first pattern and the URL convention for sample folders
- README.md: updated Features and Rate-limit sections to reflect the registry-driven approach

Validated with wiqd agent validate --mode static (clean). Re-packaged and re-provisioned to the dev tenant; same Title ID, no new auth prompts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sebastienlevert

Copy link
Copy Markdown
Collaborator Author

Heads up reviewers — this PR went through a meaningful rework after the initial commit. The first version used GitHub's GET /search/code endpoint, which requires authentication (401 anonymous) and therefore cannot work as a tool in this agent.

Switched to a registry-driven discovery model that reads .github/samples.json (the structured sample registry in this very repo, ~100 KB, fully anonymous). Two new operations:

  • getSamplesRegistryGET /repos/pnp/copilot-pro-dev-samples/contents/.github/samples.json
  • listSamplesGET /repos/pnp/copilot-pro-dev-samples/contents/samples

The registry has each sample's name, title, shortDescription, longDescription, metadata, thumbnails, authors, and Folder. Client-side filtering on those fields covers every discovery scenario the original search/code path was supposed to handle, with zero auth required.

Other changes in this round:

  • Dropped searchCode function from ai-plugin.json; added two new functions with Adaptive Cards
  • Rewrote the top-level description_for_model with explicit routing rules
  • Tuned the API-plugin conversation starter to steer the LLM toward registry metadata filtering
  • Rewrote the instruction discovery block
  • Updated the README Features + Rate-limits sections

Re-validated with wiqd agent validate --mode static (clean), re-packaged, and re-provisioned to my dev tenant. Same Title ID, no new auth prompts. Tested the registry-first routing on the live agent — works.

(I might want to ship this PR as is and chase the GitHub MCP migration in a follow-up once an anonymous PnP-scoped MCP server lands, instead of holding this one open.)

GitHub's GET /search/code requires auth, so true code search isn't an option for this anonymous agent. Layered in GET /repos/.../git/trees/main?recursive=1 (the repo-scoped tree endpoint, fully anonymous, 1 call returns all 3,172 file paths, not truncated) as the second discovery tool.

Discovery is now a 3-tier strategy:

1. getSamplesRegistry — broad metadata search (Folder, metadata keys, description keywords)
2. getRepoTree — path-pattern search (e.g., 'samples with ai-plugin.json + OpenAPI spec', 'samples with a Python backend', 'samples wired for ATK')
3. getRepoContent — targeted file reads to verify a capability or term, only after registry/tree narrows the candidates

Updates:
- github-openapi.json: added GET /repos/pnp/copilot-pro-dev-samples/git/trees/{tree_sha} with recursive query param; added GitTree + GitTreeEntry schemas
- ai-plugin.json: added getRepoTree function block with description, response_semantics, and FactSet+OpenUrl Adaptive Card; rewrote top-level description_for_model with the 3-tier routing rules
- instruction.txt: added 'File-structure discovery' block with 5 glob examples and the do-not-iterate-every-blob warning
- declarativeAgent.json: re-tuned the 6th conversation starter to 'Samples with an OpenAPI spec' so it exercises the new tree path
- README.md: added file-tree bullet to Features and updated the rate-limit math

Validated clean, re-packaged, re-provisioned to the dev tenant. Same Title ID (T_78ac3972-...), same deep link, no new auth prompts. Package size: 11.4 KB to 13.4 KB.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@garrytrinder garrytrinder left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the sample @sebastienlevert! Great concept — an agent that helps discover other samples is very useful. A few items need addressing before we can merge.

Blockers

  1. Thumbnail in .github/samples.json should show a screenshot of the agent in action, not just the icon
  2. Missing additionalMetadata.sampleTag in m365agents.yml

Suggestions

  1. App manifest schema outdated — currently v1.24, needs updating to v1.28
  2. Missing AGENT-TYPE metadata in .github/samples.json entry

@@ -0,0 +1,42 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/teams/v1.24/MicrosoftTeams.schema.json",
"manifestVersion": "1.24",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

App manifest schema is on v1.24 — please update to the latest v1.28:

"$schema": "https://developer.microsoft.com/json-schemas/teams/v1.28/MicrosoftTeams.schema.json",
"manifestVersion": "1.28",

# yaml-language-server: $schema=https://aka.ms/m365-agents-toolkits/v1.9/yaml.schema.json
# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file
# Visit https://aka.ms/teamsfx-actions for details on actions
version: v1.9

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add additionalMetadata with the correct sampleTag after the version line:

additionalMetadata:
  sampleTag: pnp-copilot-pro-dev:da-pnp-samples-guide

Also, please ensure there is no projectId property (none found currently ✅).

Comment thread .github/samples.json
"key": "PLATFORM",
"value": "None"
},
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing required AGENT-TYPE metadata entry. Please add:

{
  "key": "AGENT-TYPE",
  "value": "Declarative Agent"
}

Comment thread .github/samples.json
{
"url": "https://github.com/pnp/copilot-pro-dev-samples/raw/main/samples/da-pnp-samples-guide/M365Agent/appPackage/color.png",
"alt": "Copilot PnP Samples Guide declarative agent icon",
"order": 100,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thumbnail points to M365Agent/appPackage/color.png — ideally thumbnails should be in the assets/ folder and show a screenshot of the agent in action, not just the icon.

@garrytrinder garrytrinder marked this pull request as draft June 15, 2026 13:13
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