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

Prompts are dead; long live loops!

1 Share

As you may have heard, loops are the hottest thing in AI. The buzz is that rather than you writing prompts, you let your agent do so. The problem is that while all the videos I’ve seen are great at touting the advantages and even explaining the moving parts (though each one has slightly different architecture), I’ve yet to see one that gives concrete C# examples—let alone using the Microsoft Agent Framework.

Soooo, this is the very first in a series. I’m finding my way, stumbling in the dark, so some of this may be a bit simplistic—but I believe it is correct as far as it goes. Remember, however, that the first draft of this post was written by AI. I’ve edited it, but your mileage may vary.

Here’s a thought experiment. Imagine having an agent that keeps trying fixes until a web service stays healthy—retrying configuration changes, re-checking status, and stopping only when a health check returns OK or a safety limit is reached. That behavior—automatic, bounded repetition with an evaluation step between attempts—is exactly what loop programming enables in modern agentic AI. This post explains the pattern, why it matters, and how to implement it in C# using the Microsoft Agent Framework (MAF) concepts.

One-sentence takeaway
Loop programming = agent acts → observes → evaluates → repeats (until accepted or bound). Use MAF’s loop primitives (loop wrapper or middleware + evaluators) to implement this pattern safely in .NET.

Why loop programming matters

  • Iterative refinement: reduce hallucinations by asking the model to rework outputs until they meet quality criteria.
  • Multi-step tasks: break complex tasks into incremental attempts (repair, check, retry).
  • Automation & robustness: automatically retry flaky tools with idempotency and backoff, or orchestrate multi-tool workflows until success.
  • Cost/latency tradeoffs: each iteration consumes time and tokens—a deliberate loop strategy balances accuracy and cost.

Core MAF loop terms

  • Base agent / client: This is the model wrapped as an agent (an abstraction that receives requests and produces responses).
  • Loop wrapper or middleware: A piece that re-invokes the base agent automatically, applying evaluator logic between iterations.
  • Evaluator: A component that inspects the previous response and returns Continue or Stop. Examples:
    • Marker-based evaluator: stop when the output contains a specific marker (e.g., “DONE”).
    • Judge evaluator: ask an auxiliary judge model to say whether the output is acceptable.
    • Custom evaluator: your own logic that checks outputs, tool results, or external state.
  • Bounds: MaxIterations, timeouts, and cancellation tokens—mandatory to avoid runaway loops.
  • AgentRequest: the input to an agent (prompt, tools, options).
  • AgentResponse: the output (text, structured data, tool results).

Minimal, runnable-style C# example
Below is a full Program.cs and a simple csproj. The example uses a completion-marker evaluator (“DONE”) and a MaxIterations bound. It is a bit brain-dead, but it will give you a sense of how to string one of these together.


using System;
using System.Threading;
using System.Threading.Tasks;

using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Evaluators;
using Microsoft.Agents.AI.OpenAI.Clients;

class Program
{
static async Task Main(string[] args)
{
// Read API key (set as env var)
string? apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
if (string.IsNullOrEmpty(apiKey))
{
Console.WriteLine("Set OPENAI_API_KEY environment variable and re-run.");
return;
}
// 1) Create provider client (provider-specific)
var openAiClient = new OpenAiProviderClient(new OpenAiOptions { ApiKey = apiKey });

// 2) Convert provider client to an agent abstraction
AIAgent baseAgent = openAiClient.AsAIAgent();

// 3) Create a simple marker evaluator that stops when "DONE" appears
var evaluator = new CompletionMarkerLoopEvaluator("DONE");

// 4) Wrap the base agent with loop behavior and bounds
var loopOptions = new LoopAgentOptions { MaxIterations = 5 };
AIAgent loopAgent = new LoopAgent(baseAgent, evaluator, loopOptions);

// 5) Prepare request
var request = new AgentRequest
{
Prompt = "Summarize this paragraph and keep refining until you append DONE:\n\n" +
"The quick brown fox jumps over the lazy dog. This sentence includes all the letters of the English alphabet."
};

// 6) Use a timeout for safety
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
try
{
AgentResponse response = await loopAgent.InvokeAsync(request, cts.Token);
Console.WriteLine("Final response:\n" + response.Text);
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation timed out or was canceled.");
}
}
}

How to adapt this to the real MAF packages

  • Install packages
    • dotnet add package Microsoft.Agents.AI
    • dotnet add package Microsoft.Agents.AI.OpenAI
  • The logical steps are always pretty much the same: build a base agent, choose an evaluator, apply loop wrapper or middleware, and call it.

Designing better evaluators (AI judge and custom evaluator)


Marker evaluator (simple)

  • Pros: deterministic and cheap.
  • Cons: brittle.

AIJudge evaluator (higher quality)

  • Pattern: after each iteration, call a small judge prompt that returns YES/NO and a short reason. Use a very explicit evaluation prompt to reduce ambiguity.
  • Example judge prompt (send as a separate small completion request):
    “You are a strict grader. Given the task: [task description]. Given the model response: [response]. Is the response acceptable? Answer EXACTLY YES or NO followed by a short reason.”

Custom evaluator pattern (checks content + side effects)

  • Inspect response text for task markers (like DONE) and for required structured outputs.
  • Check external state (database, API) to determine if the side effect succeeded.
  • Optionally consult a judge model only when heuristic checks are inconclusive.

Sample custom evaluator

public class KeywordOrJudgeEvaluator : ILoopEvaluator
{
private readonly string _stopKeyword;
private readonly AIAgent? _judgeAgent;

public KeywordOrJudgeEvaluator(string stopKeyword, AIAgent? judgeAgent = null)
{
    _stopKeyword = stopKeyword;
    _judgeAgent = judgeAgent;
}

public async Task<LoopDecision> EvaluateAsync(AgentResponse lastResponse, CancellationToken ct)
{
    if (lastResponse.Text?.Contains(_stopKeyword, StringComparison.OrdinalIgnoreCase) == true)
        return LoopDecision.Stop();

    if (_judgeAgent != null)
    {
        var judgeRequest = new AgentRequest
        {
            Prompt = $"Is the following response acceptable? Answer YES or NO.\n\nResponse:\n{lastResponse.Text}\n\nCriteria: [list your criteria]"
        };
        var judgeResponse = await _judgeAgent.InvokeAsync(judgeRequest, ct);
        if (judgeResponse.Text.Trim().StartsWith("YES", StringComparison.OrdinalIgnoreCase))
            return LoopDecision.Stop();
    }

    return LoopDecision.Continue();
}
}

Practical safety and production best practices

  • Always set MaxIterations. Decide MaxIterations based on expected task complexity (2–5 for refinement tasks, more for longer repair flows).
  • Use a wall-clock timeout (CancellationTokenSource) to cap total runtime.
  • Log each iteration: input prompt, model output, evaluator decision, iteration duration, and any tool calls.
  • Be idempotent for side-effecting tool calls: include an idempotency key or track completed steps to avoid duplicate side effects.
  • Use backoff and limited retries for transient tool failures.
  • Consider human-in-the-loop for high-risk operations.
  • Capture metrics: iterations-per-task, average cost per task, success rate after N iterations.

Exponential backoff snippet

int attempt = 0;
while (attempt < maxRetries)
{
   attempt++;
   try { callTool(); break; }
   catch (TransientException)
   {
      await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
   }
}

Cost and latency tradeoffs

  • Each loop iteration = another model call (cost + latency). If you expect 2–3 iterations on average, estimate cost = baseCost × expectedIterations + judgeCost (if used).
  • Use marker evaluators when iterations are cheap and you can control the prompt reliably; use judge evaluators when marker brittleness is likely.
  • For low-latency needs, constrain MaxIterations or move part of the evaluation logic to a fast heuristic.

Debugging, testing, and observability tips

  • Unit test evaluators with mocked AgentResponse objects. Keep evaluator logic pure when possible so it’s easy to test.
  • Mock provider clients for integration tests so you can simulate iteration sequences and failures deterministically.
  • Log a concise iteration record: {iteration, promptFingerprint, outputHash, evaluatorDecision, duration, costEstimate}.
  • Add correlation IDs across iterations for traceability.

Troubleshooting common failure modes

  • Marker never appended → verify prompt instruction clarity, or switch to judge evaluator.
  • Judge flip-flops (YES/NO across iterations) → add hysteresis: require two consecutive YES judgments, or use a heuristic plus judge.
  • Side effects duplicated → make tools idempotent or track operation IDs.
  • Loop stalls (no progress) → add progress metrics and a stuck detection rule (stop if no semantic change after N iterations).

Real-world scenario examples

  • Document extraction and QA: agent extracts structured data, runs validators, requests corrections until extraction passes validators or MaxIterations reached.
  • Customer support automation: agent composes reply drafts and refines them until a judge model or human reviewer marks them acceptable.

Conclusion and next steps
Loop programming is a practical, powerful pattern for agentic AI: agent acts, inspects results, evaluates, and repeats — but only when bounded and observable. The Microsoft Agent Framework offers loop wrapper and evaluator patterns to implement this safely; adapt the example above to your MAF version and provider.

BlogWriter

My demo program, BlogWriter, uses a much more deterministic approach. While the author does pass its draft to the reviewer for evaluation, and they do create a small loop, a true looping approach would, perhaps, return better results. Something to try.

More to come soon…

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

Upgrade 643: The iPhone Duo Review

1 Share

Subtitle: October Experience Draft

Jason and Myke have spent the last few days using the iPhone Duo, and they're ready to report back. And, oh yeah, there's also a new iPad mini and a draft of Apple's forthcoming announcements this week!

This episode of Upgrade is sponsored by:

  • Fitbod: Get stronger, faster with a fitness plan that fits you. Get 25% off your membership.
  • Sentry: Mobile crash reporting and app monitoring. New users get $100 in Sentry credits with code upgrade26.
  • Planet Money: Listen wherever you get your podcasts.
  • Decagon: The AI concierge for every customer. Get a personalized demo.

Links and Show Notes:

Get Upgrade+. More content, no ads.
Check out Upgrade merch!
Submit Feedback
iPhone Duo: 24 hours in the Splash Zone – Six Colors
iPhone Duo review: Apple’s folding phone is a messy, expensive good time | The Verge
iPhone Duo review (emotional) - The Verge - YouTube
Magnetic Wallet with Stand for iPhone Duo | Belkin
iPhone Duo: A Photographer's Review - Tyler Stalman - YouTube
Daring Fireball: The iPhone Duo
Fineliner (Marco's Upcoming App)
Some iPhone Duo displays are cracking, seemingly all in the same way - 9to5Mac
iFixit iPhone Duo Teardown Points to Possible Cause of Screen Cracks - MacRumors
iPhone Duo Teardown: The Most Repairable Foldable Has a Huge Screen Problem - iFixit
Apple’s Foldable iPhone Duo Draws Early Complaints of the Screen Cracking - Bloomberg
Apple gives iPad mini its biggest update ever - Apple
Is the beloved iPad mini the best iPad? – Six Colors




Download audio: https://www.podtrac.com/pts/redirect.mp3/mgln.ai/e/613/clrtpod.com/m/pscrb.fm/rss/p/traffic.libsyn.com/upgrade/upgrade643.mp3
Read the whole story
alvinashcraft
43 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Omnibot Reborn: Giving a 1984 Robot Butler the Brain It Was Promised

1 Share
Tomy Omnibot with Ring-O companion robot mounted on an arm, OLED eye glowing

In 1984, Tomy sold a toy robot that promised a domestic future it couldn’t quite deliver. Forty years later, a maker in Miami gave it vision, a voice, and just enough intelligence to finally pull it off.

The post Omnibot Reborn: Giving a 1984 Robot Butler the Brain It Was Promised appeared first on Make: DIY Projects and Ideas for Makers.

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

What’s The Difference Between A Commercial And A Literary Plot?

1 Share

What’s the difference between a commercial and a literary plot? Discover how story goals, character journeys, and endings shape your novel.

There aren’t many authors (who actually sell books) who can get away without plotting. Bestselling authors, like Stephen King, who say they don’t plot, don’t realise they actually do it without realising it. They have an innate plotting talent. They just need less help than the rest of us.

I have noticed that even talented literary authors, who obviously don’t plot, have a shorter shelf life and fewer readers than writers who do plot.

My greatest wish as a reader is that more literary writers would learn to plot. Can you imagine the incredible books we would have to read? Some literary authors do this. Kate Atkinson writes beautifully, and her books have plots.

What’s The Difference Between A Commercial And A Literary Plot?

What is a literary plot?

  1. Generally, literary plots are full of isolated characters without a clear goal.
  2. They are slow and full of ambiguities.
  3. The author concentrates on the inner journeys of the characters and their psychological setbacks. They are often passive.
  4. The endings are often inconclusive and they mostly don’t end happily.

The bottom line? There are fewer book sales and the author makes less money, unless they win a literary prize.

What is a commercial plot?

  1. Generally, commercial plots are driven by characters with a well-defined story goal.
  2. There is lots of action and the author deals with the interior and exterior worlds of the characters.
  3. There are physical and emotional setbacks.
  4. The endings generally suit the genre of the story.

The bottom line?More of these books are sold and the author makes more money. There is next to no chance of winning a literary prize.

I think the way forward for modern writers is to marry the two.

  1. If you write literary fiction, spend some time on plotting and add some pace.
  2. If you write commercial fiction, make your characters more complex and add small twists to the endings of your stories.

Can You Combine Commercial And Literary Plotting?

You don’t have to choose between a commercial and a literary plot. You can use the strengths of both to tell a better story. Give your characters clear goals and obstacles to overcome, but also explore their inner lives, relationships, and motivations. Build a plot that keeps readers interested, and give them characters who stay with them long after they finish reading.

Examples Of Literary Authors Who Plot

  1. In Life After Life by Kate Atkinson, Ursula tries to survive the dangers she encounters in her repeated lives. Eventually, she develops a more specific goal: to kill Hitler before he can unleash the Second World War.
  2. In The Sense of an Ending by Julian Barnes, Tony wants to understand a mysterious bequest that forces him to revisit his past. As he investigates, he must confront memories and events that challenge his understanding of himself and his relationships.
  3. In Never Let Me Go by Kazuo Ishiguro, Kathy and Tommy want to prove they are truly in love so they can obtain a deferral from the organ donation programme and have more time together.

The Last Word

The best of both worlds may be the way forward. Give your characters clear goals, build in setbacks, and create complex characters whose journeys keep readers turning the pages. Happy writing.


by Amanda Patterson
© Amanda Patterson

More posts from Amanda:
  1. 7 Secrets To Writing Happy Characters Without Boring Your Audience
  2. What Is A Phobia? How To Write Characters With Phobias
  3. 3 Simple Ways To Make Your Hero Fight Back
  4. 7 Reasons To Write The Ending Of Your Novel First
  5. How To Make Readers Care About An Amoral Protagonist
  6. Why Revenge Is A Brilliant Plot For First-Time Writers
  7. The 5 Top Tips For Turning Memories Into A Memoir
  8. How To Write A Prologue: 5 Good Reasons To Include One
  9. How To Write A Locked-Room Mystery: The Secret To The Impossible Crime
  10. 10 Ways To Get Out Of A Writing Rut

Top Tip: Sign up for our free daily writing links.

The post What’s The Difference Between A Commercial And A Literary Plot? appeared first on Writers Write.

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

Train a Balance Bot With Reinforcement Learning

1 Share
Balancing robot made from M5Stack Bala2-Fire kit.

Teach a robot to balance, using reinforcement learning in simulation just like the big labs.

The post Train a Balance Bot With Reinforcement Learning appeared first on Make: DIY Projects and Ideas for Makers.

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

The Nightly Index Rebuild Job, 1998 to 2026: An Obituary

1 Share

The nightly index rebuild job has died after a long illness. It was born in 1998 to a hard disk that could not seek. It never believed the disk had been replaced. It is survived by page density, which did most of its work all along.

A newspaper obituary portrait in soft black and white of a server rack from the late 1990s, the kind the nightly index rebuild job was written for, slightly out of focus, with a small black border.

It was a job of habit. Every night at two, whether or not anything had changed, it rebuilt every index in the database. Every morning the database was exactly as fast as it had been the night before.

Nobody remembers who scheduled it. Everybody remembers being told not to remove it.

Early life of the index rebuild job

It was created in an age of spinning disks. A table whose pages lay out of order cost a read head real movement. Fragmentation was a physical thing then. You could hear it.

The job earned its place in those years. Its rebuilds put pages back in order, and the disk stopped travelling. It was, for a decade, unarguably right.

The disks changed in the 2010s. The job did not notice.

The examination

Before writing this notice I gave the deceased a fair hearing on SQL Server 2025. Three tables were built to be as fragmented as a table can be.

A million rows each, clustered on a random GUID. They were inserted in a thousand batches of a thousand, so the pages split as they filled. Each came out at 99.3 percent fragmentation and 68 percent page density. That’s 38,000 pages where an orderly table would need 26,000.

One was left alone. One got REORGANIZE. One got REBUILD. Then each was read cold and read warm. The seek test is further down, because my first version of it was wrong.

clustered index scan   fragmentation   pages    density   logical reads   cold physical   cold      warm
left alone             99.26%          38,269   68%       38,445          42,833          884 ms    383 to 431 ms
after REORGANIZE        0.48%          26,409   98%       26,579          26,623          696 ms    292 to 317 ms
after REBUILD           0.01%          26,317   98%       26,402          26,457          610 ms    283 to 314 ms

Cold means CHECKPOINT and then DROPCLEANBUFFERS. Warm is the spread over three passes, none of which touched the disk. My first version of this table dropped clean buffers without the CHECKPOINT. Its cold column measured something I can’t name. Those numbers are withdrawn.

One more trap, and it cost me a run. My first attempt at this rerun summed a column the seek index covers. So it measured that index and never touched the clustered one. The figures above sum a column only the clustered index holds.

What it was good at

The scan got faster. The reads fell from 38,445 to 26,402 after the rebuild, and 26,579 after the reorganize. The warm time fell by about a quarter.

Look at why. The reads fell by the same fraction as the page count. The rebuild didn’t make the pages faster to read. It made fewer of them, by filling each one to 98 percent instead of 68. The seek figures below come from a separate run on tables built the same way.

Density and fragmentation moved together in this test, so it cannot separate them. What it can show is that the reads fell exactly as the page count fell. A scan reads pages, not rows.

An obituary page illustration of two bookshelves, one with books packed tight, the other with the same books spaced out across more shelves.

What it was less good at

The seeks. My first run created the seek index after the maintenance. All three tables seeked through a fresh index and the numbers came out identical. That measured nothing, and a reviewer caught it.

The corrected run built the seek index first and let it fragment with the table. Then it was maintained along with everything else. It started at 99 percent fragmentation and 71 percent density on all three.

seek index (ix_n)      fragmentation   pages    density
left alone             99.36%          4,520    71%
after REORGANIZE        0.52%          3,249    99%
after REBUILD           0.00%          3,216    100%

10,000 seeks            logical reads   physical reads   CPU      elapsed
left alone, cold        30,113          4,592            447 ms   604 ms
after REORGANIZE, cold  30,089          3,288            338 ms   437 ms
after REBUILD, cold     30,071          3,176            411 ms   568 ms
left alone, warm        30,094          0                320 ms   320 ms
after REORGANIZE, warm  30,070          0                321 ms   321 ms
after REBUILD, warm     30,055          0                319 ms   318 ms

Cold means CHECKPOINT and then DROPCLEANBUFFERS before each table. My second attempt skipped the CHECKPOINT and got numbers that flattered maintenance. This is the third attempt.

Warm, the three sit within forty reads and three milliseconds of each other. Close, not identical. Cold, the maintained indexes needed about thirty percent fewer physical reads, because they had a third fewer pages to fetch. That is the only seek benefit this run found, and it lasts until the pages are cached.

Each seek averaged about three logical reads, 30,055 over 10,000. The tree is three levels deep whatever state the leaf is in.

Most transactional systems are seeks all day, on pages that stay cached. For them this run found nothing to feel.

The cost of the habit

REORGANIZE took 16 seconds on a million rows and wrote 595 MB to the transaction log. It moves pages one at a time and logs every move.

REBUILD took 0.85 seconds and wrote 1.1 MB. This database was in simple recovery, and a rebuild is minimally logged there. In full recovery it would have logged the whole index. Rebuild every index every night in full recovery and the log volume becomes its own problem. I didn’t measure how big, so I won’t put a number on it.

Both of them held locks while they worked. On a table of real size at two in the morning, that was the outage nobody attributed to the job.

Cause of death

Solid-state storage, which removed the read head the job was built to protect.

Better statistics maintenance, which turned out to be what people were mostly getting from the rebuild without knowing it. An ordinary rowstore rebuild refreshes that index’s own statistics with a full scan, as a side effect. Partitioned and resumable rebuilds have their own rules. The habit survived on that side effect for years.

And resumable, online operations. They let the rare table that needs it be rebuilt without the rest of the schema keeping it company.

Survived by

Page density and fragmentation, which this experiment could not tell apart. Check both on tables that get scanned, and rebuild when the reads say so.

Statistics, which should be updated on their own schedule, because that’s the part that was doing the good.

And one specific index in one specific database, which does need rebuilding, and whose owner knows exactly why.

A small black bordered newspaper notice reading in loving memory of the two a.m. maintenance window, no flowers.

In lieu of flowers

Query your fragmentation and your density, and measure maintenance against your own workload. This experiment could not separate the two, because they changed together. Ask which tables are scanned. Rebuild those when the measurement says so, and let the seek tables sleep.

If the job still runs in your shop and nobody knows what it’s for, I’ll help you write the eulogy.

Fragmentation is not the disease, it is the symptom the old disk happened to feel.

Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.

First appeared on The Nightly Index Rebuild Job, 1998 to 2026: An Obituary

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