The Citadel · 20 min mission
Declarative Agents, API Plugins, and OpenAPI Tool Design
Package Microsoft 365 Copilot agents with narrow REST actions, response semantics, citations, and safe write contracts.
Orientation
This guide is for developers and platform teams packaging a Microsoft 365 Copilot agent in source control. It covers the manifest stack, API plugin design, OpenAPI constraints, citations, auth, and the review process for safe live actions.
Declarative agents extend Microsoft 365 Copilot with instructions, conversation starters, knowledge, capabilities, and actions. They are packaged rather than improvised: a Microsoft 365 app manifest references a declarative agent manifest, and action references point to API plugins or MCP plugins.
API plugins are the REST path. Their quality depends on the OpenAPI contract, plugin manifest metadata, operation descriptions, response semantics, auth, and backend policy. Build task-level operations such as searchJiraIssues or prepareConfluencePublish; do not expose the raw source-system API surface and hope the model chooses safely.
Use This When / Avoid This When
Use declarative agents when
You want a Microsoft 365 Copilot-hosted agent with source-controlled instructions, knowledge/capabilities, conversation starters, and a small set of API or MCP actions.
Avoid this path when
The workflow needs a custom model runtime, proactive non-Copilot channels, long-running orchestration, or external automation that is better owned by Copilot Studio, Power Automate, or a backend.
How to use this interactive section
The OpenAPI Tool Design Checker is a contract review exercise. Use it before wiring a real API into Copilot.
- Start with the operation you want the agent to call.
- Check whether the name says the business task, not the transport detail.
- Inspect whether the request schema is flat, bounded, and safe for the model to fill.
- Verify that the response can support citations through stable title, subtitle, URL, and concise fields.
- Treat low scores as backend design work, not prompt-writing work.
OpenAPI Tool Design Checker
OpenAPI tool design checker
Design an LLM-ready API operation
Microsoft treats OpenAPI metadata as orchestration metadata. Narrow names, precise descriptions, flat schemas, citations, and safe-write fields decide whether Copilot can use the tool reliably.
| Layer | Owns | Failure to avoid |
|---|---|---|
| Declarative agent manifest | Agent identity, instructions, conversation starters, knowledge references, and action references | Broad instructions that allow the agent to act outside the business domain |
| Plugin manifest | Function metadata, API runtime, auth declarations, and response semantics | Missing response semantics that prevent useful citations or result selection |
| OpenAPI document | Operation IDs, descriptions, request schema, response schema, and server URLs | Nested, polymorphic, or huge schemas that are hard for Copilot to call reliably |
| Backend facade | Auth enforcement, field allowlists, rate limits, source normalization, idempotency, and audit | Passing raw Jira or Confluence credentials and payloads directly to the agent |
appPackage/
manifest.json
declarativeAgent.json
instruction.txt
color.png
outline.png
ai-plugin.json
apiSpecificationFile/openapi.yaml
adaptiveCards/result.json| Artifact | Current guide baseline | Review question |
|---|---|---|
| Declarative agent manifest | Use the current v1.7 schema for new examples unless Microsoft publishes a later GA schema before implementation | Are instructions, capabilities, conversation starters, knowledge, and actions scoped to the exact business task? |
| Plugin manifest | Use plugin manifest schema v2.4 for API plugins and RemoteMCPServer plugin paths | Do functions, auth, response semantics, and runtime URLs match the API or MCP server? |
| OpenAPI document | Prefer small, flat, task-level operations with explicit descriptions, bounded inputs, examples, and concise responses | Would a reviewer understand exactly when Copilot should call this operation and what it must never do? |
| Backend service | Own source auth, rate limits, field allowlists, pagination, idempotency, and audit outside the model | Can the backend reject unsafe requests even if the agent asks for them? |
{
"$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.7/schema.json",
"version": "v1.7",
"name": "ACME-OPS release assistant",
"description": "Helps program leads review ACME-OPS release risk and prepare approved weekly reports.",
"instructions": "Use only approved ACME-OPS sources. Cite Jira and Confluence evidence. Never publish without explicit approval.",
"conversation_starters": [
{
"title": "Review release risk",
"text": "Review ACME-OPS 2026.09 release risk and show source issues."
}
],
"actions": [
{
"id": "acmeOpsReleaseApi",
"file": "ai-plugin.json"
}
]
}paths:
/release-risk:
post:
operationId: searchJiraIssues
summary: Find ACME-OPS release issues for risk review
description: >
Runs one approved JQL query, returns normalized issue facts,
and does not mutate Jira or Confluence.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [projectKey, fixVersion]
properties:
projectKey:
type: string
enum: [ACME-OPS]
fixVersion:
type: string
example: "2026.09"
maxResults:
type: integer
maximum: 50
responses:
"200":
description: Bounded source-linked release issuesSafe API plugin design sequence
Hide source-system complexity behind a facade
Create one business operation per task. For Jira, the facade owns JQL, field allowlists, pagination, source URLs, and error normalization.
Make descriptions operational
Operation descriptions should say when to use the tool, what arguments mean, what the tool returns, and what it never mutates.
Add response semantics and citations
Return title, subtitle, URL, and concise fields so Copilot can select, cite, and display results without dumping raw payloads.
Split write operations
Use prepare and commit operations. Prepare returns preview and approval ID. Commit re-reads live state, checks approval, uses idempotency, writes once, and records audit.
Operation Naming
Bad
callJiraApi, search, updatePage, or runAnyJql. These names hide risk, invite broad parameters, and give the orchestrator weak selection signals.
Better
searchJiraIssues, getReleaseRiskFacts, prepareConfluencePublish, and commitConfluencePublish. These names say the business task and imply the mutation boundary.
| Risk | Why it matters | Safer design |
|---|---|---|
| Nested or polymorphic schemas | Complex request shapes are harder for Copilot to fill and are listed in known issue guidance for extensibility | Flatten request bodies, use enums, add examples, and split unrelated operations |
| Large result arrays | The model may ignore, truncate, or poorly summarize long arrays and raw payloads | Filter server-side, paginate, return top results, and expose citable business fields |
| Ambiguous auth | OAuth, Entra SSO, API key, and no-auth support differ by plugin type and tenant configuration | Prefer OAuth or Entra SSO for production and document redirect URI, scopes, consent, and stale credential recovery |
| Write confirmation only in UI | A confirmation prompt is helpful but not a complete safety control | Use backend prepare/commit, approval records, idempotency, and live re-read before mutation |
| Missing response semantics | Copilot cannot turn raw JSON into useful citations without a mapping contract | Return stable title, subtitle, and url fields and map them in the plugin manifest |
Developer workflow with Agents Toolkit
Validate the local environment
Run toolkit health checks before provisioning. Confirm tenant, license, app registration, sideloading, and local tunnel requirements.
Scaffold the package
Create the declarative agent project, keep manifests in source control, and review generated schema versions instead of trusting scaffold defaults.
Add one action at a time
Import or generate the OpenAPI document, select only needed operations, and verify function names match operation IDs.
Test selection and citations
Use developer/debug mode where available, inspect whether Copilot chose the right action, and verify response semantics produce useful citations.
Package for admin review
Validate, package, and publish through the approved tenant process. Production users should not depend on ad hoc sideloading.
Knowledge check
Why put Jira behind a backend facade instead of exposing raw Jira REST as an API plugin?
Reach the end and this star joins your charted sky.