Creating APIs and declarative agents for Microsoft 365 Copilot today involves writing multiple JSON and YAML files that are tedious to create and prone to errors. Microsoft has introduced TypeSpec, a domain-specific language (DSL) that streamlines this process by replacing hand-written configuration files with a strongly-typed, developer-friendly syntax.
In this article, you’ll learn:
- What TypeSpec is
- Why Microsoft created it as a way to create APIs
- How Microsoft 365 is leveraging it to create declarative agents
- How can it make your development workflow more productive and reliable
Challenge with creating APIs today
When you’re working on creating a new API, one of the common things you’re going to end up doing is not only writing all the code for your API, but also writing the descriptions for those APIs. These descriptions are more important these days with many different tools requiring detailed API documentation.
For example, when you’re creating a declarative agent (DA) and defining the actions available to your agent, you have to write the documentation for your API using a standard format that Large Language Models (LLMs) will understand. This format is an OpenAPI Description (OAD) format.
In addition, when you create a DA for Microsoft 365 Copilot, there are other files you’re going to need as well:
- Declarative agent manifest file: This defines the agent itself.
- Plugin manifest file: This defines the type of data that’s available to the Microsoft 365 Copilot orchestrator and the different capabilities of what it can do. We’re using the actions file to teach the orchestrator what tools (aka: skills) it has access to.
- OpenAPI Description (OAD) file: The actions file is paired with an OAD file, which we refer to as a runtime. This has a one-to-one map with the function defined in the action manifest for the declarative agent, mapping to a specific endpoint defined in the OAD file.
The challenge with this approach is that writing all of these JSON files and YAML files can be problematic. It’s easy to make mistakes and you don’t have any kind of error checking during development to ensure everything you’ve done is valid.
What is TypeSpec?
To address this challenge, Microsoft created a new language called TypeSpec to better assist developers in creating APIs. You can think of TypeSpec as the tooling to support an API-first approach for developers.
TypeSpec removes all of those hand-written JSON and YAML files that slow you down and are more prone to typos and errors. Instead, you’ll work with a strongly typed language. When you compile a TypeSpec project, it will generate standards-compliant API schemas in just a matter of seconds, including all those files I just referred to - the OAD document and JSON manifests.
Because TypeSpec is inspired by TypeScript, the syntax is going to be fairly familiar, although there are some differences. It’s a minimal language that helps developers describe API shapes in a very familiar way.
When you write TypeSpec and compile it using the TypeSpec compiler, you’ll define an emitter that can generate various formats of files for you, depending on the libraries you’re using, so you can leverage it within your different projects.
Out of the box, the TypeSpec standard library supports a couple of different protocols, including:
- OpenAPI 3.0 specification (OAD files, also known as Swagger definitions)
- JSON Schema
- Protobuf (a REST alternative format from Google)
Benefits of using TypeSpec
You can think of TypeSpec as a domain specific language (DSL). Just like when creating resources for Microsoft Azure, you would create ARM templates, which are verbose JSON files that can be very tedious to write and troubleshoot. Microsoft created a language called Bicep, which is a DSL for creating ARM templates in a much more productive and efficient way.
You can think of TypeSpec as the DSL for creating all of the files needed when you generate an API, both the description files (the OAD file) and the files needed for creating declarative agents.
TypeSpec provides several productivity benefits:
- Type checking: We can make sure that the objects we’re creating are used in the right scenarios and supported scenarios with the tool at development time.
- IntelliSense: Because it’s a strongly typed language, you’re going to get IntelliSense, so you get native coding tips as you’re typing along. You get this a little bit when you’re creating the different manifest files for API plugins or for declarative actions when it comes to Microsoft 365 Copilot, but nowhere near the same level of support that you get from TypeSpec.
- Development-time validation: If you type something that you can’t do, it’ll let you know right away with red squiggles that something is not permitted in the current context.
- Object references: Create endpoints, operations, and actions as objects and then reference their properties in the same way we can with Bicep or any other standard programming language.
TypeSpec language elements
Let’s take a look at some of the different language elements inside TypeSpec:
Import statements: You can use
import
statements to pull packages in, using the exact same kind of packaging structure that we have with the npm global registry.import "@typespec/http"; import "@typespec/openapi3"; import "@microsoft/typespec-m365-copilot"; import "./env.tsp"; import "./actions.tsp";
Namespaces: Like many other programming languages, namespaces allow you to group related objects and types. This organization makes it easier to locate things and helps avoid name conflicts. Namespaces can be nested within each other, and they’re automatically available across your entire project.
Decorators: A decorator can be referenced using the
@
symbol prefix, and it must be placed before any of the entities that they are decorating. A common one is the@doc
decorator to define documentation for the very next object.model OrderLineItem { @doc("The name of the dish to order") name: string; @doc("The quantity of the dish to order.") quantity: integer; }
Operations: These are service endpoints when it comes to an API. They’re characterized by an operation’s name, some parameters, and a return type. You’re almost writing it just like a function in many of the other languages you’re familiar with. The following code defines an HTTP GET operation named
listRepairs
that represents the/repairs
endpoint for a service:@route("/repairs") @doc("Returns a list of repairs with their details and images") @returnsDoc("A list of repairs") @get op listRepairs( @doc("Filter repairs by who they're assigned to") @query assignedTo?: string ): { @statusCode statusCode: 200; @body results: { .. }[] };
That’s not all… There are many other elements available in TypeSpec, like interfaces, enums, unions, aliases, values, and arrays - similar things that you have in many other languages.
TypeSpec compiler and emitters
The way TypeSpec works is through a compiler and emitter. You can think of the compiler very much the same way as we do with TypeScript. When you compile your TypeSpec (.tsp
files), they’re run through the compiler, which will ultimately generate the resulting files we need for the different API specifications.
In the case of Microsoft 365 Copilot declarative agents, that would be the JSON file manifest for the declarative agent and the OAD document in JSON or YAML
When those files are generated with an emitter. An emitter defines how the compiled TypeSpec is going to get exported. If you give it a TypeSpec object, the emitter knows how to write the proper specification file that corresponds to and is valid with the schema you’re working with.
For example, the operation defined in the previous sample will create the following operation in an OAD file:
# ..
paths:
/repairs:
get:
summary: List all repairs
description: Returns a list of repairs with their details and images
operationId: listRepairs
parameters:
- name: assignedTo
in: query
description: Filter repairs by who they're assigned to
schema:
type: string
responses:
'200':
description: A list of repairs
content:
application/json:
schema:
type: array
items:
type: object
# ..
Why Microsoft is using TypeSpec for declarative agents
Now that you understand what TypeSpec is and some of its benefits, let’s look at it in the context of M365 Copilot DA’s. Why is Microsoft using this to create declarative agents?
Microsoft has historically built its reputation on platform stability and avoiding breaking changes. That’s a commitment that the community has actively supported and enforced. While there have been some exceptions, Microsoft has generally maintained industry-leading stability standards that developers can rely on.
But we now face very different changes and challenges today to the stability model:
- Non-deterministic AI models: In the AI world, models are inherently non-deterministic, and applications built on them can no longer guarantee consistent behavior. This is compounded by the rapid pace of model evolution and customer demands for model flexibility. Many want the ability to swap out models or bring their own models into applications.
- Extraordinary pace of change: The AI space is evolving at an unprecedented rate. Microsoft’s platform and M365 Copilot teams are moving so fast, with schemas and decisions (and product names for that matter) frequently becoming obsolete almost as quickly as they’re understood.
These forces are straining the traditional agreement between Microsoft and the developer community. Complex enterprise systems, especially when you add AI, go far beyond simple demo applications and now require constant revisiting and updating to keep pace with platform changes. Developers can’t ignore and opt out of these changes - they’re forced to adapt as the platform evolves beneath them.
Microsoft’s solution is to take advantage of TypeSpec to provide some distance and an abstraction from the rapidly changing platform. The strategy is to create tools that can adapt to platform shifts through code generation, potentially targeting multiple versions simultaneously. This approach restores some of the stability and predictability for developers.
Microsoft sees this as a necessity for maintaining developer productivity in an environment where the traditional development loop is being disrupted by the complexity and deployment requirements of AI-enhanced applications. By providing this abstraction layer, Microsoft hopes to give developers back some of the certainty that we’ve lost in this rapidly evolving landscape.
Microsoft’s TypeSpec library for declarative agents
What Microsoft has done with respect to TypeSpec is they’ve created a TypeSpec library. A TypeSpec library is how we can package reusable objects as well as new rules, decorators, and emitters for new file types that need to be generated.
Microsoft has created its own TypeSpec library, @microsoft/typespec-m365-copilot, that adds decorators, rules, and an emitter.
They’ve also created an action for the Microsoft 365 Agents Toolkit (ATK):
provision:
- uses: typeSpec/compile
with:
path: ./src/agent/main.tsp
manifestPath: ./appPackage/manifest.json
outputDir: ./appPackage/.generated
typeSpecConfigPath: ./tspconfig.yaml
When the action runs as part of the compilation process, it’s going to:
- Compile the TypeSpec project
- Generate the declarative agent manifest
- Generate the OAD document for our API (if defined in the TypeSpec files)
The action also leverages Kiota, a project from Microsoft, to generate the API manifest that’s referenced by the declarative agent’s manifest and maps to operations defined in the OAD file that was generated.
Current state of the TypeSpec library
The @microsoft/typespec-m365-copilot library is currently v1.0.0-rc.3 with a very tight dependency on TypeSpec v1.0.0-rc.1. This is a little bit behind today because TypeSpec has now reached general availability and even had a minor release since reaching that milestone.
In my opinion, even though the TypeSpec library for M365 Copilot DAs is in preview, it’s okay to use it for creating DAs today because none of the TypeSpec code is what’s being deployed - it’s only used to generate the deployed files. Provided the files it’s generating are good, then we’re good. It’s not dangerous to use or going to break on you. Issues would only affect your development experience.
I have found a few bugs and identified a few things that need to change (Microsoft has already made some changes), but nothing I would consider a showstopper.
One annoying aspect is that we’re lacking a good blank starter project for a declarative agent built using TypeSpec. There is one available today in the Microsoft 365 Agents Toolkit, but it’s using an existing API (GitHub API). That’s fine for many scenarios, but if you need to create your API or start a project that’s going to have its custom API, it’s not a great starter.
Create Your Own M365 Copilot DA Project With Azure Functions & TypeSpec
Check out my article on creating a reliable M365 Declarative Agent starter project that includes TypeSpec and an Azure Function for a new custom API. Even if Microsoft adds a similar starter project, this article will help you better understand how TypeSpec works and how you can customize the M365 Agents Toolkit (ATK) build configuration: How to add TypeSpec to M365 Copilot Declarative Agent Projects
Conclusion
Now that you understand what TypeSpec is and why Microsoft is using it to help with developer productivity for declarative agents, you can see how it addresses the challenges of creating APIs and declarative agents through hand-written JSON and YAML files. TypeSpec provides a strongly-typed, developer-friendly approach that includes IntelliSense, type checking, and validation while generating all the necessary files for your declarative agents.
While the current state of Microsoft’s TypeSpec library is still in release candidate status, its a solid foundation for creating declarative agents today. The abstraction layer it provides helps insulate developers from the rapidly changing AI landscape while maintaining the productivity and reliability we expect from Microsoft development tools.
What questions do you have about TypeSpec or creating declarative agents?
Drop a comment below and let me know what you’d like to learn more about!

Microsoft MVP, Full-Stack Developer & Chief Course Artisan - Voitanos LLC.
Andrew Connell is a full stack developer who focuses on Microsoft Azure & Microsoft 365. He’s a 20+ year recipient of Microsoft’s MVP award and has helped thousands of developers through the various courses he’s authored & taught. Whether it’s an introduction to the entire ecosystem, or a deep dive into a specific software, his resources, tools, and support help web developers become experts in the Microsoft 365 ecosystem, so they can become irreplaceable in their organization.