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

Daily Reading List – March 12, 2026 (#740)

1 Share

It was a day. But we had a fun read-through of our Google Cloud Next developer keynote. I’m excited to see many of you in person soon!

[article] AI productivity gains are 10%, not 10x. We’ve said the same thing publicly. There are tasks that have 3x or 10x productivity gains, but it’s not uniform across the whole day or entire value stream.

[article] CEOs think AI use is mandatory — but employees don’t agree, survey says. This story posts about the disconnect between execs and employees, but notice the blurb about middle managers. You don’t win that tier over, every initiative tends to die.

[article] Pity the developers who resist agentic coding. I wouldn’t use the word pity at this point. This article points out that devs are missing the thrill of really building at the speed of thought.

[blog] Cloud CISO Perspectives: New Threat Horizons report highlights current cloud threats. Even if the threats themselves don’t change (they do), notice how bad actors seamlessly switch to the ones getting less attention.

[blog] Introducing Replit Agent 4: Built for Creativity. How we work changed. Stop fighting it. Tools like Replit do a great job of showing what the future looks like.

[blog] What you need to know about the Gemini Embedding 2 model. This is new, but not getting the attention it deserves. This new embeddings model makes life much easier for those with a mix of data.

[blog] Human Insight, Amplified: How Forrester Is Reinventing Research For The AI Era. This seems like a good idea. Analyst firms need to rethink their research approach, and distribution. This addresses the latter.

[blog] Protecting cities with AI-driven flash flood forecasting. Great work from Microsoft Research to make this capability available to local communities.

[blog[ 5 design skills to sharpen in the AI era. From Figma, this seems like a useful list of areas to focus on.

[blog] Inference on GKE Private Clusters. Good use case! Can a Kubernetes cluster with no internet access still do AI inference? Yes, yes it can.

Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:



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

Build an Agent That Thinks Like a Data Scientist: How We Hit #1 on DABStep with Reusable Tool Generation

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

How we compare model quality in Cursor

1 Share
We use a hybrid online-offline eval process to keep our understanding of model quality aligned with what developers actually do.
Read the whole story
alvinashcraft
31 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Coding After Coders: The End of Computer Programming as We Know It

1 Share

Coding After Coders: The End of Computer Programming as We Know It

Epic piece on AI-assisted development by Clive Thompson for the New York Times Magazine, who spoke to more than 70 software developers from companies like Google, Amazon, Microsoft, Apple, plus other individuals including Anil Dash, Thomas Ptacek, Steve Yegge, and myself.

I think the piece accurately and clearly captures what's going on in our industry right now in terms appropriate for a wider audience.

I talked to Clive a few weeks ago. Here's the quote from me that made it into the piece.

Given A.I.’s penchant to hallucinate, it might seem reckless to let agents push code out into the real world. But software developers point out that coding has a unique quality: They can tether their A.I.s to reality, because they can demand the agents test the code to see if it runs correctly. “I feel like programmers have it easy,” says Simon Willison, a tech entrepreneur and an influential blogger about how to code using A.I. “If you’re a lawyer, you’re screwed, right?” There’s no way to automatically check a legal brief written by A.I. for hallucinations — other than face total humiliation in court.

The piece does raise the question of what this means for the future of our chosen line of work, but the general attitude from the developers interviewed was optimistic - there's even a mention of the possibility that the Jevons paradox might increase demand overall.

One critical voice came from an Apple engineer:

A few programmers did say that they lamented the demise of hand-crafting their work. “I believe that it can be fun and fulfilling and engaging, and having the computer do it for you strips you of that,” one Apple engineer told me. (He asked to remain unnamed so he wouldn’t get in trouble for criticizing Apple’s embrace of A.I.)

That request to remain anonymous is a sharp reminder that corporate dynamics may be suppressing an unknown number of voices on this topic.

Tags: new-york-times, careers, ai, generative-ai, llms, ai-assisted-programming, press-quotes, deep-blue

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

Agent Harness in Agent Framework

1 Share

Agent harness is the layer where model reasoning connects to real execution: shell and filesystem access, approval flows, and context management across long-running sessions. With Agent Framework, these patterns can now be built consistently in both Python and .NET.

In this post, we’ll look at three practical building blocks for production agents:

  • Local shell harness for controlled host-side execution
  • Hosted shell harness for managed execution environments
  • Context compaction for keeping long conversations efficient and reliable

Shell and Filesystem Harness

Many agent experiences need to do more than generate text. They need to inspect files, run commands, and work with the surrounding environment in a controlled way. Agent Framework makes it possible to model those capabilities explicitly, with approval patterns where needed.

The following examples show compact harness patterns in both Python and .NET.

Python: Local shell with approvals

import asyncio
import subprocess
from typing import Any

from agent_framework import Agent, Message, tool
from agent_framework.openai import OpenAIResponsesClient


@tool(approval_mode="always_require")
def run_bash(command: str) -> str:
    """Execute a shell command locally and return stdout, stderr, and exit code."""
    result = subprocess.run(
        command,
        shell=True,
        capture_output=True,
        text=True,
        timeout=30,
    )
    parts: list[str] = []
    if result.stdout:
        parts.append(result.stdout)
    if result.stderr:
        parts.append(f"stderr: {result.stderr}")
    parts.append(f"exit_code: {result.returncode}")
    return "\n".join(parts)


async def run_with_approvals(query: str, agent: Agent) -> Any:
    current_input: str | list[Any] = query

    while True:
        result = await agent.run(current_input)
        if not result.user_input_requests:
            return result

        next_input: list[Any] = [query]
        for request in result.user_input_requests:
            print(f"Shell request: {request.function_call.name}")
            print(f"Arguments: {request.function_call.arguments}")
            approved = (await asyncio.to_thread(input, "Approve command? (y/n): ")).strip().lower() == "y"
            next_input.append(Message("assistant", [request]))
            next_input.append(Message("user", [request.to_function_approval_response(approved)]))
            if not approved:
                return "Shell command execution was rejected by user."

        current_input = next_input


async def main() -> None:
    client = OpenAIResponsesClient(
        model_id="<responses-model-id>",
        api_key="<your-openai-api-key>",
    )
    local_shell_tool = client.get_shell_tool(func=run_bash)

    agent = Agent(
        client=client,
        instructions="You are a helpful assistant that can run shell commands.",
        tools=[local_shell_tool],
    )

    result = await run_with_approvals(
        "Use run_bash to execute `python --version` and show only stdout.",
        agent,
    )
    print(result)


if __name__ == "__main__":
    asyncio.run(main())

This pattern keeps execution on the host machine while giving the application a clear approval checkpoint before the command runs.

Security note: For local shell execution, we recommend running this logic in an isolated environment and keeping explicit approval in place before commands are allowed to run.

Python: Hosted shell in a managed environment

import asyncio

from agent_framework import Agent
from agent_framework.openai import OpenAIResponsesClient


async def main() -> None:
    client = OpenAIResponsesClient(
        model_id="<responses-model-id>",
        api_key="<your-openai-api-key>",
    )
    shell_tool = client.get_shell_tool()

    agent = Agent(
        client=client,
        instructions="You are a helpful assistant that can execute shell commands.",
        tools=shell_tool,
    )

    result = await agent.run("Use a shell command to show the current date and time")
    print(result)

    for message in result.messages:
        shell_calls = [c for c in message.contents if c.type == "shell_tool_call"]
        shell_results = [c for c in message.contents if c.type == "shell_tool_result"]

        if shell_calls:
            print(f"Shell commands: {shell_calls[0].commands}")
        if shell_results and shell_results[0].outputs:
            for output in shell_results[0].outputs:
                if output.stdout:
                    print(f"Stdout: {output.stdout}")
                if output.stderr:
                    print(f"Stderr: {output.stderr}")
                if output.exit_code is not None:
                    print(f"Exit code: {output.exit_code}")


if __name__ == "__main__":
    asyncio.run(main())

Hosted shell is useful when you want the agent to execute commands in a provider-managed environment rather than directly on the local machine.

.NET: Local shell with approvals

using System.ComponentModel;
using System.Diagnostics;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;

var apiKey = "<your-openai-api-key>";
var model = "<responses-model-id>";

[Description("Execute a shell command locally and return stdout, stderr and exit code.")]
static string RunBash([Description("Bash command to execute.")] string command)
{
    using Process process = new()
    {
        StartInfo = new ProcessStartInfo
        {
            FileName = "/bin/bash",
            ArgumentList = { "-lc", command },
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
        }
    };

    process.Start();
    process.WaitForExit(30_000);

    string stdout = process.StandardOutput.ReadToEnd();
    string stderr = process.StandardError.ReadToEnd();

    return $"stdout:\n{stdout}\nstderr:\n{stderr}\nexit_code:{process.ExitCode}";
}

IChatClient chatClient = new OpenAIClient(apiKey)
    .GetResponsesClient(model)
    .AsIChatClient();

AIAgent agent = chatClient.AsAIAgent(
    name: "LocalShellAgent",
    instructions: "Use tools when needed. Avoid destructive commands.",
    tools: [new ApprovalRequiredAIFunction(AIFunctionFactory.Create(RunBash, name: "run_bash"))]);

AgentSession session = await agent.CreateSessionAsync();
AgentResponse response = await agent.RunAsync("Use run_bash to execute `dotnet --version` and return only stdout.", session);

List<FunctionApprovalRequestContent> approvalRequests = response.Messages
    .SelectMany(m => m.Contents)
    .OfType<FunctionApprovalRequestContent>()
    .ToList();

while (approvalRequests.Count > 0)
{
    List<ChatMessage> approvals = approvalRequests
        .Select(request => new ChatMessage(ChatRole.User, [request.CreateResponse(approved: true)]))
        .ToList();

    response = await agent.RunAsync(approvals, session);
    approvalRequests = response.Messages
        .SelectMany(m => m.Contents)
        .OfType<FunctionApprovalRequestContent>()
        .ToList();
}

Console.WriteLine(response);

Like the Python version, this approach combines local execution with an explicit approval flow so the application stays in control of what actually runs.

Security note: For local shell execution, we recommend running this logic in an isolated environment and keeping explicit approval in place before commands are allowed to run.

.NET: Hosted shell with protocol-level configuration

using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;
using OpenAI.Responses;

var apiKey = "<your-openai-api-key>";
var model = "<responses-model-id>";

IChatClient chatClient = new OpenAIClient(apiKey)
    .GetResponsesClient(model)
    .AsIChatClient();

CreateResponseOptions hostedShellOptions = new();
hostedShellOptions.Patch.Set(
    "$.tools"u8,
    BinaryData.FromObjectAsJson(new object[]
    {
        new
        {
            type = "shell",
            environment = new
            {
                type = "container_auto"
            }
        }
    }));

AIAgent agent = chatClient
    .AsBuilder()
    .BuildAIAgent(new ChatClientAgentOptions
    {
        Name = "HostedShellAgent",
        UseProvidedChatClientAsIs = true,
        ChatOptions = new ChatOptions
        {
            Instructions = "Use shell commands to answer precisely.",
            RawRepresentationFactory = _ => hostedShellOptions
        }
    });

AgentResponse response = await agent.RunAsync("Use a shell command to print UTC date/time. Return only command output.");
Console.WriteLine(response);

This makes it possible to target a managed shell environment from .NET today while keeping the rest of the agent flow in the standard Agent Framework programming model.

Context Compaction

Long-running agent sessions accumulate chat history that can exceed a model’s context window. The Agent Framework includes a built-in compaction system that automatically manages conversation history before each model call — keeping agents within their token budget without losing important context (Docs).

Python: In-run compaction on the agent

import asyncio

from agent_framework import Agent, InMemoryHistoryProvider, SlidingWindowStrategy, tool
from agent_framework.openai import OpenAIChatClient


@tool(approval_mode="never_require")
def get_weather(city: str) -> str:
    weather_data = {
        "London": "cloudy, 12°C",
        "Paris": "sunny, 18°C",
        "Tokyo": "rainy, 22°C",
    }
    return weather_data.get(city, f"No data for {city}")


async def main() -> None:
    client = OpenAIChatClient(
        model_id="<chat-model-id>",
        api_key="<your-openai-api-key>",
    )

    agent = Agent(
        client=client,
        instructions="You are a helpful weather assistant.",
        tools=[get_weather],
        context_providers=[InMemoryHistoryProvider()],
        compaction_strategy=SlidingWindowStrategy(keep_last_groups=3),
    )

    session = agent.create_session()
    for query in [
        "What is the weather in London?",
        "How about Paris?",
        "And Tokyo?",
        "Which city is the warmest?",
    ]:
        result = await agent.run(query, session=session)
        print(result.text)


if __name__ == "__main__":
    asyncio.run(main())

This example keeps the most recent conversational context intact while trimming older tool-heavy exchanges that no longer need to be replayed in full.

.NET: Compaction pipeline with multiple strategies

using System.ComponentModel;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Compaction;
using Microsoft.Extensions.AI;
using OpenAI;

var apiKey = "<your-openai-api-key>";
var model = "<chat-model-id>";

[Description("Look up the current price of a product by name.")]
static string LookupPrice([Description("The product to look up.")] string productName) =>
    productName.ToUpperInvariant() switch
    {
        "LAPTOP" => "The laptop costs $999.99.",
        "KEYBOARD" => "The keyboard costs $79.99.",
        "MOUSE" => "The mouse costs $29.99.",
        _ => $"No data for {productName}."
    };

IChatClient chatClient = new OpenAIClient(apiKey)
    .GetChatClient(model)
    .AsIChatClient();

PipelineCompactionStrategy compactionPipeline = new(
    new ToolResultCompactionStrategy(CompactionTriggers.MessagesExceed(7)),
    new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(4)),
    new TruncationCompactionStrategy(CompactionTriggers.GroupsExceed(12)));

AIAgent agent = chatClient
    .AsBuilder()
    .UseAIContextProviders(new CompactionProvider(compactionPipeline))
    .BuildAIAgent(new ChatClientAgentOptions
    {
        Name = "ShoppingAssistant",
        ChatOptions = new ChatOptions
        {
            Instructions = "You are a concise shopping assistant.",
            Tools = [AIFunctionFactory.Create(LookupPrice)]
        },
        ChatHistoryProvider = new InMemoryChatHistoryProvider()
    });

AgentSession session = await agent.CreateSessionAsync();

string[] prompts =
[
    "What's the price of a laptop?",
    "How about a keyboard?",
    "And a mouse?",
    "Which is cheapest?",
    "What was the first product I asked about?"
];

foreach (string prompt in prompts)
{
    Console.WriteLine($"User: {prompt}");
    AgentResponse response = await agent.RunAsync(prompt, session);
    Console.WriteLine($"Agent: {response}\\n");

    if (session.TryGetInMemoryChatHistory(out var history))
    {
        Console.WriteLine($"[Stored message count: {history.Count}]\\n");
    }
}

By combining multiple compaction strategies, you can keep sessions responsive and cost-aware without giving up continuity.

What’s Next?

These patterns make Agent Framework a stronger foundation for real-world agent systems:

  • Local shell with approvals enables controlled execution on the host.
  • Hosted shell supports execution in managed environments.
  • Compaction strategies help long-running sessions stay within limits while preserving useful context.

Whether you are building an assistant that can inspect a project workspace or a multi-step workflow that needs durable context over time, these capabilities help close the gap between model reasoning and practical execution.

For more information, check out our documentation and examples on GitHub, and install the latest packages from NuGet (.NET) or PyPI (Python).

The post Agent Harness in Agent Framework appeared first on Microsoft Agent Framework.

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

What is the Windows Clipboard?

1 Share


Unicode Clipboard Img

The Windows clipboard is a built‑in feature that temporarily stores anything you copy—text, images, files. The clipboard is stored in regular RAM, just like any other application data. There is no dedicated hardware region or special memory bank reserved for it. It is wrapped in OS‑level access control and session isolation.

How Windows Protects Clipboard Data

The Windows clipboard uses normal system memory, not a special protected memory region — but Windows does protect access to it. Only processes running in the same user session can access the 
clipboard. A random background service running as SYSTEM cannot read your clipboard unless it explicitly impersonates your user.

Apps must use the official APIs, see below.

Windows enforces:

  • Only one process can open the clipboard at a time.

  • A process must own the clipboard to modify it.

  • Apps cannot read the clipboard without requesting access.

Technical Details

The Windows clipboard was designed as a mechanism that Microsoft Windows operating systems use to allow data to be shared between applications. It first appeared in Windows 3.1, although its functionality has greatly increased since then. 


When you copy something, Windows doesn’t just store the raw bytes. It stores one or more representations of the data, each tagged with a format ID.

A clipboard format tells Windows and applications:

  • what kind of data is stored

  • how to interpret it

  • how to convert it if needed

This is why you can copy text from Word and paste it as plain text, rich text, HTML, or even an image depending on the target app.

Clipboard formats commonly used (CF_TEXT, CF_UNICODETEXT, CF_HDROP, custom formats) are stored as handles to memory blocks.

Microsoft also provides the ability for “private data formats”, custom formats that are application specific (for example, fonts in a word processing program), and that could be registered so that other applications could transfer data in these formats. Two private data formats that are used extensively are object link embedding CF_OLE (0xC013) decimal 49171 and CF_ DataObjects (0xC009) decimal 49161.

For an application to send data to the clipboard, it first allocates a block of global memory using GlobalAlloc, Global- Lock, and GlobalUnlock (Fig. 1). It then opens the clipboard using OpenClipboard, empties it using EmptyClipboard, places the clipboard data using SetClipboard and then closes the clipboard using CloseClipboard (Microsoft.com,). While only one piece of data can be present in the clipboard at any given time, it is possible to send and store that piece of data in multiple formats by performing multiple SetClipboardData functions. 

This allows applications that handle data in different ways to all have access to it (e.g., text in Microsoft Word with or without formatting). Once data is in the clipboard, the block of global memory belongs to the clipboard and other pointers to it become invalid. Getting data from the clipboard (Fig. 2) is even easier and involves opening the clipboard, determining which of the available clipboard formats to retrieve (this is an application specific task), retrieving a handle to the data, and then closing the clipboard.

Live look at list all formats when you copy an item.
InsideClipboard - View the content of all formats stored in the Clipboard (nirsoft.net)

Open Source: https://doxygen.reactos.org/d0/dd2/win32ss_2user_2ntuser_2clipboard_8c.html#afb1abd5c321fb8e6a65f8994dcec07e1

The clipboard formats defined by the system are called standard clipboard formats. These clipboard formats are described in the following table.

Constant/value Description
CF_BITMAP
2
A handle to a bitmap (HBITMAP).
CF_DIB
8
A memory object containing a BITMAPINFO structure followed by the bitmap bits.
CF_DIBV5
17
A memory object containing a BITMAPV5HEADER structure followed by the bitmap color space information and the bitmap bits.
CF_DIF
5
Software Arts' Data Interchange Format.
CF_DSPBITMAP
0x0082
Bitmap display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in bitmap format in lieu of the privately formatted data.
CF_DSPENHMETAFILE
0x008E
Enhanced metafile display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in enhanced metafile format in lieu of the privately formatted data.
CF_DSPMETAFILEPICT
0x0083
Metafile-picture display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in metafile-picture format in lieu of the privately formatted data.
CF_DSPTEXT
0x0081
Text display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in text format in lieu of the privately formatted data.
CF_ENHMETAFILE
14
A handle to an enhanced metafile (HENHMETAFILE).
CF_GDIOBJFIRST
0x0300
Start of a range of integer values for application-defined GDI object clipboard formats. The end of the range is CF_GDIOBJLAST.
Handles associated with clipboard formats in this range are not automatically deleted using the GlobalFree function when the clipboard is emptied. Also, when using values in this range, the hMem parameter is not a handle to a GDI object, but is a handle allocated by the GlobalAlloc function with the GMEM_MOVEABLE flag.
CF_GDIOBJLAST
0x03FF
See CF_GDIOBJFIRST.
CF_HDROP
15
A handle to type HDROP that identifies a list of files. An application can retrieve information about the files by passing the handle to the DragQueryFile function.
CF_LOCALE
16
The data is a handle to the locale identifier associated with text in the clipboard. When you close the clipboard, if it contains CF_TEXT data but no CF_LOCALE data, the system automatically sets the CF_LOCALE format to the current input language. You can use the CF_LOCALE format to associate a different locale with the clipboard text.
An application that pastes text from the clipboard can retrieve this format to determine which character set was used to generate the text.
Note that the clipboard does not support plain text in multiple character sets. To achieve this, use a formatted text data type such as RTF instead.
The system uses the code page associated with CF_LOCALE to implicitly convert from CF_TEXT to CF_UNICODETEXT. Therefore, the correct code page table is used for the conversion.
CF_METAFILEPICT
3
Handle to a metafile picture format as defined by the METAFILEPICT structure. When passing a CF_METAFILEPICT handle by means of DDE, the application responsible for deleting hMem should also free the metafile referred to by the CF_METAFILEPICT handle.
CF_OEMTEXT
7
Text format containing characters in the OEM character set. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data.
CF_OWNERDISPLAY
0x0080
Owner-display format. The clipboard owner must display and update the clipboard viewer window, and receive the WM_ASKCBFORMATNAME, WM_HSCROLLCLIPBOARD, WM_PAINTCLIPBOARD, WM_SIZECLIPBOARD, and WM_VSCROLLCLIPBOARD messages. The hMem parameter must be NULL.
CF_PALETTE
9
Handle to a color palette. Whenever an application places data in the clipboard that depends on or assumes a color palette, it should place the palette on the clipboard as well.
If the clipboard contains data in the CF_PALETTE (logical color palette) format, the application should use the SelectPalette and RealizePalette functions to realize (compare) any other data in the clipboard against that logical palette.
When displaying clipboard data, the clipboard always uses as its current palette any object on the clipboard that is in the CF_PALETTE format.
CF_PENDATA
10
Data for the pen extensions to the Microsoft Windows for Pen Computing.
CF_PRIVATEFIRST
0x0200
Start of a range of integer values for private clipboard formats. The range ends with CF_PRIVATELAST. Handles associated with private clipboard formats are not freed automatically; the clipboard owner must free such handles, typically in response to the WM_DESTROYCLIPBOARD message.
CF_PRIVATELAST
0x02FF
See CF_PRIVATEFIRST.
CF_RIFF
11
Represents audio data more complex than can be represented in a CF_WAVE standard wave format.
CF_SYLK
4
Microsoft Symbolic Link (SYLK) format.
CF_TEXT
1
Text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data. Use this format for ANSI text.
CF_TIFF
6
Tagged-image file format.
CF_UNICODETEXT
13
Unicode text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data.
CF_WAVE
12
Represents audio data in one of the standard wave formats, such as 11 kHz or 22 kHz PCM.
Read the whole story
alvinashcraft
7 hours ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories