Blog Post

Microsoft Foundry Blog
7 MIN READ

Build a Grounded Package Upgrade Advisor with Microsoft-Decision-1

SonakshiA's avatar
SonakshiA
Icon for Microsoft rankMicrosoft
Nov 03, 2026

About the Microsoft Decision Model

In October 2026, Microsoft announced Microsoft-Decision-1, the latest model for fast decision-scoring available on Microsoft Foundry. Unlike LLMs that generate textual outputs, decision models return structured outputs that allow software to immediately act on, without having to first interpret the response.

The model accepts a state value which can be text or JSON. There are three question types based on the decision we need:

Question

Type

Result

Yes/No, true/false questions

noul

A probability from 0 through 1

Multiple Choice Questions

choice

One selection option and the probability for each option

Questions related to ranking or grading

score

A value on an ordered scale and the probability for each level. Starts from 0

Use Case

We will be building a simple application that decides whether a software package needs upgrading.

An agent searches trusted sources (via Grounding with Bing Custom Search resource) for release notes and security advisories. A decision model then reads that evidence and says whether to upgrade, why, and how urgently.

Pre-Requisites

  1. Azure Subscription
  2. Microsoft Foundry resource deployed in a resource group. Deploy the Microsoft-Decision-1 model, and gpt-4.1 model to power the agent
  3. A Grounding with Bing Custom Search resource

Adding Sources to Bing Custom Search

  1. Go to the Bing Custom Search resource
  2. Click on Configurations in the left pane under the Resource Management section
  3. Create a new configuration and name it ‘documentations’. This is the Domain Name
  4. Add the following web addresses:

          https://docs.djangoproject.com/en/stable/releases

          https://www.djangoproject.com/weblog

          https://www.djangoproject.com/download

          https://pypi.org/project/django

  1. Save the configuration

Add Bing Custom Search as a Tool to Foundry

In the previous section, we made the tool. Now, we will add it to Foundry

Steps:

  1. Click on Management Centre
  2. Click on Connected resources
  3. Click on + New Connection
  4. Choose Grounding with Bing Custom Search

     

  5. It will automatically show all the Bing Custom Search resources. Connect the one you created for this tutorial by choosing ‘Add Connection’
  6. Click on the connection, and save the Id

Creating the Foundry Agent

Set up a .env file and populate the following information:

ENDPOINT=<https://<your-foundry-resource-name>.services.ai.azure.com/providers/microsoft> (This is the decision model’s endpoint)
PROJECT_ENDPOINT=https://<your-foundry-resource-name>.services.ai.azure.com/api/projects/proj-default
DEPLOYMENT_NAME=<decision-model’s deployment name>
CONN_ID=<Bing Custom Search Id we saved in the previous step>
DOMAIN_NAME=documentations

We create a foundry agent using the following code snippet and deploy it to Foundry. The file is called create_agent.py. Run this file to deploy the agent to foundry.

import os
from azure.identity import DefaultAzureCredential, InteractiveBrowserCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import (
    PromptAgentDefinition,
    BingCustomSearchPreviewTool,
    BingCustomSearchToolParameters,
    BingCustomSearchConfiguration,
)
from dotenv import load_dotenv
load_dotenv()

PROMPT = """
You are a software upgrade research agent.

Given a package name and installed version, use Bing Custom Search to find
official release notes, security advisories, and support information.

Summarize:
- Security issues affecting the installed version and available fixes.
- Whether the version is still supported.
- Relevant breaking changes and upgrade requirements.

Use only retrieved evidence and include source URLs. If applicability is
unclear, say so. Do not treat missing evidence as proof that a version is safe.

Return a JSON object with:
- package
- installed_version
- summary
- source_urls
"""
conn_id = os.getenv("CONN_ID")
project_client = AIProjectClient(
    endpoint=os.getenv("PROJECT_ENDPOINT"),
    credential=DefaultAzureCredential()
)

tool = BingCustomSearchPreviewTool(
    bing_custom_search_preview=BingCustomSearchToolParameters(
        search_configurations=[
            BingCustomSearchConfiguration(
                project_connection_id=conn_id,
                instance_name=os.getenv("DOMAIN_NAME"),
            )
        ]
    )
)

with project_client:
    agent = project_client.agents.create_version(
        agent_name="extract-news-agent",
        definition=PromptAgentDefinition(
            model="gpt-4.1",
            instructions=PROMPT,
            tools=[tool],
        ),
    )
    print(f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})")

Setting up the Decision Model

The following code sets up the decision model. The file is called model.py

import os
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
from dotenv import load_dotenv
from typesafe_sdk import TypeSafeClient

load_dotenv()

ENDPOINT = os.getenv("ENDPOINT")
DEPLOYMENT_NAME = os.getenv("DEPLOYMENT_NAME")
def assess_upgrade(state: str):
    with DefaultAzureCredential() as credential:
        token_provider = get_bearer_token_provider(
            credential, "https://ai.azure.com/.default"
        )

        with TypeSafeClient(
            api_key=token_provider(),
            base_url=ENDPOINT,
            model=DEPLOYMENT_NAME,
            timeout=60,
        ) as client:
            return client.system_one(
                state=state,
                questions={
                    "upgrade_needed": {
                        "type": "noul",
                        "instructions": (
                            "Does the supplied evidence indicate that the installed "
                            "version needs an upgrade? Use only the supplied evidence. "
                            "Missing evidence is not proof that no upgrade is needed."
                        ),
                        "criteria": {
                            "true": (
                                "Evidence identifies an applicable security fix, "
                                "end-of-support, or required compatibility upgrade."
                            ),
                            "false": (
                                "Evidence establishes that the installed version is "
                                "supported and no applicable upgrade requirement exists."
                            ),
                        },
                    },
                    "reason": {
                        "type": "choice",
                        "instructions": (
                            "Choose the primary upgrade reason. If multiple apply, "
                            "prioritize security-fix, then end-of-support, then "
                            "compatibility. Choose insufficient-evidence if the "
                            "installed version cannot be assessed reliably."
                        ),
                        "criteria": {
                            "security-fix": (
                                "An official advisory explicitly affects the installed "
                                "version and identifies a fix."
                            ),
                            "end-of-support": (
                                "The installed version no longer receives support."
                            ),
                            "compatibility": (
                                "An upgrade is required for the stated environment "
                                "or application requirements."
                            ),
                            "routine-update": (
                                "Only optional improvements or routine fixes apply."
                            ),
                            "no-upgrade-needed": (
                                "Evidence supports retaining the installed version."
                            ),
                            "insufficient-evidence": (
                                "Evidence is missing, conflicting, or does not "
                                "establish applicability to the installed version."
                            ),
                        },
                    },
                    "urgency": {
                        "type": "score",
                        "instructions": (
                            "Rate upgrade urgency using only verified applicability "
                            "and impact in the supplied evidence. Do not assume an "
                            "older version is vulnerable."
                        ),
                        "criteria": [
                            "Routine: no established urgent upgrade requirement.",
                            "Planned: upgrade in a normal maintenance cycle.",
                            "Urgent: applicable material security risk, unsupported "
                            "version, or significant compatibility impact.",
                            "Immediate: confirmed exposure to a critical issue or "
                            "active exploitation relevant to the stated deployment.",
                        ],
                    },
                },
            )


def print_upgrade_decision(response):
    needed = response.nouls["upgrade_needed"]
    reason = response.choices["reason"]
    urgency = response.scores["urgency"]

    print(f"Upgrade-needed signal: {needed.noul:.1%}")
    print(f"Reason: {reason.choice} (confidence: {reason.confidence:.1%})")

    if reason.choice == "insufficient-evidence":
        print("Urgency: not actionable without more evidence")
        action = "gather more evidence"
    else:
        print(f"Urgency: {urgency.score:.2f} of 3")
        if needed.noul >= 0.5 and urgency.score >= 2:
            action = "prioritize upgrade review"
        elif needed.noul >= 0.5 or reason.choice != "no-upgrade-needed":
            action = "schedule upgrade review"
        else:
            action = "monitor"

    print(f"Action: {action}")

We leverage all three types of questions in this code.

  1. “upgrade-needed” has a noul type associated to it, we return either true or false based on the agent’s output.
  2. “reason” has a choice type associated to it. We choose a reason for the upgrade.
  3. “urgency” has a score type associated to it. We define a criterion to decide the urgency. The score starts from 0 and can be a decimal.

The instructions field tells the decision model how to judge the question, while criteria field defines the best possible answers.

The print_upgrade_decision() function handles the output formatting:

  1. We print if the upgrade is needed (noul type)
  2. We print the reason (choice type)
  3. We print the action needed based on the urgency score (score type)

Calling the Agent

In this segment, we will watch the workflow in action!

The following code snippet sends a query to the agent and returns a response. The file is called fetch_news.py

from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from model import assess_upgrade, print_upgrade_decision
import json
import os

from dotenv import load_dotenv
load_dotenv()

endpoint = os.environ["PROJECT_ENDPOINT"]
agent_name = "extract-news-agent"
user_message = "We use Django 4.2.0. Find official security advisories affecting this version and identify the fixed versions." # change this as per your needs

with (
    DefaultAzureCredential() as credential,
    AIProjectClient(
        endpoint=endpoint,
        credential=credential,
        allow_preview=True,
    ) as project_client,
):
    # Bind the OpenAI client to the existing agent endpoint.
    openai_client = project_client.get_openai_client(agent_name=agent_name)

    # GitHub Copilot preview agents require a conversation for every Responses turn.
    conversation = openai_client.conversations.create()
    response = openai_client.responses.create(
        conversation=conversation.id,
        input=[{"role": "user", "content": user_message}],
    )

    raw_output = response.output[-1].content[0].text
    print(raw_output)
    news_item = json.loads(raw_output)
    summary = news_item["summary"]

    # Classify each news summary with the decision model
    decision = assess_upgrade(summary)
    print_upgrade_decision(decision) # print the decision

The response contains a JSON object with these fields (we had defined this in our prompt while creating the agent):

- package

- installed_version

- summary

- source_urls

In the snippet, we send the summary to the decision model and print the final decision.

Sample output:

Run the fetch_news.py file to get the output!

Next Steps:

  1. Try it yourself! Clone the repository
  2. Extend the use case by:
    • Scanning a real dependency file (requirements.txt, pyproject.toml, package.json) and ranking all packages by urgency.
    • Outputting a report (Markdown or JSON) with the decision, reason, confidence and source URLs.
    • Running it as a scheduled job or CI check that opens an issue or PR comment when an upgrade is urgent.

References:

  1. Deploy and use Microsoft-Decision-1 in Microsoft Foundry - Microsoft Foundry | Microsoft Learn
  2. Microsoft-Decision-1: Our model for fast decision-making
Updated Oct 28, 2026
Version 1.0