41 Comments
User's avatar
Bobby Montalvo's avatar

I'm trying to follow along with this tutorial but the formatting is off and python is picky about formatting. I've read your comment about "full code can be found in my repo" but it's not obvious where in the repo this code is. Care to provide a link to the .py file for this tutorial please?

Pedro Marques's avatar

Copy all tutorial send to deepseek and ask for the code all togheter :)

David Stark's avatar

Yes, same problem. It looks like the formatting was off.

Nir Diamant's avatar

what is the problem?

David Stark's avatar

The State class that uses a TypedDict at the beginning. The formatting is all off. It had me questioning if there was a novel Python syntax I had not heard of.

class State(TypedDict): text:

str classification:

str entities: List[str] summary: str

On a positive note, it's good motivation to read up on Python's TypedDict feature from the typing package.

Tingwen Zhang's avatar

Here is the corrected syntax:

class State(TypedDict):

text: str

classification: str

entities: List[str]

summary: str

The syntax

variable: type

is required for a TypedDict object.

Rahul Pandey's avatar

My understanding of Agent is that it should be able to handle some complexity which may arise at run time. How is the above designed system different from a simple program which uses LLM to answer some questions? but in the overall flow the so called agent is a linear program flow. If you can elaborate that part

Nir Diamant's avatar

Thank for you comment! Please refer to other comments on this blog post, as I answered this question :)

Yatn Bangad's avatar

Hi Nir, I'm unable to get an answer to this question from the other comments. I understand you have intentionally demo'd a simple flow but this can very well be done with prompts to an LLM. Can you describe a more complex use case for agents?

Further, I notice that the output generated by the classification and entity extraction nodes are not being used in the summarization node. Can you you please explain what is the use of having these if this is the case? If not, can you explain how the output from those is being used in the summarization node?

Jan Andrew Bloxham's avatar

May I recommend reading Gary Marcus’ substack for a different pov.

PapayaNews's avatar

Love how you framed this as 'simpler' not 'simple.' The strategic move here isn't just building agents—it's democratizing who can build them. Every marketer, PM, and analyst who learns this shifts from AI consumer to AI composer. That's the real disruption. Subscribed

Nir Diamant's avatar

Love your comment. Thanks 😊

Ruben Hassid's avatar

As easy as it can be.

Nir Diamant's avatar

Next time will try to make it even easier :)

Hrju Blja's avatar

Thanks for sharing this, I managed to successfully run the whole code and get the intended output.

That being said, I am struggling to see how this code (putting aside the usage of the LangGraph framework) is different from the old good hard coded and predictable series of functions calls, when an output of a function A serves as an input of a function B. What specifically is "agentic" in this code? How this agent "can dynamically adjust its focus based on what it discovers"?

Bar's avatar

How does the summarization considering the information from the previous steps (classification and entities) if it only uses state["text"] and not state["classification"] or state["entities"].

It seems that summarization logic doesn’t use the classification or entity extraction output. Please correct me if I wrong...

potentialMind's avatar

This is not an agent but a workflow.

Nir Diamant's avatar

This is a minimal version of a controllable agent

ThePizzaMaster's avatar

Me, I feel like this needs a stronger use case. It's not clear how AI chaining did something that a series of well-reasoned prompts couldn't.

Nir Diamant's avatar

Thanks for your input, Dave.

The use case in this blog post is intentionally simple, as its goal is to provide an introduction and help readers understand what agents are and how to create one.

yonlehman's avatar

As others have said, I'm uncomfortable with inventing a "new" method "ai agents" for what is good old programming that uses an ai based text processesing function. Using a, state machine abstraction is also as old computer science, in the 80 there was an attempt to have a graphical state machine engine (David Harel StateCharts) I don't think it ever became mainstream since state machines are useful for small examples. Once you have many states and many edges, especially when you introduce error handling potentially on every node, good old programming with sequencing loops and conditions is still the most straightforward and readable way to represent what you want the software to do. My main concern with you simplified example is that people not trained in software engineering will think that ai makes everything simple, anyone can vibe program without bothering to learn how to do it reliably and safely.

ManjP's avatar

Like other readers commented, it is hard to see the power of agents from this example, I understand this was intentionally simplified. Might help to link to a blog post that shows the real power, the autonomous ability to decide based on context. If the agent gets non-English input, could it translate and then summarize?

Nir Diamant's avatar

You can see many more tutorials on my GitHub. both explanations + code:

https://github.com/NirDiamant/GenAI_Agents

Claudia Ng's avatar

The example code looks like it could be a workflow. How do you decide whether to implement it as an agent or a workflow?

Nir Diamant's avatar

An agent can be a workflow where each step uses an LLM for a specific complicated task. This way, we have much more control over the agent.

Zachary Huang's avatar

Like your tutorial and have subscribed to your newsletter! I'm new to medium. Can I get you quick feedback on an even simpler agent https://the-pocket.github.io/PocketFlow/design_pattern/agent.html, built on an 100-line framework

I made https://substack.com/home/post/p-158349453

Ravi Teja Lanka's avatar

Hello Nir, thanks for the excellent blog post, I would like to have few inputs from you, especially with the way we use the word AI Agents, In the example you have shown as part of blog is more of an AI system which is a workflow, according to the blog from Anthropic "Building Effective Agents", an AI Agent is one which takes decisions autonomously. It would be helpful if you can write a blog on building a true AI agent, and how to distinguish when to use AI workflow and when to use an AI Agent

Nir Diamant's avatar

Thanks for your input, Ravi.

The use case in this blog post is intentionally simple, as its goal is to provide an introduction and help readers understand what agents are and how to create one.

xiongzhenglong's avatar

AttributeError Traceback (most recent call last)

in <cell line: 0>()

5

6 state_input = {"text": sample_text}

----> 7 result = app.invoke(state_input)

8

9 print("Classification:", result["classification"])

6 frames

in classification_node(state)

6 )

7 message = HumanMessage(content=prompt.format(text=state["text"]))

----> 8 classification = llm.invoke([message]).content.strip()

9 return {"classification": classification}

10

AttributeError: 'tuple' object has no attribute 'invoke'

Could anyone help identify why this is happening? Thanks!

Nir Diamant's avatar

I answered the open issue on the repo.

Nir Diamant's avatar

I saw that you opened an issue on the repo. I'll take care of it (or someone else will) soon.

Thanks! 🙂

Alain Airom's avatar

It seems that the app should be changed to; import os

from typing import TypedDict, List

from langgraph.graph import StateGraph, END

from langchain.prompts import PromptTemplate

from langchain_openai import ChatOpenAI

from langchain.schema import HumanMessage

class State(TypedDict):

text: str

classification: str

entities: List[str]

summary: str

llm = ChatOpenAI(model="gpt-4-0613", temperature=0)

def classification_node(state: State):

prompt = PromptTemplate(

input_variables=["text"],

template="Classify the following text into one of the categories: News, Blog, Research, or Other.\n\nText:{text}\n\nCategory:"

)

message = HumanMessage(content=prompt.format(text=state["text"]))

classification = llm.invoke([message]).content.strip()

return {"classification": classification, **state}

def entity_extraction_node(state: State):

prompt = PromptTemplate(

input_variables=["text"],

template="Extract all the entities (Person, Organization, Location) from the following text. Provide the result as a comma-separated list.\n\nText:{text}\n\nEntities:"

)

message = HumanMessage(content=prompt.format(text=state["text"]))

entities_str = llm.invoke([message]).content.strip()

entities = [e.strip() for e in entities_str.split(",")] if entities_str else []

return {"entities": entities, **state}

def summarization_node(state: State):

prompt = PromptTemplate(

input_variables=["text"],

template="Summarize the following text in one short sentence.\n\nText:{text}\n\nSummary:"

)

message = HumanMessage(content=prompt.format(text=state["text"]))

summary = llm.invoke([message]).content.strip()

return {"summary": summary, **state}

workflow = StateGraph(State)

# Add nodes to the graph

workflow.add_node("classification_node", classification_node)

workflow.add_node("entity_extraction", entity_extraction_node)

workflow.add_node("summarization", summarization_node)

# Add edges to the graph

workflow.set_entry_point("classification_node")

workflow.add_edge("classification_node", "entity_extraction")

workflow.add_edge("entity_extraction", "summarization")

workflow.add_edge("summarization", END)

# Compile the graph

app = workflow.compile() # This line is crucial

sample_text = """

OpenAI has announced the GPT-4 model, which is a large multimodal model that exhibits human-level performance on various professional benchmarks. It is developed to improve the alignment and safety of AI systems.

additionally, the model is designed to be more efficient and scalable than its predecessor, GPT-3. The GPT-4 model is expected to be released in the coming months and will be available to the public for research and development purposes.

"""

state_input = {"text": sample_text, "classification": "", "entities": [], "summary": ""}

result = app.invoke(state_input)

print("Classification:", result["classification"])

print("\nEntities:", result["entities"])

print("\nSummary:", result["summary"])

But at the end no access to gpt-4-0613

Nir Diamant's avatar

the full code can be found in my repo and it works (I tested it yesterday).

if you choose to work with openAI you'll need to configure a private key on their website first. but you can use any llm that you want.

Alain Airom's avatar

And where is your repo please?

Alain Airom's avatar

Found the repo, I'll check, thx