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
ToolMessageand 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.