Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
148897 stories
·
33 followers

Armchair Architects: Designing Effective AI Agents

1 Share
From: Microsoft Developer
Duration: 20:15
Views: 188

In this second episode of season six of the Armchair Architects series on the Azure Essentials Show, Uli, Eric, and David dive deep into the anatomy of AI agents, breaking down their essential components and exploring the practical challenges of building and operating them.

The discussion covers foundational elements like language models, knowledge bases, orchestration frameworks, and the critical role of memory, while also addressing governance, environmental awareness, and best practices for keeping agents up-to-date and secure.

Together, the three architects offer a comprehensive look at what it takes to design robust, responsive, and well-governed AI agents for enterprise environments.

Key Takeaways
- Understand the core components of an AI agent: language model, knowledge, orchestration, and tools.
- Learn about different types of memory (short-term, medium-term, long-term) and their impact on agent behavior.
- Discover best practices for refreshing agent knowledge and managing environmental awareness.
- Explore governance strategies and the importance of separating agent autonomy from oversight.
- Gain insights into practical frameworks and protocols like RAG, MCP, and orchestration tools (LangChain, Semantic Kernel, Autogen).

Recommended Resources & Next Steps
- Read Microsoft’s documentation on AI agent architectures and governance.
https://learn.microsoft.com/search/?terms=AI%20Agent%20architecture
- Explore articles on Retrieval Augmented Generation (RAG) and vector databases for knowledge management.
https://learn.microsoft.com/search/?terms=Retrieval%20Augmented%20Generation
- Review best practices for data privacy and memory management in AI systems.
https://learn.microsoft.com/purview/dspm-for-ai?tabs=m365

Related Episodes
- Watch more episodes of Armchair Architects https://aka.ms/ArmchairArchitects
- Watch more episodes of the Azure Essentials Show https://aka.ms/AzureEssentialsShow

Connect
- David Blank-Edelman https://www.linkedin.com/in/dnblankedelman/
- Uli Homann https://www.linkedin.com/in/ulrichhomann/
- Eric Charran https://www.linkedin.com/in/ericcharran/

Chapters
0:00 Introduction
1:08 Agent anatomy
8:22 Deeper dive on Memory
10:15 Handling sensitive data
13:52 Staying up-to-date
19:45 Queuing up the next episode

Read the whole story
alvinashcraft
just a second ago
reply
Pennsylvania, USA
Share this story
Delete

Old Developers using New Tools with Brady Gaster

1 Share
How are folks adapting to the new tools available for development today? Carl and Richard talk to Brady Gaster about his work on improving the tooling for software development at Microsoft - and the transformation that is currently underway! Brady talks about developers doing app modernization, dealing with the challenges of the cloud, and the many fun things you get to do as software developers over the years - and how there's only more coming!



Download audio: https://dts.podtrac.com/redirect.mp3/api.spreaker.com/download/episode/68548644/dotnetrocks_1976_old_developers_using_new_tools.mp3
Read the whole story
alvinashcraft
just a second ago
reply
Pennsylvania, USA
Share this story
Delete

Vibe Coding with GitHub Spark: From idea to app in minutes (continued)

1 Share

Yesterday we started exploring GitHub Spark. We looked at the basic prompting experience, the live preview but also explored the visual editing features and the specification generation (through a PRD.md file). But we didn't have the time to check out all the features. 

Let's dive in...

Seamless GitHub Integration

This is where Spark really shines. Unlike standalone vibe coding tools, Spark can create a GitHub repository from your project. Once created you get a repository with GitHub Actions, Dependabot, and all the standard tooling. The code is synchronized so you don’t need to leave the vibe coding experience.


Remark: This is also a great way to better understand what is going on behind the scenes. It allowed me to fix some issues where I wasn’t able to solve it inside GitHub Spark.

Need more power? Open a Codespace directly from Spark and continue development with the full GitHub ecosystem at your fingertips.

Upload a sketch or an image

You don’t have to start with only a prompt but you can also start from an existing design or sketch you draw on a napkin. Take a picture and attach it to the Spark's input field, together with the following example prompt.

Authentication

Spark has built-in authentication, since users need to sign in with their GitHub account to access your app. You control who has access to your app by setting visibility and data access options.

 

One-Click Deployment

When you're ready, click "Publish" and your app goes live on Microsoft Azure with built-in authentication and a secure URL. No DevOps knowledge required.

 

Billing

GitHub Spark uses your existing GitHub Copilot plan. Each prompt consumes 4 premium requests, which draw from your plan's premium request allowance. (More info here: GitHub Spark billing - GitHub Docs)

 


Conclusion

I think that GitHub Spark certainly has its place among the other vibe coding tools. In addition, it offers some unique features like the visual editor and of course the great GitHub integration that makes it a compelling candidate.

My main wish is that the used model will still improve as it got stuck a few times. The good news was that I was always able to fix it by switching to the repository and do some changes there (using GitHub Copilot).

Addendum

I used Github Spark to create a 7 minutes workout application. The 7-minute workout is a high-intensity circuit training routine designed to deliver maximum fitness benefits in minimal time using just body weight, a chair, and a wall.

I started doing this workout every day with my oldest son and we noticed that we had 2 problems;

  1. We always forgot the exact order of the routines
  2. Tracking the time manually was cumbersome

So we decided to build an app that walks you through the routine and keeps track of the time. Timing and the exact exercise are shared through audio cues so you don’t have to look at your cellphone during the routine.

The app is available here (you only need a GitHub account to be able to access it):

https://7-minute-workout-com--wullemsb.github.app

Read the whole story
alvinashcraft
32 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Why Real-Time RAG Matters — and Why Modern GenAI Systems Must Be Architected This Way

1 Share

Why Real-Time RAG Matters — and Why Modern GenAI Systems Must Be Architected This Way

As organizations accelerate their adoption of Generative AI, one reality is becoming increasingly clear: modern GenAI systems cannot rely on static knowledge. The world they operate in changes too quickly — customer expectations shift in minutes, social sentiment evolves in real time, and internal policies or operational data update continuously.

In this environment, the traditional approach of embedding documents once, storing them in a vector database, and occasionally refreshing the index is no longer enough. It creates a fundamental disconnect between what the system knows and what is actually happening.

This is why real-time Retrieval-Augmented Generation (RAG) must be treated as an integral architectural consideration, not an optional enhancement. It determines whether a GenAI system remains accurate, trustworthy, and aligned with current data.

If your system relies on stale knowledge:

  • its answers become outdated the moment something changes,
  • hallucinations increase as the model tries to fill in missing context,
  • customer interactions lose relevance, and
  • the credibility and value of the entire AI initiative erode quietly but quickly.

Real-time RAG changes that. It ensures modern GenAI systems:

  • continuously ingest new information,
  • embed and index updates as they occur,
  • retrieve context reflecting the present moment, and
  • generate responses grounded in up-to-date truth rather than historical snapshots.
This shift isn’t cosmetic — it’s architectural.
It’s the difference between deploying AI that remembers the past versus AI that understands the present.

As GenAI becomes foundational across industries — powering customer service, decision support, automation, and insights — engineering for real-time context is no longer optional. It’s the new baseline.

How Real-Time RAG Works

At its core, real-time Retrieval-Augmented Generation follows a continuous cycle:

Stream → Embed → Store → Retrieve → Generate → Attribute.

High-Level View of Real-Time RAG System Design

This cycle keeps GenAI systems aligned with live information rather than stagnant data.

  • Stream new information as it arrives — social media posts, customer events, CRM changes, policy updates.
  • Embed new text, snippets, or updates into vector representations immediately.
  • Store those vectors with metadata: timestamps, source, content type.
  • Retrieve the most relevant and most recent pieces during inference.
  • Generate responses using an LLM that leverages this fresh context.
  • Attribute citations and timestamps so responses are auditable and trustworthy.

The architecture ensures that intelligence remains synchronized with the environment it operates in.

Pattern 1: Social Media Monitoring in Real Time

Take the example of brand sentiment tracking. You don’t need yesterday’s conversation — you need right now.

A real-time RAG pipeline can:

  • Stream posts continuously from X, LinkedIn, Reddit, or industry communities.
  • Enrich those posts with metadata like authorship, hashtags, or language.
  • Embed each new post on arrival.
  • Store those embeddings in a vector database built for high-volume ingestion.
  • Retrieve the latest, most relevant sentiment when queried.

Instead of delayed dashboards, you get a real-time view of what’s happening.

This is the same paradigm used by real-time streaming systems described by AWS and Google Cloud for near-instantaneous insight pipelines.

Pattern 2: Conversational AI with Live Knowledge

Now imagine a customer asking:

“Is the premium plan still available?”

If your AI relies on stale or nightly-refreshed data, it won’t reflect what changed two minutes ago.

Real-time RAG solves this by:

  • Continuously capturing updates from CRMs, policy systems, internal wikis, inventory feeds.
  • Embedding only changed or newly added content (“incremental indexing”).
  • Using recency-aware retrieval to ensure the system pulls the freshest information.
  • Generating responses that accurately reflect current availability, pricing, or policy.

This transforms a chatbot or voice agent from a static FAQ engine into a dynamic, context-aware intelligence layer.

Frameworks like LangChain and LlamaIndex now provide built-in primitives for streaming retrieval and context refresh, enabling these capabilities at scale.

Building a Real-Time RAG Pipeline

A robust real-time RAG architecture typically includes:

1. Streaming Ingestion

Use Kafka, Amazon Kinesis, or Google Pub/Sub to capture new events instantly.
This prevents reliance on slow batch processes.

2. Incremental Embedding

Only newly changed content should be re-embedded.
This keeps latency low and cost manageable.

3. Vector Database Optimized for Recency

Choose a vector store capable of:

  • high-throughput ingestion,
  • fast filtering by timestamp, and
  • metadata-aware semantic retrieval.

Pinecone, Milvus, Weaviate, and pgvector are common options.

4. Real-Time Retrieval and Generation

LLMs retrieve both relevant and recent chunks before generating outputs.
Streaming responses improve the user experience and reduce perceived latency.

5. Attribution and Explainability

Every answer must show where the information came from and when it was last updated.
This is critical for trust and alignment with governance standards.

Practical Insights

  • Freshness beats volume: A smaller, up-to-date index is more valuable than a massive but stale one.
  • Latency matters: Slow pipelines negate the value of “real-time.”
  • Chunk strategically: Smaller, meaningful chunks improve retrieval quality.
  • Observe and measure: Track ingestion lag, embedding speed, retrieval latency, and model response time.
  • Prioritize what truly needs to be real-time: Not every dataset requires immediate re-embedding.
  • Metadata is the backbone: Without timestamps and sources, recency-aware retrieval is impossible.

The Bigger Picture

We’re entering an era where AI must operate with situational awareness, not just static knowledge.
Systems that cannot adapt in real time will feel outdated — because they are.

Real-time RAG represents the architectural shift that enables AI to:

  • stay aligned with live information,
  • respond accurately to dynamic situations, and
  • support decisions based on what is true now.

The organizations that embrace this architecture will build AI systems that are not only intelligent, but aware. And awareness — especially in a fast-moving world — is the real advantage.

References:

Read the whole story
alvinashcraft
40 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Building Uber's Dynamic Pricing Engine in .NET: Supply-Demand Algorithms, Geospatial Indexing, and Real-Time Market Simulation

1 Share

## 1 Building Uber’s Dynamic Pricing Engine in .NET: Supply-Demand Algorithms, Geospatial Indexing, and Real-Time Market Simulation

Uber’s pricing engine is one of the most fascinating real-time systems ever deployed at scale. It balances millions of drivers and riders across constantly changing geographies, optimizing prices every few seconds to match market conditions. In this article, we’ll reconstruct that core system — not the entire Uber stack, but the essential architectural, algorithmic, and engineering ideas that power dynamic pricing — using modern *.NET 8/9* technologies.

We’ll move from concept to implementation: building event-driven microservices, handling live geospatial data, calculating real-time supply-demand ratios, and integrating predictive models with *ML.NET*. The focus is on production-grade architecture — code that can run at scale, not just a toy simulation.

### 1.1 The Business Imperative: Beyond “Surge”

Most people think “surge pricing” is about profit. It’s not — it’s about market equilibrium. When too many riders request rides and too few drivers are available, prices must rise to restore balance. The system isn’t punishing demand; it’s broadcasting scarcity. The goal is threefold:

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

How to Parse XML in Python Without Using External Libraries

1 Share

In software development, you’ll run into XML (Extensible Markup Language) when working with configuration files, API responses, data exports, and more. While there are powerful third-party libraries for parsing XML, Python's standard library already includes everything you need.

In this tutorial, you'll learn how to parse XML using Python's built-in xml.etree.ElementTree module. No pip installs required.

🔗 You can find the code on GitHub.

Prerequisites

To follow along with this tutorial, you should have:

  • Python 3.7 or later installed on your system

  • Basic understanding of Python syntax and data structures

  • Familiarity with basic programming concepts like loops and conditionals

  • A text editor or IDE for writing Python code

No external libraries are required as we'll use Python's built-in xml.etree.ElementTree module.

Table of Contents

  1. How to Read an XML String

  2. How to Read an XML File

  3. How to Find Elements in an XML Tree

  4. How to Extract Text and Attributes from XML

  5. How to Build a Simple XML Parser

  6. How to Handle Missing Data

How to Read an XML String

Let's start simple. We'll parse XML directly from a string to understand the fundamental concepts.

import xml.etree.ElementTree as ET

xml_string = """
<catalog>
    <product id="101">
        <name>Wireless Keyboard</name>
        <price currency="USD">29.99</price>
    </product>
</catalog>
"""

root = ET.fromstring(xml_string)
print(f"Root tag: {root.tag}")
print(f"Root attributes: {root.attrib}")

How this works:

  • We import xml.etree.ElementTree and give it the alias ET (this is the convention)

  • ET.fromstring() parses the XML string and returns the root element

  • Every element has a .tag property (the element name) and .attrib dictionary (its attributes)

  • The root object represents the <catalog> element in our XML

For the above example, you’ll see the following output:

Root tag: catalog
Root attributes: {}

Here, the root.attrib is empty because the root element <catalog> in the provided xml_string does not have any attributes defined. Attributes are key-value pairs within the opening tag of an XML element, like id="101" or currency="USD" in the <product> and <price> elements. Since <catalog> only has a tag and no additional information within its opening tag, its attributes dictionary is empty.

How to Read an XML File

In real applications, you'll usually read XML from files. Say you have a products.xml file. Here's how you can read from the XML file:

# Parse an XML file
tree = ET.parse('products.xml')
root = tree.getroot()

print(f"Root element: {root.tag}")

Before we proceed to run and check the output, let’s note the differences between reading XML strings vs files:

  • ET.parse() reads from a file and returns an ElementTree object

  • We call .getroot() to get the root element

  • Use ET.parse() for files, ET.fromstring() for strings

Running the above code should give you:

Root element: catalog

How to Find Elements in an XML Tree

ElementTree gives you three main ways to search for elements. Understanding when to use each is important.

import xml.etree.ElementTree as ET

xml_data = """
<catalog>
    <product id="101">
        <name>Wireless Keyboard</name>
        <categories>
            <category>Electronics</category>
            <category>Accessories</category>
        </categories>
    </product>
    <product id="102">
        <name>USB Mouse</name>
        <categories>
            <category>Electronics</category>
        </categories>
    </product>
</catalog>
"""

root = ET.fromstring(xml_data)

# Method 1: find() - returns the FIRST matching element
first_product = root.find('product')
print(f"First product ID: {first_product.get('id')}")

# Method 2: findall() - returns ALL direct children that match
all_products = root.findall('product')
print(f"Total products: {len(all_products)}")

# Method 3: iter() - recursively finds ALL matching elements
all_categories = root.iter('category')
category_list = [cat.text for cat in all_categories]
print(f"All categories: {category_list}")

Now let’s understand how the three methods work:

  • find() stops at the first match. Use when you only need one element.

  • findall() only searches direct children (one level deep). Use for immediate child elements.

  • iter() searches recursively through the entire tree. Use when elements might be nested anywhere.

This is important: findall('category') on root won't find anything because <category> isn't a direct child of <catalog>. But iter('category') will find all categories no matter how deeply nested. So when you run the above code, you’ll get:

First product ID: 101
Total products: 2
All categories: ['Electronics', 'Accessories', 'Electronics']

How to Extract Text and Attributes from XML

Now let's extract actual data from our XML. This is where you turn structured XML into Python data you can work with.

xml_data = """
<catalog>
    <product id="101">
        <name>Wireless Keyboard</name>
        <price currency="USD">29.99</price>
        <stock>45</stock>
    </product>
</catalog>
"""

root = ET.fromstring(xml_data)
product = root.find('product')

# Get element text content
product_name = product.find('name').text
price_text = product.find('price').text
stock_text = product.find('stock').text

# Get attributes (two ways)
product_id = product.get('id')  # Method 1: .get()
product_id_alt = product.attrib['id']  # Method 2: .attrib dictionary

# Get nested attributes
price_element = product.find('price')
currency = price_element.get('currency')

print(f"Product: {product_name}")
print(f"ID: {product_id}")
print(f"Price: {currency} {price_text}")
print(f"Stock: {stock_text}")

This outputs:

Product: Wireless Keyboard
ID: 101
Price: USD 29.99
Stock: 45

What's happening here:

  • .text gets the text content between opening and closing tags

  • .get('attribute_name') safely retrieves an attribute (returns None if missing)

  • .attrib['attribute_name'] accesses the attribute dictionary directly (raises KeyError if missing)

  • Use .get() when an attribute might be optional, use .attrib[] when it's required

How to Build a Simple XML Parser

Let's put it all together with a practical example. We'll parse the full product catalog and convert it to a Python list of dictionaries.

def parse_product_catalog(xml_file):
    """Parse an XML product catalog and return a list of product dictionaries."""
    tree = ET.parse(xml_file)
    root = tree.getroot()

    products = []

    for product_element in root.findall('product'):
        # Extract product data
        product = {
            'id': product_element.get('id'),
            'name': product_element.find('name').text,
            'price': float(product_element.find('price').text),
            'currency': product_element.find('price').get('currency'),
            'stock': int(product_element.find('stock').text),
            'categories': []
        }

        # Extract categories (nested elements)
        categories_element = product_element.find('categories')
        if categories_element is not None:
            for category in categories_element.findall('category'):
                product['categories'].append(category.text)

        products.append(product)

    return products

Breaking down this parser:

  • We iterate through all <product> elements using findall()

  • For each product, we extract text and attributes into a dictionary. We convert numeric strings to proper types (float for price, int for stock)

  • For nested categories, we first check if the <categories> element exists. Then we iterate through child <category> elements and collect their text

The result is clean Python data structures you can easily work with. You can now use the parser like so:

products = parse_product_catalog('products.xml')

for product in products:
    print(f"\nProduct: {product['name']}")
    print(f"  ID: {product['id']}")
    print(f"  Price: {product['currency']} {product['price']}")
    print(f"  Stock: {product['stock']}")
    print(f"  Categories: {', '.join(product['categories'])}")

Output:

Product: Wireless Keyboard
  ID: 101
  Price: USD 29.99
  Stock: 45
  Categories: Electronics, Accessories

Product: USB Mouse
  ID: 102
  Price: USD 15.99
  Stock: 120
  Categories: Electronics

How to Handle Missing Data

Real-world XML is messy (no surprises there!). Elements might be missing, text might be empty, or attributes might not exist. Here's how to handle that gracefully.

xml_data = """
<catalog>
    <product id="101">
        <name>Wireless Keyboard</name>
        <price currency="USD">29.99</price>
    </product>
    <product id="102">
        <name>USB Mouse</name>
        <!-- Missing price element -->
    </product>
</catalog>
"""

root = ET.fromstring(xml_data)

for product in root.findall('product'):
    name = product.find('name').text

    # Safe way to handle potentially missing elements
    price_element = product.find('price')
    if price_element is not None:
        price = float(price_element.text)
        currency = price_element.get('currency', 'USD')  # Default value
        print(f"{name}: {currency} {price}")
    else:
        print(f"{name}: Price not available")

Here, we handle potential missing data by:

  1. Using product.find('price') to search for the <price> element within the current <product> element.

  2. Checking if the result of find() is None. If an element is not found, find() returns None.

  3. Using an if price_element is not None: condition to only attempt to access the text (price_element.text) and attributes (price_element.get('currency', 'USD')) of the <price> element if it was actually found.

  4. Adding an else block to handle the case where the <price> element is missing, printing "Price not available".

This approach prevents errors that would occur if you tried to access .text or .get() on a None object. For the above code snippet, you’ll get:

Wireless Keyboard: USD 29.99
USB Mouse: Price not available

Here are a few more error-handling strategies:

  • Always check if find() returns None before accessing .text or .get()

  • Use .get('attr', 'default') to provide default values for missing attributes

  • Consider wrapping parsing in try-except blocks for production code

  • Validate your data after parsing rather than assuming XML structure is correct

Conclusion

You now know how to parse XML in Python without installing any external libraries. You learned:

  • How to read XML from strings and files

  • The difference between find(), findall(), and iter()

  • How to extract text content and attributes safely

  • How to handle nested elements and missing data

The xml.etree.ElementTree module works well enough for most XML parsing needs, and it's always available in Python's standard library.

For more advanced XML navigation and selection, you can explore XPath expressions. XPath works well for selecting nodes in an XML document and can be very useful for complex structures. We’ll cover this in another tutorial.

Until then, happy parsing!



Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories