Back to Archive

Using Microsoft Foundry to Draft Azure Service Enablement Documentation

16 min read
Using Microsoft Foundry to Draft Azure Service Enablement Documentation

In the first part of this series, I described the work that should happen before an Azure service becomes available to workload teams: assess the service, connect its capabilities to security controls, and document the guardrails and implementation guidance.

That process starts with documentation. Someone has to find the relevant service pages, work out which details matter, and connect the evidence to the questions in the service assessment. I wanted to see whether Microsoft Foundry could help with that first pass.

The experiment is deliberately small: a Foundry prompt agent that prepares a service profile for human review. The agent does not choose the organization's security controls, create Azure Policy assignments, or approve a service. Those decisions stay with the platform and security teams.

What this prototype produces

  • A draft product description in Markdown and a structured JSON document for one Azure service.
  • Source references beside the facts they support, with unknowns and open questions called out.
  • A document for a human reviewer to correct and complete, not an approved service baseline.

Why start with a prompt agent?

For this task, I did not need a custom agent runtime. Microsoft's documentation recommends a prompt agent when a model, instructions and tools are enough; a hosted agent is the option when you need your own code or orchestration logic. I wanted to test the research and drafting step before adding either.

Microsoft's current product documentation calls the platform Microsoft Foundry. Older material and some familiar references call it Azure AI Foundry. (What is Microsoft Foundry?, Foundry Agent Service overview)

The New agent menu in the Foundry portal makes that choice explicit. Build an agent creates a prompt agent in the portal. Code an agent is the route to your own code, and there are options to start from a template or link an external agent. I picked Build an agent.

The New agent menu in Microsoft Foundry, with Build an agent, Code an agent, With agent template and Link external agent.

File Search, or live documentation?

My original plan was to upload a curated set of private documents and use the Foundry File Search tool. That was not feasible in the time I had. Documents give you a fixed source of truth, but you have to download, upload and refresh every document yourself.

For the first run I went the other way and gave the agent two tools:

  • the Microsoft Learn MCP server, so it can search and read current Microsoft Learn documentation;
  • Web search, which uses Grounding with Bing, for material that is not on Learn.

Azure service documentation changes often, and the Learn MCP server keeps the agent on the current version.

Keep the first run narrow

I started with Azure Storage and Blob Storage because the previous post already used it to illustrate the service enablement process.

I did not upload internal standards, customer data, production configuration, or tenant exports. Instead, I gave the agent a small set of onboarding inputs in the chat:

InputValue
ServiceAzure Storage account with Blob Storage
Service ownerPlatform team
ScopeOrganizational
RegionWest Europe
RedundancyZRS
Network exposurePrivate only
Data classificationInternal (CIA 222)

The classification label is deliberately opaque. I wanted to see whether the agent would make up what "CIA 222" means. (Spoiler: it did not, more on that below.)

The agent has no Azure Policy write tool, no subscription access, no deployment credentials and no permission to make a service available. If it cannot find support for a statement, it should say so instead of filling in the blank.

The flow

Flow: onboarding inputs → prompt agent → Microsoft Learn MCP server + web search → Markdown and JSON draft → platform and security review.

The drafting flow: onboarding inputs, prompt agent, evidence retrieval through the Microsoft Learn MCP server and web search, a Markdown and JSON draft, and platform and security review.

Write the plan before the prompt

Before I touched the portal, I wrote a development plan for the agent. It describes what the agent is for, what it must never do, and what the output has to look like. The agent instructions are derived from that plan.

These decisions in the plan apply to all other parts:

  • Draft only. Each output has the review status pending. A human must approve the output. The agent must never mark a control as verified.
  • The same intake for all resource types. Storage is the first test, not the only scenario. A common intake applies to all resource types. The agent asks resource-specific questions only when they are important. A workload description is optional context. It is not a requirement.
  • A known origin for each answer. The agent marks each input as user_provided, source_derived or unknown.
  • Unknown is a correct answer. A missing value is null or needs_review. The agent must not guess a value. This rule helps to prevent hallucinations.
  • Benchmarks need a verified version. The target is MCSB v2 and CIS Azure Foundations Benchmark v5. The agent must not assume a version string. The agent does not use CIS content until the license is confirmed.
  • Guardrails stay proposals. The agent can propose guardrails. A guardrail becomes an organizational guardrail only after a designated human approves it. The approved guardrail has an owner, a version, a scope and an effective date. Later onboardings are assessed against the approved set.

The plan also defines the output contract. The Markdown product description has nine sections: intro, pricing, networking, security, identity, data actions, guardrails, control mapping, and assumptions with a reviewer checklist. The JSON has the same content in a structure that a pipeline can validate later. These JSON rules are important for governance:

  • assessmentStatus can be not_assessed, recommended, evidence_provided or verified_by_reviewer. The agent must not set verified_by_reviewer.
  • confidence gives the strength of the mapping evidence. It does not give the compliance status.
  • Guardrail status can be proposed, approved, superseded or rejected. The agent can only create proposed items.
  • Each sourceIds entry must point to an entry in sources.
  • The agent must not copy proprietary CIS control text into title.

That is a lot of rules for a chat agent. I don't expect the model to follow all of them perfectly. What matters is that a reviewer, and later a validator, can check each one.

Build the agent in Foundry

1. Project and model

I used an existing Foundry project in Sweden Central. The model is gpt-6-luna with a Data Zone Standard deployment. The Microsoft Foundry setup guide gives the steps to set up the project and the model, and the necessary permissions.

This model is a candidate, not a final decision. Before production, the plan says: compare it with one or more other models on the same test set.

2. Instructions and tools

The instructions are a short version of the development plan. The model must obey them in each turn. The plan contains the rules and the reasons. The instructions contain only the rules.

I made two changes to the plan:

  1. The plan assumes a curated knowledge source with versions. This agent has only Microsoft Learn and web search. Thus the retrieval rules tell the agent to prefer Learn and to name the facts that it cannot confirm.
  2. The plan keeps the approved guardrail set outside the prompt. This agent has no approved set. Thus the agent must say this. It must not suggest that an approved set exists.

These are the instructions, with the section titles in capital letters as in the portal:

You are the Azure Resource Service Enablement Assistant. Help teams onboard
Azure resources using the Cloud Adoption Framework (CAF) Service Enablement
approach.

PURPOSE AND LIMITS
- Produce an evidence-backed product description (Markdown) and a structured
  JSON control mapping for one Azure resource type, for expert review.
- You draft documentation only. You do not deploy resources, assign policies,
  attest compliance, approve controls or approve guardrails.
- You do not technically enforce anything. Enforcement needs a separate
  mechanism such as Azure Policy, IaC validation or a governed review.
  Never claim a guardrail is enforced unless evidence of that mechanism is
  supplied.

INTAKE
- Work for any Azure resource type. Storage is only one example. A workload
  description is optional context, not a prerequisite.
- Start from the common intake: resource type, service owner, intended
  capability and consumers, region, environment, management scope, SKU or
  tier, redundancy, data classification, network exposure.
- Ask resource-specific questions only when they change pricing, architecture,
  security or data handling. Ask a focused question instead of blocking when
  something is missing.
- Track every answer as user_provided, source_derived or unknown.
- Treat a label such as a data classification as opaque. Do not interpret
  what you were not told.

EVIDENCE AND SOURCES
- Prefer official Microsoft Learn documentation, official pricing pages and
  calculators, CAF guidance and the Microsoft cloud security benchmark (MCSB).
  Use the Microsoft Learn MCP server first. Use web search only for what Learn
  does not cover.
- Every material factual claim and every control mapping needs one or more
  source IDs that resolve to the sources list.
- Record the URL, publisher and, when available, the publication or update
  date of each source. Do not invent dates.
- If sources conflict, show both claims. Do not silently choose one.
- If you cannot find support, write "Not found in the provided sources" and
  add it to the open questions.
- Separate sourced product facts, your recommendations, and what the
  organization must decide.

OUTPUT: MARKDOWN
Include these sections, in this order:
1. Intro
2. Pricing: cost drivers, region, SKU or tier, usage assumptions, source date,
   exclusions. Never present an estimate as a quote.
3. Networking
4. Security: built-in capabilities and recommended configuration, separate
   from what the organization owns.
5. Identity: options, recommended patterns, role scoping, key and SAS caveats.
6. Data actions: operations, actors, authorization, retention, logging. If
   not applicable, say why.
7. Guardrails: proposed requirements, rationale, scope, evidence, exception
   process, approval state.
8. Control mapping summary
9. Assumptions, open questions and reviewer checklist
Start with a status line: draft, human review required.

OUTPUT: JSON
Follow schemaVersion 1.0.0 with these top-level keys: document, resource,
sections (intro, pricing, networking, security, identity, dataActions),
controls, guardrails, guardrailAssessment, assumptions, openQuestions, sources.
- Unknown values are null, an empty list or needs_review. Never infer them.
- applicability: applicable, not_applicable or needs_review.
- assessmentStatus: not_assessed, recommended or evidence_provided. Never set
  verified_by_reviewer.
- controlLayer: service, platform or organizational.
- confidence describes the strength of the mapping evidence, not compliance.
- Guardrail status is always proposed. Leave guardrailId, owner, approval
  details, effectiveAt and reviewAt as null.
- Guardrail assessment outcomes are meets, gap, not_applicable,
  needs_evidence or needs_review. Never say meets without supplied evidence.
- Keep guardrailAssessment as not_assessed unless an approved guardrail set
  with version, scope, effective date and source is supplied. Otherwise ask
  for it. Do not imply one exists.
- benchmarkVersion stays null until the organization confirms the exact MCSB
  release or profile. Do not assume a version.
- CIS: use only identifiers and your own summaries, and only if licensed and
  approved CIS material was supplied. Otherwise return one record that says
  CIS was not assessed. Do not copy CIS control text.
- Run a self-check before answering: valid JSON, every sourceId resolves, and
  no field breaks the rules above. State that you did not run an automated
  schema validator.

REVIEW AND SAFETY
- Keep the review status "pending." Do not mark a control verified or a
  document approved.
- If a requested field is not applicable to the resource, state why instead
  of omitting it.
- A gap against an approved guardrail blocks a positive onboarding
  recommendation until it is remediated or a human approves a documented,
  time-bound exception. You cannot waive or reinterpret a guardrail.
- Do not ask for or repeat secrets or customer data.
- Finish with a short list of decisions or evidence a service owner and
  security reviewer must confirm before the draft is adopted.

This text is a clean version of the instructions. It is not an exact copy from the portal. Some words in the agent are different, but the rules are the same.

Under Tools, I added Web search and the Microsoft Learn MCP server. I added no other tools and no knowledge source.

The agent playground in Foundry, with the gpt-6-luna model, the end of the instructions, and Web search and Microsoft Learn MCP server as tools.

Warning: read the web search notice. When you add Web search, the portal shows a notice. Grounding with Bing has additional costs and separate terms. Customer data goes outside the Azure compliance boundary. This risk is acceptable for a prototype that sends only public service names and an invented classification label. It is not acceptable if your onboarding inputs contain data that you do not put into a public search engine. Make this decision before you add the tool. (Grounding with Bing Search)

The first run: Azure Storage with Blob Storage

My first message was one sentence:

I want to onboard Azure Storage Blob Container.

That is all the agent got to start with. The values from the input table above came in during the conversation, and the Markdown product description and JSON draft were built from them. I only had to approve the tool calls for Web search and the MCP server. That is a setting you can change, so the tools run without approval.

The response took 36 seconds and used about 97,700 tokens. The agent called the Learn MCP server and web search, and the portal listed 77 citations under the answer. The whole conversation was about 157,600 tokens by then. That is not cheap for one service profile, and it is worth tracking before you run this for every resource type.

The agent response in the Foundry playground, showing the end of the JSON sources list, a validation note, and the citations bar.

The Markdown part opens with a status line I did not have to argue for:

Status: Draft; human review required. This is a service-enablement draft, not an assessment of a deployed account. No resource configuration or evidence of implementation was supplied.

The networking section is a good example of the tone throughout:

User requirement: private-only access. A Blob private endpoint can provide a private IP in a virtual network, and Blob private endpoint DNS uses privatelink.blob.core.windows.net. A private endpoint alone does not disable the Storage public endpoint; the owner should confirm public network access is disabled and DNS resolves correctly for intended clients. VNet/subnet, DNS ownership, client networks, and connectivity paths are unknown. S4

The JSON follows the contract. This is the NS-2 control record:

{
  "benchmark": "MCSB",
  "benchmarkVersion": null,
  "controlId": "NS-2",
  "title": "Secure cloud services with network controls",
  "applicability": "applicable",
  "assessmentStatus": "not_assessed",
  "controlLayer": "platform",
  "recommendation": "For this private-only requirement, use a private endpoint, disable public network access, and provide evidence of DNS/client resolution and public endpoint restrictions.",
  "rationale": "The user specified private-only networking; the Azure Policy mapping associates NS-2 with Storage private link and network restriction controls.",
  "serviceCapability": "Storage supports private endpoints and network access restrictions.",
  "evidenceRequired": [
    "Approved network design",
    "Private endpoint configuration evidence",
    "Private DNS and client resolution evidence",
    "Public network access setting evidence"
  ],
  "sourceIds": ["S4", "S9"],
  "confidence": "medium",
  "reviewNotes": "Exact organization-approved MCSB release/profile not supplied. No resource configuration evidence supplied."
}

In total, the draft mapped four MCSB controls (NS-2, IM-1, DP-3 and DP-5), added one CIS record that explicitly says nothing was assessed, and proposed three guardrails: private-only access, identity-based Blob authorization, and secure transfer.

The outcome

It is a rough version, but a lot worked out of the box. Some of it would still need tighter guardrails in the prompt to prevent hallucinations. So, what did the agent do well on the first try?

  1. It did not invent the classification. "CIA 222" is preserved as an opaque label, and the DP-5 record says not to infer a customer-managed key requirement from it.
  2. It kept the review status pending. Every control is not_assessed, every guardrail is proposed, and guardrailId, owner and approval fields are null.
  3. It refused to make up CIS mappings. No approved CIS v5 material was supplied, so it returned no CIS control IDs and asked for the approved release and licensing approval.
  4. It left benchmark versions empty. benchmarkVersion is null on every MCSB record, with a review note, instead of guessing "v2" from the plan.
  5. It caught the private endpoint trap. The networking section, the NS-2 record and the guardrail all say that a private endpoint does not disable the public endpoint. That is exactly the kind of detail that goes missing in hand-written onboarding notes.
  6. It treated pricing as a dependency. No estimate, just a list of cost drivers and a note that the account SKU, tier and usage are unknown.
  7. It was honest about validation. It ended with a note saying the JSON was not run against a schema or validator.

The flipside

There were also mistakes that are unacceptable in a production environment:

  1. The dates are wrong. generatedAt, every retrievedAt, and the pricing note all say 2026-04-02. That is not when I ran the agent. A provenance field that the model fills in itself is not provenance. The run date has to come from the system, not the model.
  2. Ten sources are really about six pages. S7, S9 and S10 point to the same Azure Policy regulatory compliance page. S2 and S6 are the same page with and without an anchor, and S3 is an anchor on S1. The citations look thorough, but a reviewer has fewer independent sources than the list suggests.
  3. The portal citations and the document sources don't match. The portal showed 77 citations, including the Azure Policy GitHub repository and the Australian Government ISM PROTECTED mapping. The document lists 10 sources. I cannot tell from the output which retrieved pages influenced which claim, and the ISM result is irrelevant to this scenario.
  4. Citations point to pages, not passages. [S9] tells me which page to open, not which sentence supports the claim. For control mappings, the reviewer still has to find the mapping on the page and check it.
  5. No publication dates. publishedOrUpdatedAt is null for every source. The plan's source freshness rule depends on that field.
  6. Minor contract drift. The Markdown puts the control mapping before the guardrails, the reverse of the order in the contract. Not a big deal for a human, but a renderer that expects a fixed order would notice.

None of these are reasons to drop the idea. They are reasons to keep the reviewer in the loop and to move provenance and validation out of the model.

Is the draft grounded enough?

Before I add more resource types, I want to do a short set of tests. The Storage run did some of these tests. The other tests need a separate run.

TestExpected resultResult
Where does Azure Storage document the minimum TLS version?Find the applicable source and cite it.Partially. It names minimum TLS as a setting that you can configure, and it cites S5 and S6. It does not give a value. It says that the organizational baseline must give the value.
Does a private endpoint alone disable the public endpoint?Give the documented limitation with a citation.Yes. The draft gives this fact in three locations, with S4 as the source.
Ask for information that the sources do not contain.Say that the information is not found and keep it for review.Yes. SKU, retention, key model, DNS owner and other values are null. The draft shows them as open questions.
Supply a requirement (private only).Keep the supplied requirement separate from the service facts.Yes. The draft shows it as "User requirement" and marks it as user_provided.
Sources with conflicting statements or dates.Show the conflict. Do not select one statement without a note.Not done yet.

One run is not an evaluation, but it does tell me the instructions are roughly right. It doesn't mean the agent is reliable.

What the human reviewer still decides

The draft is useful only if a reviewer can check the evidence and make the decisions. A platform engineer and the security or compliance owner must decide these items:

  • Is the documented capability in scope for the service baseline of the organization?
  • Which control objective applies? Is the source sufficient evidence?
  • Can Azure Policy enforce the requirement? Which definition and alias apply to the resource property?
  • What must workload teams configure? This includes dependencies such as private endpoint DNS.
  • Do gaps need more research, a compensating control or an explicit exception?

The agent's own output ends with a similar list: open questions for the service owner, the security reviewer and the guardrail approvers. That is the most useful part of the draft. It turns "go read the Storage docs" into a short list of decisions.

What's next

The obvious next step is in the portal itself. Foundry has an Evaluation tab and an Optimize tab. Optimize uses a dataset and evaluators to generate and compare variations of the instructions, tool descriptions and model choice, and you decide whether to promote one. The 75 → 92.5 numbers on the screen are Microsoft's own example benchmark for a tax agent, not a result for this agent.

The Optimize tab for the Azure-Service-Enablement-Assistant, with Microsoft's example benchmark and an Optimize my agent button.

Before Optimize is useful, I need a test set. That means more than Storage: compute, networking, databases and a platform service, plus cases for conflicting sources, credential exceptions and a missing guardrail set. Without that, Optimize would tune the agent towards one resource type.

Next to that, I want to change a few things:

  • Validate the JSON against a published JSON Schema, and check that every sourceIds entry resolves. The agent already admits it did not do this.
  • Stamp dates outside the model. generatedAt and retrievedAt should come from the pipeline.
  • Keep live documentation and add grounded company knowledge next to it. For the service itself, I want the most current information, so the Learn MCP server stays. Azure changes too often for a copy I have to refresh by hand. But live documentation cannot tell the agent which risks my organization cares about or which security control framework applies. That is where a curated knowledge source helps: the approved control framework, the company risk data and, later, the approved guardrail set. File Search or an Azure AI Search index can hold those. The agent then takes service facts from live Learn and organizational requirements from a versioned source, and the draft shows which is which.

This post is a showcase of how quickly Foundry gets you from an idea to a working draft, so I stayed in the portal. For anything you plan to keep, my advice is to run it in code where possible. Code gives you the flexibility to validate output, stamp dates, control retrieval and version the instructions. The Continue in code button is right there for that. It is out of scope for this post.

The question from the first post was whether Foundry could turn service documentation into a useful onboarding draft without guessing. For one service, mostly yes: it guessed less than I expected, and it was honest about what it did not know. The places where it did go wrong, dates and source bookkeeping, are exactly the things I should not have asked a model to do in the first place.

Sources

Related Posts