In part 4 of this series we created our final two agents. In this final part of the series we’ll review the workflow that we create with the StateGraph class of LangGraph.
Continue readingCreating a multi-agent application – Part 5 (final)
Creating a multi-agent application – Part 4
In part 3 we looked at creating the researcher. As promised, today we’ll look at the author.

You’ll notice in the following code a great deal of similarity to what we’ve seen before. The goal is to create a code “template” that we can follow as we create any agent; departing only for the agent’s special requirements and abilities.
As usual, we start with the factory method:
def create_author_chain():
"""Creates the author chain."""
def author_invoke(state):
research = state.get("research_findings", [])
research_text = "\n\n".join(research) if research else "No research available."
prompt = author_prompt_template.format(
main_task=state.get("main_task", ""),
research_findings=research_text,
draft=state.get("draft", ""),
review_notes=state.get("review_notes", "")
)
try:
response = llm.invoke(prompt)
content = response.content if hasattr(response, 'content') else str(response)
return content if content else "Draft in progress..."
except Exception as e:
print(f"Author error: {e}")
return "Error generating draft. Please try again."
return author_invoke
# Creating a callable object
author_chain = create_author_chain()
Continue reading Creating a multi-agent application — Part 3
In the previous post, we examined how to load the libraries we need and how to create the Blogger agent. In this post, we’ll examine the Research agent. You’ll no doubt notice the pattern of defining the template, the agent and the node. This will carry through for all the agents we’ll create.
researcher_prompt_template = """You are a researcher for a technical blog
focused on .NET and AI with examples in C# and Python
Research Topic: {task}
Your goal is to find relevant, up-to-date insights for developers. Focus on:
- Key trends, challenges, or innovations
- Real-world use cases
- Supporting data or quotes from credible sources
- Simple explanations
- Short code examples in C# or Python
Summarize your findings concisely.
"""
In this template we start by telling the researcher what role it will play. We then provide a goal and narrow that goal to a series of topics to focus on and how to present that data.
Continue readingCreating a multi-agent application. Part 2
In my previous post, I showed the output of a multi-agent application I wrote to create blog posts (not to worry, it is for demonstration purposes only). In this post, I will begin the process of working through the code, line by line.
This application is written in Python, in a Colab notebook, using (among other things) LangChain and LangGraph. To follow along you will need to obtain an API key from OpenAI and a key from Tavily.
If you are a C# programmer with little or no Python experience, don’t panic! Python is pretty readable, and I’ll explain any part that is potentially obscure or confusing.
This will be a multi-agent application. The agents we’ll create will be:
- Blogger which will orchestrate the others
- Researcher, which will search the web for relevant information
- Author, which will write drafts of the blog post
- Reviewer, which will evaluate the drafts and suggest improvements
As a general rule, I try to limit the number of agents to 3-5. Any more than that can get terribly complicated with diminishing returns. Your mileage may vary.
Continue readingCreating a multi-agent application – Part 1
The following text was created by a multi-agent application designed to create blog posts. In my next post we’ll take the application apart, step by step. For now, here is a test run with the prompt Use of multiagents in writing a C# application.”
Draft created: 2653 characters
{‘author’: {‘draft’: ‘# Harnessing Multi-Agent Systems in C# Applications\n’
‘\n’
‘In the evolving landscape of software development, ‘
‘multi-agent systems (MAS) have emerged as a powerful ‘
‘paradigm, particularly in enhancing the functionality of ‘
‘applications. However, the integration of these systems ‘
‘into C# applications comes with its own set of ‘
‘challenges and considerations. This post explores the ‘
‘key aspects of implementing multi-agent systems in C#, ‘
‘drawing from recent research findings.\n’
‘\n’
‘## Understanding Multi-Agent Systems\n’
‘\n’
‘At its core, a multi-agent system consists of multiple ‘
‘autonomous agents that interact with one another to ‘
‘achieve specific goals. These agents can be designed to ‘
‘perform tasks collaboratively, leading to improved ‘
‘efficiency and problem-solving capabilities. However, as ‘
‘highlighted by Elliot One, simply increasing the number ‘
‘of agents does not guarantee better outcomes. In fact, ‘
‘it can complicate the debugging process, making it more ‘
‘difficult to trace failures and understand system ‘
‘behavior. This underscores the importance of thoughtful ‘
‘design and implementation when developing multi-agent ‘
‘systems.\n’
‘\n’
ReAct and Agents in AI
In the previous post, we looked at the use of Chain of Thought (CoT) reasoning in the context of LLMs. For an LLM to take action in the world, however, it needs agents. The paradigm for this is called ReAct—that is, REason and ACT.
In order to interact with the world, the agent will use tools (such as code that accesses APIs, searches the Internet, etc.). This creates a dynamic cycle:

Think—the LLM reasons and decides what tool to use
ACT—the LLM uses the tool to take action in the world
Observe—the LLM observes the result of the action and adjusts accordingly, refining its plan
The cycle ends when the LLM has its final answer.
Continue readingAI Reasoning and Planning
Until very recently, it was observed that LLMs had a very hard time with complex problems. Context was lost, memory of previous steps was distorted, and so forth. This led to unreliable results (hallucinations) and, consequently, to a lack of trust in the technology.

Recent research has shown that LLMs are, in fact, quite good at reasoning and planning if the problem is broken into a series of steps as a result of the right prompts. This reasoning and planning greatly improves the accuracy of the LLM’s output.
Continue readingPEAS for Agent AI
A classic AI framework to define an agent’s task environment is PEAS. It stands for:
- Performance
- Environment
- Actuators
- Sensors
The R in RAG
In my previous post we looked at saving to the vector store. In this short post we’ll look at retrieving that information.
The simple search is a good starting point and depends on writing a good prompt, but we can do better.

- One problem in searching is that we often retrieve redundant data. For example, the basic search might retrieve ten very similar chunks. Maximal Marginal Relevance first builds a set of results that are relevant but also diverse. It then iterates through the relevant documents looking for ones that are as different as possible. As you might expect, this gives you a diverse set of relevant documents.
Deeper into RAG
In the previous post we walked through creating a RAG example, line by line. Let’s take a closer conceptual look at the steps involved in creating a RAG
- Load your source documents, being careful to keep the meta-data
- Split your document into semantically meaningful chunks
- Convert your text to vector representations in an embedding model
- Store your vector representations in a vector database
- Retrieve the data you need
RAG In Detail
In my previous post I walked through a RAG example but glossed over the details. In this post I’ll back up and walk through the program line by line.

The key steps in RAG are
- Load the data
- Split the text into smaller chunks to fit within context limits
- Create a Document object
- Embed the document in vectors that represent semantic meaning
- Store the document—typically in vector stores. These are databases designed to store embeddings and provide fast semantic retrieval
- Invoke a retriever to query the back end to return the most relevant Document object
- Create a prompt for the LLM
RAG – A Quick Example
In the previous blog post, we imported a few Python modules and configured our AI key, using Colab.
In this blog post we’ll use Retrieval-Augmented Generation (RAG) to extend an LLM that we’ll get from OpenAI. I’ll use a number of features from the libraries we imported with only a cursory explanation and will come back to them in upcoming blog posts to examine them in more depth. But I want to get to RAG right away because it is rapidly becoming central to AI and because it is cool.
LLMs are incredibly expensive to create and train, and it isn’t feasible to train them on everything. Besides that, much data is proprietary. It may be that you want an LLM that handles (to use the canonical case) your HR policies. Clearly no commercial LLM knows about those policies, nor should they. And equally clearly, you’re not going to train an LLM from scratch. What you want to do is to combine your own corpus of data (HR policy papers, etc.) with an existing LLM, and that is exactly what RAG is for.
In this simple example, we’re going to take a scene or two from Romeo and Juliet and feed it to gpt-40-mini; one of many LLMs available for use at minimal cost (we’ll get into how cost is computed in an upcoming post).
The first thing we’ll do after configuring the OPEN_API_KEY will be to get a TextLoader to import the text file with the scenes from Romeo and Juliet
Continue reading





































