Hello fam, i’ve been trying to create a custom deepagent using langgraph, yeah i created a custom react agent and wanted to extend the functionality into a deep agent , after creating the todo list planning tool, i could not add the extended deep agent state that used this todo tool in the custom react agent. Any one who can help please.
hi @AbasEkanem
thank for this question!
It is not easy to refer to this without any code snippets from you, but let me try
In LangGraph, the graph state is your source of truth—so you can:
- Define a richer TypedDict state (e.g.,
messages
+todos
). - Give the ReAct agent a planning tool (e.g.,
write_todos
). - Wrap the ReAct runnable in a node that only reads/writes
messages
. - Add a follow-up node that inspects the last
ToolMessage
and syncs the tool output into your extended state (todos
).
I’ve prepared this example:
import json
from typing import Annotated, List
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_core.messages import AnyMessage, ToolMessage, HumanMessage
from langchain_core.tools import tool
from langchain_core.runnables import RunnableConfig
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.prebuilt import create_react_agent
load_dotenv()
config: RunnableConfig = {"configurable": {"thread_id": "unique_id_1"}}
def get_llm():
return init_chat_model(
"claude-3-7-sonnet-latest",
model_provider="anthropic"
)
@tool("write_todos")
def write_todos(items: List[str]) -> dict:
"""Replace the current todo list. Return a JSON object: {"todos": [...]}."""
print(f"Writing todos: {items}")
return {"todos": items}
class DeepState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
todos: List[str]
def build_graph():
model = get_llm()
# Instruct the agent to plan using write_todos early, then proceed with normal ReAct
prompt = (
"You are a helpful agent. First, produce a concrete task plan by calling the "
"`write_todos` tool with a concise checklist. Then continue using tools to act."
)
react = create_react_agent(model=model, tools=[write_todos], prompt=prompt)
def react_node(state: DeepState, config: RunnableConfig):
print(f"React to {state['todos']}")
# Pass only messages to the ReAct runnable; it returns updated messages
result = react.invoke({"messages": state["messages"]}, config=config)
return {"messages": result["messages"]}
def sync_todos(state: DeepState):
# Find the most recent write_todos ToolMessage and merge into state
for msg in reversed(state.get("messages", [])):
if isinstance(msg, ToolMessage) and msg.name == "write_todos":
payload = msg.content
try:
data = json.loads(payload) if isinstance(payload, str) else payload
items = [str(x) for x in data.get("todos", [])]
print(f"Syncing todos: {items}")
return {"todos": items}
except Exception:
# Ignore malformed payloads; keep state unchanged
print(f"Error parsing payload: {payload}")
return {}
print(f"No `ToolMessage` found in messages: {state['messages']}")
return {}
# def sync_todos(state: DeepState):
# print(f"Sync to {state['todos']}")
# # If the last tool call was write_todos, merge it into the graph state
# if not state.get("messages"):
# print(f"Nothing to sync")
# return {}
# last = state["messages"][-2]
# if isinstance(last, ToolMessage) and last.name == "write_todos":
# payload = last.content
# try:
# data = json.loads(payload) if isinstance(payload, str) else payload
# items = [str(x) for x in data.get("todos", [])]
# print(f"Return {items}")
# return {"todos": items}
# except Exception:
# # Ignore malformed payloads; keep state unchanged
# print(f"Error parsing payload: {payload}")
# return {}
# print(f"Return empty: {last}")
# return {}
builder = StateGraph(DeepState)
builder.add_node("react", react_node)
builder.add_node("sync_todos", sync_todos)
builder.add_edge(START, "react")
builder.add_edge("react", "sync_todos")
builder.add_edge("sync_todos", END)
return builder.compile(checkpointer=InMemorySaver())
if __name__ == "__main__":
app = build_graph()
out = app.invoke(
{
"messages": [
HumanMessage(
"Plan the research steps as todos, then summarize findings on LangGraph."
)
],
"todos": [],
},
config
)
print("TODOS:", out.get("todos"))
print("LAST MESSAGE:", out.get("messages", [])[-1])
1 Like
thank you so much for this , this is helpful…
1 Like
your welcome @AbasEkanem
yeah also how do you host your ai applications freely apart from langgraph platform?
I don’t know much about free hosts. But you might want to explore Hugging Face Spaces.