#SharePointProblems | Koskila.net

Solutions are worthless unless shared! Antti K. Koskela's Personal Professional Blog

Declarative Copilot agents without custom agent code

Reading Time 10 min
Word Count 1720 words
Comments 0 comments
View

Coming down from the highs of this year's awesome HELish summit, I figured I'd visit the topic of my talk one more time!

We've now presented multiple sessions on the topic with my friend and former colleague Gautam Sheth, and figured I'd address some of the questions and feedback we've gotten in a couple of blog posts.

In this first post, I'll explain why declarative Microsoft 365 Copilot agents can take you surprisingly far without you having to write custom agent code or maintaining an agent backend. You still have configuration to write, and sometimes an integration to build, but you don't have to rebuild Copilot before doing anything useful with it.

Interested? Let's get to it!

About this series

In the session, we introduced a support-ticket scenario: First setting up an agent to pull data from issues reported on GitHub, then giving it access to more knowledge and actions, and finally getting it out into other people's hands and figuring out why it misbehaves - along the way, I'll address some of the feedback and questions we've gotten so far!

You can find the published installments under Baby Steps to Copilot Mastery. Each post tackles a different question, so you can jump to the one you need without treating the whole series as homework.

Background

The fastest way to make a useful Microsoft 365 Copilot agent is often to resist the urge to build too big. Start by declaring what your agent is for, how it should behave, and what it is allowed to know. Add actions only when the use case actually needs them.

That was the central idea in our HELish Summit 2026 session, Baby Steps to Copilot Mastery: Easy Wins with M365 Agents Toolkit & Copilot Connectors. The product names will of course move around (so don't get too attached), but the basic idea should survive a few more rounds of rebranding.

What "declarative" means here

A declarative agent is configuration layered on top of Microsoft 365 Copilot.

Like I alluded to before, think of it this way: You describe the specialist; Microsoft hosts the orchestration, models, user experience, and runtime.

You still need to make four decisions clearly:

  1. Identity: What is the agent called, what is its purpose, and which conversation starters help users get going?
  2. Behavior: What instructions, boundaries, tone, and output format should it follow?
  3. Knowledge: Which SharePoint sites, files, web sources, or external systems should ground its answers?
  4. Actions: Which tools may it use, and which of those tools can change something?

The important bit is the order: define the specialist first, ground it second, and add actions last. The API or tool calls should only follow when the job description is clear!

Microsoft runs the platform, you define the specialist

The appeal is not that declarative agents magically remove all engineering. It's that you don't have to build and operate a chat application, connect it to a model, implement the orchestration, set up and maintain the infrastructure, and finally explain to users where to find the thing. They already have Copilot, after all!

You get to spend the effort on instructions, useful knowledge, and the actual task instead. And you'll have plenty of time left over!

And because your instructions and manifests are files, you can review and version them like the rest of your work. "No custom agent code" doesn't mean "no code" - and instead of whatever half-baked versioning you would get from the ClickOps tools, you can get proper version control with Git.

Microsoft also provides the platform's security controls. But this is not permission to stop thinking about security! You still own the source permissions, connector access rules, and the operations you expose. An instruction saying "don't show confidential tickets" is not an access-control list.

Use the Microsoft-hosted runtime until a real requirement proves that it is not enough. A custom engine agent should be an answer to a constraint, not the starting point for every experiment.

How much "no code" are we talking about?

Our session sample repository follows one support-ticket scenario through three stages:

  1. Internal Support: build a custom (Copilot) connector for Microsoft Search to ingest support tickets, then declare an agent that finds and summarizes them through the InternalSupportTickets connection.
  2. Internal Support Escalation uses that knowledge and Work IQ tools to prepare escalations through Microsoft 365.
  3. Internal Support Closure uses a small GitHub REST API plugin to read issues, record resolution notes, and close or reopen them.

Note, that in real life, you would have only used one agent for the entire support-ticket workflow, rather than splitting it into separate stages for internal support, escalation, and closure. The staged approach is for demo purpose only.

Oh, and we could have used a gallery (built-in) connector for the first demo too. We deliberately built a custom one to make things a bit spicier and show how the content gets into the index. A session about not writing custom agent code naturally needed us to write code for something else! 😅

Not because we like coding - nobody does THAT anymore! It's for educational purposes only, obviously.

The connector is written in TypeScript, but the agents themselves are still 100% declarative.

The distinction is custom integration code versus a custom agent runtime. You might need a crawler or API adapter because your source system is unusual. That does not automatically mean you also need to implement the agent's orchestration and host it yourself.

If your knowledge is already in SharePoint or files, or a gallery connector does the job, even that integration may be configuration only. The closure agent goes directly to GitHub's existing API, so it does not need a custom proxy backend either.

A practical decision tree

The following decision tree should help you make decisions about when to use custom agent code:

  1. Need behavior only? Start with instructions and conversation starters.
  2. Need internal documents? Add the relevant SharePoint content or files. Don't overcomplicate it!
  3. Need external knowledge? Look for a gallery connector first.
  4. Need ingestion the gallery doesn't support? Consider a custom synced connector, including its permission model.
  5. Need Microsoft 365 context or actions - or other MCP servers? Check the Work IQ or MCP tools available in your tenant or elsewhere!
  6. Need an existing business API? Describe the operations you need in an API plugin.
  7. Need your own model or orchestration, proactive messaging, or Teams behavior the hosted agent doesn't support? NOW we're getting into interesting territory! A custom engine agent may actually be justified. 😁

This is not a ranking of technologies or approaches! I'd never be opinionated about the "right" way to do things 😉 It's more about a way to avoid paying the operational cost of a complicated option before you know that you need it.

A requirement to look up one ticket should not accidentally turn into a platform engineering career change.

Where does Agents Toolkit fit?

The Microsoft 365 Agents Toolkit gives the configuration a repeatable lifecycle: Scaffold the project, configure the manifests and environments, validate, provision the required registrations, and publish the package.

For a declarative agent, this is not the same thing as deploying a custom agent server. Our GitHub sample, for example, provisions its app and OAuth configuration without deploying an Azure Function (or any other backend) for the agent.

As a side note - always keep the configuration in version control! "What exactly changed?" is a much easier question to answer with a diff than with a memory of whichever admin portal you were in last Thursday.

What's the catch?

This will not solve your every agent problem.

You're playing in Microsoft's sandbox. You give up control over parts of the runtime and the user experience. When a requirement needs something outside that sandbox, more instructions won't necessarily get you there.

Debugging can be painful. Was the answer wrong because of the instructions, retrieval, permissions, or a tool call? Not owning the runtime is lovely right up until you'd really like to put a breakpoint in it.

Licensing and availability still matter. Check what your users can actually access, how their usage is billed, and which capabilities your tenant permits. "It worked in the demo tenant" is unfortunately not a licensing plan.

Not every API fits neatly. Authentication, request shapes, and the available confirmation experience all matter. Sometimes a small adapter is enough; sometimes the requirement really does call for a different architecture.

But when the requirements fit, declarative agents let you focus on useful behavior instead of rebuilding orchestration, hosting, and a chat UI from scratch. That's a fairly good trade in my book.

Where would I start?

Pick one real workflow. Before opening VS Code, ask:

  • What would make this workflow meaningfully easier?
  • What information would the agent need?
  • Does it need to change anything, or would finding and explaining the right information be enough?
  • Where should it stop and ask for confirmation?

The answers to these questions will usually make the next steps quite obvious! Maybe you only need better instructions and a few files. Maybe you need a connector. Or maybe the whole thing would be better as a search page and a small piece of automation - not everything needs to be an agent!

For the first attempt, I'd leave write actions out. Give the agent a narrow purpose and a source you know well. Ask a few questions you can check yourself, including one the source cannot answer. Does it cite useful evidence, and does it admit when it doesn't know? That tells you more than a very convincing paragraph about nothing in particular.

The rule of thumb from the session still applies:

Configure first. Connect second. Code only at the edge.

Keep reading

Next in this series: choosing knowledge sources for a declarative agent, tentatively planned for October 6. After that, we'll look at Work IQ and API actions on October 13(-ish). The examples will follow the support-ticket agents from our session.

I might mess up the schedule - I'm changing jobs after all, so bear with me if the dates shift a bit.

For something to work through now, my introduction to Copilot Connectors in Microsoft Search covers how to inspect a connection and query its content. The HELish Summit announcement has the original session context.

References

Comments

Interactive comments not implemented yet. Showing legacy comments migrated from WordPress.

No comments yet.

Whitewater Magpie Ltd.
•
© 2026
Static Site Generation timestamp: 2026-09-28T18:01:26Z