Integrating Microsoft Copilot Declarative Agents with Azure AI Search - A TypeSpec Approach

The Power of Direct API Integration

In today’s AI-driven workplace, Microsoft 365 Copilot has become an indispensable tool for productivity. However, its true potential is unlocked when integrated with organizational knowledge sources. While OneDrive/SharePoint integration provides a simple solution, and custom engine agents offer maximum flexibility, Azure AI Search strikes the perfect balance - giving developers control over indexing and relevance without the complexity of maintaining full language model deployments.

Microsoft Copilot Declarative Agent - Azure AI Search Results

Direct API integration is crucial because:

  • It allows precise control over data chunking and parsing
  • Enables custom relevance algorithms tailored to your domain
  • Provides hybrid search capabilities (lexical, semantic, and vector)
  • Maintains security through Azure’s robust access controls
  • Offers cost-effectiveness compared to full custom engine solutions

High-Level Steps to Configure Azure AI Search with Blob Storage

  1. Create Azure AI Search service (Standard tier recommended)

  2. Upload documents to Blob Storage container (e.g., benefits PDFs/handbooks)

  3. Connect data source (Blob Storage → AI Search)

  4. Add a skillset to chunk and embed files
    Use Azure AI Search skills to split documents into chunks and generate vector embeddings. For example, use a SplitSkill to break documents into pages and an AzureOpenAIEmbeddingSkill to create embeddings for each chunk. This enables more accurate and efficient semantic search.

  5. Enable semantic search (Optional: for better relevance)

  6. Test queries in Search Explorer

  7. Copy endpoint/key for Copilot integration

json
{
"name": "rag-1747904935717-skillset",
"description": "Skillset to chunk documents and generate embeddings",
"skills": [
{
"@odata.type": "#Microsoft.Skills.Text.SplitSkill",
"name": "#1",
"description": "Split skill to chunk documents",
"context": "/document",
"defaultLanguageCode": "en",
"textSplitMode": "pages",
"maximumPageLength": 2000,
"pageOverlapLength": 500,
"maximumPagesToTake": 0,
"unit": "characters",
"inputs": [
{ "name": "text", "source": "/document/content" }
],
"outputs": [
{ "name": "textItems", "targetName": "pages" }
]
},
{
"@odata.type": "#Microsoft.Skills.Text.AzureOpenAIEmbeddingSkill",
"name": "#2",
"context": "/document/pages/*",
"resourceUri": "https://aiservices-openai.openai.azure.com",
"apiKey": "<redacted>",
"deploymentId": "text-embedding-ada-002",
"dimensions": 1536,
"modelName": "text-embedding-ada-002",
"inputs": [
{ "name": "text", "source": "/document/pages/*" }
],
"outputs": [
{ "name": "embedding", "targetName": "text_vector" }
]
}
],
"indexProjections": {
"selectors": [
{
"targetIndexName": "rag-1747904",
"parentKeyFieldName": "parent_id",
"sourceContext": "/document/pages/*",
"mappings": [
{ "name": "text_vector", "source": "/document/pages/*/text_vector" },
{ "name": "chunk", "source": "/document/pages/*" },
{ "name": "title", "source": "/document/title" }
]
}
],
"parameters": {
"projectionMode": "skipIndexingParentDocuments"
}
}
}

Test Your Azure AI Search Query with Postman

Before integrating your Azure AI Search index with Copilot or any other application, it’s a best practice to test your search endpoint using tools like Postman. This ensures your index is returning the expected results and your API is functioning correctly.

You can use the following sample POST request in Postman to validate your setup:

Endpoint:
https://${AISearchServerURL}/indexes/${indexname}/docs/search?api-version=2025-05-01-preview

Headers:

  • api-key: <your-search-service-admin-key>
  • Content-Type: application/json

Body:

json
{
"search": "Health Benefits",
"top": 10,
"select": "title, chunk"
}

Validate Azure AI Search Results with Postman

Postman - Validating Azure AI Search Results

Integrating Azure AI Search API with Microsoft Copilot Declarative Agent using TypeSpec

TypeSpec provides a streamlined way to define your API contracts and generate all necessary configuration files automatically. Here’s how to build the complete solution:

plaintext
/perks-agent
├── main.tsp # Main TypeSpec definition
├── actions-search-api.tsp # Azure AI Search actions

To generate the files needed for a Copilot declarative agent API-based plugin, you need two main TypeSpec files: main.tsp and actions-search-api.tsp. Below is a description of each file, their purpose, and example content.

1.main.tsp

The main.tsp file defines the overall agent, its instructions, and how it interacts with the Azure AI Search API actions. It sets up the agent’s metadata, instructions for handling user queries, and links to the actions defined in actions-search-api.tsp.

Example:

typescript
import "@typespec/http";
import "@typespec/openapi3";
import "@microsoft/typespec-m365-copilot";
import "./actions-search-api.tsp";

using TypeSpec.Http;
using TypeSpec.M365.Copilot.Agents;
using TypeSpec.M365.Copilot.Actions;

@agent(
"Perks Agent",
"Declarative agent created with Microsoft 365 Agents Toolkit and TypeSpec for Microsoft 365 Copilot."
)

@instructions("""
...instructions as provided in your prompt...
""")

@conversationStarter(#{
title: "Welcome to the Perks Assistant!",
text: "What employee benefits and perks are available to me?"
})

namespace perksagent {
@service
@server(global.AISearchAPI.SERVER_URL)
@actions(global.AISearchAPI.ACTIONS_METADATA)
namespace AISearchAPIActions {
op searchPerks is global.AISearchAPI.searchPerks;
}
}

2. actions-search-api.tsp

This file defines the Azure AI Search API actions, including the endpoint, authentication, request/response models, and metadata for Copilot. It describes how the agent will interact with the Azure AI Search REST API.

typescript
import "@typespec/http";
import "@microsoft/typespec-m365-copilot";

using TypeSpec.Http;
using TypeSpec.M365.Copilot.Actions;

@service
@server(AISearchAPI.SERVER_URL)
@actions(AISearchAPI.ACTIONS_METADATA)
namespace AISearchAPI {
const ACTIONS_METADATA = #{
nameForHuman: "Perks Agent",
descriptionForHuman: "Helps users find info about employee benefits, perks, and company policies using Azure AI Search.",
descriptionForModel: "Helps users find info about employee benefits, perks, and company policies using Azure AI Search.",
legalInfoUrl: "https://docs.github.com/en/site-policy/github-terms/github-terms-of-service",
privacyPolicyUrl: "https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement"
};

const SERVER_URL = "https://search-perks-agent.search.windows.net";

@useAuth(ApiKeyAuth<ApiKeyLocation.header, "api-key">)
@route("/indexes/rag-1747904935717/docs/search")
@card(#{ dataPath: "$.value", title: "$.title", url: "$.chunk", file: "adaptiveCards/searchResults.json" })
@post op searchPerks(
@body post: DataRequest,
@query("api-version") apiVersion: string = "2025-05-01-preview",
): DataResponse;

model DataRequest {
search: string;
top?: integer = 5;
select?: string = "title,chunk";
}

model DataResponse {
value: DataItem[];
}
model DataItem {
title: string;
chunk: string;
}
}

3. API Key Authentication

To secure your Azure AI Search calls, register an API key in the Teams Developer Portal. You can do this via the Agents Toolkit in VS Code or manually:

  1. Open the Teams Developer Portal
    Navigate to Tools → API key registration.

  2. Create a new key

    • If you have no registrations: click Create an API key.
    • Otherwise: click New API key.
    • Select Add secret, then paste your API key.
  3. Fill in registration details

    • API key name: A friendly identifier (e.g., “PerksAgentKey”).
    • Base URL: Your API’s base URL (must match an entry in your OpenAPI servers array).
    • Target tenant: Restrict to your home tenant if desired.
    • Target Teams App: Choose Any Teams app, or bind to your published app’s ID.
  4. Save

    • Completing registration returns an API key registration ID. Copy the API Key registration ID
    • Add the API key registration ID in your envrionment file as below
      APIKEYAUTH_REGISTRATION_ID=19de18e2-c0a6-40e9-8257-dddddd

To secure your Azure AI Search calls, use the TypeSpec @useAuth decorator with ApiKeyAuth. For example:

typescript
@useAuth(ApiKeyAuth<ApiKeyLocation.header, "api-key">)

Above decorate will generate the following OpenAPI securitySchemes entry and global security requirement:

yaml
components:
securitySchemes:
api_key:
type: apiKey
in: header
name: api-key

security:
- api_key: []
  • type: apiKey specifies the scheme.
  • in: header tells clients to send the key in an HTTP header.
  • name: api-key is the header name Azure AI Search expects.

4. Automatically Generated Files

After compiling your TypeSpec project, the following files will be generated in the appPackage/ directory:

text
appPackage/
├── declarativeagent.json
├── aisearchapiactions-apiplugin.json
└── aisearchapiactions-openapi.yml
File Description
declarativeagent.json Defines the agent and its capabilities for Copilot.
aisearchapiactions-apiplugin.json Describes the API plugin for Copilot integration.
aisearchapiactions-openapi.yml The OpenAPI specification for your Azure AI Search API actions.

Perks Agent Screenshot

Perks Agent Screenshot

Important Note

These files are needed to register and deploy your API plugin to a Microsoft Copilot declarative agent.

References

Author: Ejaz Hussain
Link: https://office365clinic.com/2025/05/25/build-copilot-declarative-agent-using-typespec/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.