The following article originally appeared on Hugo Bowne-Anderson’s newsletter, Vanishing Gradients, and is being republished here with the author’s permission.
In this post, we’ll build two AI agents from scratch in Python. One will be a coding agent, the other a search agent.
Why have I called this post “How to Build a General-Purpose AI Agent in 131 Lines of Python” then? Well, as it turns out now, coding agents are actually general-purpose agents in some quite surprising ways.
What I mean by this is once you have an agent that can write code, it can:
It’s more appropriate to think of coding agents as “computer-using agents” that happen to be great at writing code. That doesn’t mean you should always build a general-purpose agent, but it’s worth understanding what you’re actually building when you give an LLM shell access. That’s also why we’ll build a search agent in this post: to show the pattern works regardless of what you’re building.
For example, the coding agent we’ll build below has four tools: read, write, edit, and bash.
It can do
This is a small subset of what’s possible. It’s also the reason Claude Cowork seemed promising and why OpenClaw has taken off in the way it did.
So how can you build this? In this post, I’ll show you how to build a minimal version.
Agents are just LLMs with tools in a conversation loop and once you know the pattern, you’ll be able to build all types of agents with it:

As Ivan Leo wrote,
The barrier to entry is remarkably low: 30 minutes and you have an AI that can understand your codebase and make edits just by talking to it.
The goal here is to show that the pattern is the same regardless of what you’re building an agent for. Coding agent, search agent, browser agent, email agent, database agent: they all follow the same structure. The only difference is the tools you give them.
We’ll start with a coding agent that can read, write, and execute code. As stated, the ability to write and execute code with bash also turns a “coding agent” into a “general-purpose agent.” With shell access, it can do anything you can do from a terminal:
Check out Ivan Leo’s post for how to do this in JavaScript and Thorsten Ball’s post for how to do it in Go.
Start by creating our project:

We’ll be using Anthropic here. Feel free to use your LLM of choice. For bonus points, use Pydantic AI (or a similar library) and have a consistent interface for the various different LLM providers. That way you can use the same agentic framework for both Claude and Gemini!
Make sure you’ve got an Anthropic API key set as ANTHROPIC_API_KEY environment variable.
We’ll build our agent in four steps:
write, edit, and bash

Text in, text out. Good! Now let’s give it a tool.
We’ll start by implementing a tool called read which will allow the agent to read files from the filesystem. In Python, we can use Pydantic for schema validation, which also generates JSON schemas we can provide to the API:

The Pydantic model gives us two things: validation and a JSON schema. We can see what the schema looks like:


We wrap this into a tool definition that Claude understands:

Then we add tools to the API call, handle the tool request, execute it, and send the result back:

Let’s see what happens when we run it:

This script calls the Claude API with a user query passed via command line. It sends the query, gets a response, and prints it.
Note that the LLM matched on the tool description: Accurate, specific descriptions are key! It’s also worth mentioning that we’ve made two LLM calls here:
This often trips up people building agents for the first time, and Google has made a nice visualization of what we’re actually doing:

We have a read tool, but a coding agent needs to do more than read. It needs to:
That’s three more tools: write, edit, and bash.
Same pattern as read. First the schemas:

Then the executors:

And the tool definitions, along with the code that runs whichever one Claude picks:

The bash tool is what makes this actually useful: Claude can now write code, run it, see errors, and fix them. But it’s also dangerous. This tool could delete your entire filesystem! Proceed with caution: Run it in a sandbox, a container, or a VM.
Interestingly, bash is what turns a “coding agent” into a “general-purpose agent.” With shell access, it can do anything you can do from a terminal:
It was actually “Pi: The Minimal Agent Within OpenClaw” that inspired this example.
Try asking Claude to edit a file: It often wants to read it first to see what’s there. But our current code only handles one tool call. That’s where the agentic loop comes in.
Right now Claude can only call one tool per request. But real tasks need multiple steps: read a file, edit it, run it, see the error, fix it. We need a loop that lets Claude keep calling tools until it’s done.
We wrap the tool handling in a while True loop:

Note that here we have sent the entire past history of accumulated messages as we progress through loop iterations. When building this out more, you’ll want to engineer and manage your context more effectively. (See below for more on this.)
Let’s try a multistep task:

Right now the agent handles one query and exits. But we want a back-and-forth conversation: Ask a question, get an answer, ask a follow-up. We need an outer loop that keeps asking for input.
We wrap everything in a while True:

The messages list persists across turns, so Claude remembers context. That’s the complete coding agent.
Once again we’re merely appending all previous messages, which means the context will grow quite quickly!
An agent harness is the scaffolding and infrastructure that wraps around an LLM to turn it into an agent. It handles:
And more.
Think of it like this: The LLM is the brain; the harness is everything else that lets it actually do things.
What we’ve built above is the hello world of agent harnesses. It covers the loop, tool execution, and basic context management. What it doesn’t have: safety guardrails, token limits, persistence, or even a system prompt!
When building out from this basis, I encourage you to follow the paths of:
AGENTS.md from multiple directories, persistent sessions you can resume and branch, and an extensibility system (skills, extensions, prompts)SOUL.md, MEMORY.md, daily logs), proactive behavior (heartbeats, cron), preintegrated tools (browser, subagents, device control), and the ability to message you without being promptedIn order to really show you that the agentic loop is what powers any agent, we’ll now build a search agent (inspired by a podcast I did with search legends John Berryman and Doug Turnbull). We’ll use Gemini for the LLM and Exa for web search. You can find the code here.
But first, the astute reader may have an interesting question: If a coding agent really is a general-purpose agent, why would anyone want to build a search agent when we could just get a coding agent to extend itself and turn itself into a search agent? Well, because if you want to build a search agent for a business, you’re not going to do it by building a coding agent first… So let’s build it!
As before, we’ll build this step-by-step. Start by creating our project:

Set GEMINI_API_KEY (from Google AI Studio) and EXA_API_KEY (from exa.ai) as environment variables.
We’ll build our agent in four steps (the same four steps as always):


web_search)Gemini can answer from its training data, but we don’t want that, man! For current information, it needs to search the web. We’ll give it a web_search tool that calls Exa.

The system instruction grounds the model, (ideally) forcing it to search instead of guessing. Note that you can configure Gemini to always use web_search, which is 100% dependable, but I wanted to show the pattern that you can use with any LLM API.
We then send the tool call result back to Gemini:

Some questions need multiple searches. “Compare X and Y” requires searching for X, then searching for Y. We need a loop that lets Gemini keep searching until it has enough information.


Same as before: We want back-and-forth conversation, not one query and exit. Wrap everything in an outer loop:

Messages persist across turns, so follow-up questions have context.
The pattern is the same for both agents. Add any tool:
web_search to the coding agent: Look things up while codingbash to the search agent: Act on what it findsbrowser: Navigate websitessend_email: Communicatedatabase_query: Run SQLOne thing we’ll be doing is showing how general purpose a coding agent really can be. As Armin Ronacher wrote in “Pi: The Minimal Agent Within OpenClaw”:
Pi’s entire idea is that if you want the agent to do something that it doesn’t do yet, you don’t go and download an extension or a skill or something like this. You ask the agent to extend itself. It celebrates the idea of code writing and running code.
Building agents is straightforward. The magic isn’t complex algorithms; it’s the conversation loop and well-designed tools.
Both agents follow the same pattern:
The only difference is the tools.
Thank you to Ivan Leo, Eleanor Berger, Mike Powers, Thomas Wiecki, and Mike Loukides for providing feedback on drafts of this post.
The Shift, Agentic Edition connects the people building AI tools with those creating agents, so we can all level up together.
In this episode, members of the Microsoft Azure Database team, Nikisha, James, Debbi and Jared explore a question from you, our community:
Wait, my agent needs a database?
Get the eBook:
Building a strategic database ecosystem: From Choice to Orchestration | Microsoft Azure
https://aka.ms/databaseecosystem
Join our community: https://techcommunity.microsoft.com/
Meet the Team:
Nikisha Reyes-Grange, Director Product Marketing
https://www.linkedin.com/in/nikisha/
James Codella, Principal Product Manager
https://www.linkedin.com/in/jamescodella/
Jared Meade, Sr. Product Marketing Manager
https://www.linkedin.com/in/jared-meade/
Debbi Lyons, Director Product Marketing
https://www.linkedin.com/in/debbilyons/
The Shift podcast is a place for experts to share their insights and opinions. As students of the future of technology, Microsoft values inputs from a diverse set of voices. That said, the opinions and findings of our guests are their own and they may not necessarily reflect Microsoft's own research or positions.
This episode of The Shift was recorded in January 2026. All information about products and offers are relevant to the time of recording.
In this stream, I'll start working on a source generator idea to exclude named properties from equality in a C# record.
https://github.com/JasonBock/Transpire/issues/44
#dotnet #csharp
Read the full Show Notes and search through the world's largest audio library on Agile and Scrum directly on the Scrum Master Toolbox Podcast website: http://bit.ly/SMTP_ShowNotes.
"Communication clarity is more important than technical complexity, because if you do not understand, it's pretty hard to execute." — Iryna Stelmakh
Iryna shares one of her most painful career stories — a project in the healthcare domain focused on cancer treatment research data. When she joined, she was managing around 9 projects simultaneously and agreed to take this one on the condition that a strong technical lead would own the technical direction. The project began with a critical misunderstanding: sales had communicated that the client needed a database redesign, but the client actually needed a migration to a different database type. Similar words, fundamentally different work.
For three months, the team worked through research and discovery phases, trying to understand the actual problem. But communication gaps — compounded by language barriers between the Ukrainian development team and the US-based client — prevented them from identifying the real need in time. Iryna trusted the technical lead's reports that everything was on track. She relied instead of checking. Eventually, the client lost confidence and left. It remains the only project in her career she considers a genuine failure.
The lesson cuts deep: teams must have people who can ask the right questions early. As Vasco observes, the root cause was implicit assumptions that were never discovered or explored by the different people involved.
In this episode, we also talk about the importance of the monitoring and controlling phase in project management.
Self-reflection Question: When you trust a team member's assessment that "everything is fine," what verification steps do you take to confirm that understanding is truly shared across all stakeholders?
Iryna recommends Team Topologies by Matthew Skelton and Manuel Pais as a book that changed how she thinks about Agile leadership. "Great agile leadership is not only about frameworks, but it's about communication, influence, and the ability to align people around shared goals," she explains. The book helped her understand that Agile isn't just about team process — it's about organizational structure, team boundaries, and responsibilities. She also recommends Never Split the Difference by Chris Voss for Scrum Masters who want to sharpen their communication and influence tactics. As Iryna puts it, communication is one of the most important skills a Scrum Master must have.
[The Scrum Master Toolbox Podcast Recommends]
Angela thought she was just there to coach a team. But now, she's caught in the middle of a corporate espionage drama that could make or break the future of digital banking. Can she help the team regain their mojo and outwit their rivals, or will the competition crush their ambitions? As alliances shift and the pressure builds, one thing becomes clear: this isn't just about the product—it's about the people.
🚨 Will Angela's coaching be enough? Find out in Shift: From Product to People—the gripping story of high-stakes innovation and corporate intrigue.
[The Scrum Master Toolbox Podcast Recommends]
About Iryna Stelmakh
Iryna Stelmakh is a Project & Delivery Leader and Agile Coach who helps leaders turn complexity into clarity. With 10+ years across US, Nordic, and Eastern European environments, she works at the intersection of business transformation and human systems, building resilient organizations and high-performing teams in complex contexts.
You can link with Iryna Stelmakh on LinkedIn.