• Microsoft Agent Framework 1.0: three runnable Python examples

    Microsoft Agent Framework reached 1.0 GA on May 21, 2026 for both .NET and Python. It consolidates the previous Semantic Kernel and AutoGen SDKs into one supported codebase with a stable API surface and a long-term support commitment.

    To see what zero-to-agent actually looks like against my own Azure OpenAI deployment, I wrote three small Python examples that progressively add capability: a hello-world agent, an agent with local Python tools, and an agent that connects to a remote MCP server. All three are real files I ran.

    You need Python 3.10 or newer, an Azure OpenAI deployment (I used gpt-4o-mini, which is gpt-4.1-mini behind the alias), the endpoint URL and an API key, and pip install agent-framework==1.0 python-dotenv. Drop the credentials in a .env:

    AOAI_ENDPOINT=https://...
    AOAI_DEPLOYMENT=gpt-4o-mini
    AOAI_API_KEY=...
    AOAI_API_VERSION=2024-10-21
    

    The first example is a single agent that takes one prompt and returns one response. No tools, no state, no MCP. If it returns a sentence, the SDK and the deployment are both working:

    import os
    from dotenv import load_dotenv
    from agent_framework import (
        ChatClientAgent,
    )
    from agent_framework.azure import (
        AzureOpenAIChatClient,
    )
    
    load_dotenv()
    E = os.environ
    
    client = AzureOpenAIChatClient(
        endpoint=E["AOAI_ENDPOINT"],
        api_key=E["AOAI_API_KEY"],
        deployment_name=E["AOAI_DEPLOYMENT"],
        api_version=E["AOAI_API_VERSION"],
    )
    
    agent = ChatClientAgent(
        chat_client=client,
        instructions=(
            "Terse release-notes "
            "summarizer. One sentence."
        ),
    )
    
    prompt = (
        "Summarize: Azure VPN P2S "
        "now supports user-group "
        "IP pools, GA 2026-05-21."
    )
    print(agent.run(prompt).content)
    

    Adding a tool is one more parameter. The Annotated[..., "description"] pattern feeds each parameter description into the tool schema the model sees; the function docstring becomes the tool description:

    from typing import Annotated
    
    PRICES = {
        "MSFT": 412.10,
        "TSLA": 178.42,
        "PGEN": 1.23,
    }
    
    def get_price(
        sym: Annotated[
            str, "Ticker, uppercase"
        ],
    ) -> str:
        "Mock price for a ticker."
        p = PRICES.get(sym.upper())
        if p is None:
            return f"unknown {sym}"
        return f"{sym}: ${p:.2f}"
    
    agent = ChatClientAgent(
        chat_client=client,
        instructions=(
            "Portfolio assistant. "
            "Use the tool for prices."
        ),
        tools=[get_price],
    )
    
    q = "MSFT price? PGEN above $1?"
    print(agent.run(q).content)
    

    With two questions in one prompt the agent calls the tool twice and summarizes both results.

    The third example skips local tools entirely and pulls them from a remote MCP server. Agent Framework ships an MCP client, so any compliant server is a tool source with no glue code. The Microsoft Learn MCP server at learn.microsoft.com/api/mcp is public and Streamable-HTTP:

    import asyncio
    from agent_framework.mcp import (
        MCPStreamableHTTPClient,
    )
    
    URL = (
        "https://learn.microsoft.com"
        "/api/mcp"
    )
    
    async def main():
        mcp = MCPStreamableHTTPClient(
            url=URL,
        )
        async with mcp:
            tools = await mcp.list_tools()
            agent = ChatClientAgent(
                chat_client=client,
                instructions=(
                    "MS Learn assistant. "
                    "Use the MCP tools."
                ),
                tools=tools,
            )
            q = (
                "Front Door Standard "
                "vs Premium tiers?"
            )
            r = await agent.run_async(q)
            print(r.content)
    
    asyncio.run(main())
    

    Swap the URL for GitHub’s, Atlassian’s, or your own private one – the rest of the code is unchanged.

    Two gotchas worth knowing: agent-framework==1.0 moved instructions to the ChatClientAgent constructor, so preview code that set it on ChatClientAgentOptions will break. And if a model deployment rejects parallel tool calls, pass parallel_tool_calls=False on the agent constructor.


  • Azure updates: weeks 21-22, 2026

    Azure shipped a batch of updates over the last two weeks. Here are the five worth more than a line.

    Microsoft Agent Framework 1.0 GA

    Microsoft Agent Framework reached 1.0 GA on May 21 for both .NET and Python. The 1.0 release commits Microsoft to a stable API surface with long-term support. Agent Framework consolidates work that was previously split across Semantic Kernel and AutoGen.

    One breaking change from preview to GA: the Instructions setting moved off ChatClientAgentOptions and onto the ChatClientAgent constructor directly.

    Source: Azure update #560982.

    Azure Front Door WebSocket support (public preview)

    Azure Front Door Standard and Premium now support WebSocket connections with no additional configuration. The HTTP handshake is inspected, then the upgraded connection passes through.

    The practical use case is putting Web PubSub, SignalR, or a custom WebSocket workload behind Front Door for global edge presence and WAF inspection at the handshake. Two things to know: WAF rules apply only to the handshake, not to the open connection; and Web PubSub is not on Front Door Premium’s supported Private Link origin list, so a Standard Internal Load Balancer or Application Gateway is needed between Front Door and a private Web PubSub endpoint.

    Source: Azure Front Door WebSocket (Microsoft Learn).

    P2S User Groups and IP address pools (GA)

    Azure VPN Gateway Point-to-Site connections can now assign IP addresses from different pools based on the user’s Entra ID group membership. Prior to this GA, segmenting VPN users by role required parallel gateways or NSG rules keyed off unpredictable IP ranges.

    The mechanism: define User Groups on the gateway, map each group to an address pool, and set a priority for users that match multiple groups. Downstream NSGs can then key off per-group subnets.

    Source: Azure update #564460.

    Entra-only identities with Azure Files (GA)

    Azure Files SMB shares can now authenticate against Microsoft Entra ID alone, without AD DS, Entra Domain Services, or hybrid identity sync.

    For organizations running cloud-only identity, this removes one of the remaining reasons to keep a domain controller running just for file-share access. Hybrid environments still have their own configuration paths.

    Source: Azure update #562359.

    Virtual network flow logs connector with Microsoft Sentinel (GA)

    Azure now offers a native data connector that sends Virtual Network flow logs directly into Microsoft Sentinel. Before this, getting VNet or NSG flow logs into Sentinel for SecOps correlation required a custom ingestion pipeline, typically built on Storage, Event Hub, and a Function App or Logic App.

    For Sentinel deployments that already ingest the other Azure first-party signal sources (Activity Log, Entra ID sign-ins, Defender for Cloud), this adds network-layer telemetry without parallel ingestion infrastructure. Typical detection use cases include lateral movement, anomalous east-west flows, and exfiltration over uncommon ports.

    The connector is GA, not preview.

    Source: Azure update #564689.


  • Running eclipse-mosquitto in an Azure IoT Edge Module

    I was looking to run a MQTT broker on an IoT edge device, allowing devices to communicate locally with each other. The most important thing is to modify the “Container Create Options” so that the container’s port can be seen on the local network. Also I want to use the no auth mosquitto config (it is in development), so I overrode the cmd section.

    With those changes, the device was able to pull the standard docker image “eclipse-mosquitto:latest” and it started running on the local device and the exposed 1883 port was available for local devices

    {
      "NetworkingConfig": {
        "EndpointsConfig": {
          "host": {}
        }
      },
      "ExposedPorts": {
        "1883/tcp": {}
      },
      "HostConfig": {
        "PortBindings": {
          "1883/tcp": [
            {
              "HostPort": "1883"
            }
          ]
        },
        "NetworkMode": "host"
      },
      "Cmd": [
        "/usr/sbin/mosquitto",
        "-c",
        "/mosquitto-no-auth.conf"
      ]
    }
    

  • How to find the Raspberry Pi model

    Note to self:

    How to find the Raspberry Pi Model :

    cat /proc/device-tree/model
    

  • Azure Functions (PowerShell) : Find the current FunctionApp and Function names

    I was writing an Azure Function in PowerShell. I wanted to know the name of the current FunctionApp and the current Function. Since it was a timer triggered function, I couldn’t pass the names. It took me a while to to figure this out. There may be other ways, but this only way I could find it. Again, this is in PowerShell

    if ($ENV:AZURE_FUNCTIONS_ENVIRONMENT  -eq "Development"){
      $CurrentFunctionAppName=$($PSScriptRoot.split("/")[-2])
      $CurrentFunctionName= $($PSScriptRoot.split("/")[-1])
    }
    else {
      $CurrentFunctionAppName=$($ENV:WEBSITE_SITE_NAME)
      $CurrentFunctionName= $($PSScriptRoot.split("/")[-1])
    }
    

    We need a conditional is as the method is different if you are running local vs in azure.


  • Quickly find that new Raspberry Pi’s address

    Saw this the other day, and I wanted to post it, so that I can remember it.

    How to find a Raspberry Pi’s DHCP address:

    arp -na | grep -i "b8:27:eb"
    


  • Quick 1 liner to download your Azure Billing Statements

    Simple and quick – I had never done it before. I was working on a different script, but I realized that I have never downloaded my billing statements from azure. Simple 1 liner to download them:

    foreach ($invoice in $(Get-AzBillingInvoice -GenerateDownloadUrl)){irm $invoice.Downloadurl -OutFile "$($invoice.Name).pdf"}
    

    Hope that helps someone!


  • PowerShell to get the cost of a VM per day

    PowerShell to get the cost of a VM per day

    I wanted to get the cost of a VM each day. I came up with the following code. Just the VM cost, not the ingress (DataTrIn) or egress (DataTrOut). I hope it helps someone!

    $results=Get-AzConsumptionUsageDetail -StartDate 2019-12-01 -EndDate 2019-12-10 -IncludeAdditionalProperties
    $subscriptions="YourSubName"
    foreach ($sub in $subscriptions){
    $results | `
    where {$_.ConsumedService -eq 'Microsoft.Compute'} | `
    where {$_.SubscriptionName -eq $sub}| `
    Select UsageStart, InstanceName, UsageQuantity,PreTaxCost,@{N="UsageType";E={(ConvertFrom-Json $($_.AdditionalInfo)).UsageType}} | `
    where {$_.UsageType -eq 'ComputeHR'} | `
    Sort-Object InstanceName,UsageStart | ft 
    }