LangGraph with SovereignEG
Goal: build a graph with one chatbot node, then upgrade it to a tool-using agent.
Time: 10 minutes.
LangGraph runs your LLM logic as a graph of nodes. The model itself is the same ChatOpenAI object from the LangChain guide.
Step 1 — Install
pip install langgraph langchain-openaiStep 2 — A one-node graph
Save as langgraph_hello.py:
import os
import time
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, MessagesState, START, END
llm = ChatOpenAI(
model="SovereignEG/Qwen3.8-27B-FP8",
base_url="https://backend.sovereigneg.com/v1",
api_key=os.environ["SOVEREIGNEG_API_KEY"],
)
def chatbot(state: MessagesState):
# The node receives the message list and returns new messages to append
return {"messages": [llm.invoke(state["messages"])]}
builder = StateGraph(MessagesState)
builder.add_node("chatbot", chatbot)
builder.add_edge(START, "chatbot")
builder.add_edge("chatbot", END)
graph = builder.compile()
start = time.time()
result = graph.invoke({"messages": [("user", "Hello, who are you?")]})
elapsed = time.time() - start
response = result["messages"][-1]
print(response.content)
print(f"\nTime: {elapsed:.2f}s")
print(f"Tokens: {response.usage_metadata}")python langgraph_hello.pyHow it works: START → chatbot → END. MessagesState is a built-in state that keeps a list of messages and appends whatever each node returns.
Step 3 — A tool-using agent (ReAct)
The model supports tool calling, so you can use LangGraph's prebuilt agent. It calls tools in a loop until it has a final answer.
import os
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
llm = ChatOpenAI(
model="SovereignEG/Qwen3.8-27B-FP8",
base_url="https://backend.sovereigneg.com/v1",
api_key=os.environ["SOVEREIGNEG_API_KEY"],
temperature=0,
)
@tool
def get_weather(city: str) -> str:
"""Return today's weather for a city."""
fake = {"Cairo": "34°C, sunny", "Alexandria": "29°C, windy"}
return fake.get(city, "unknown city")
@tool
def add(a: float, b: float) -> float:
"""Add two numbers."""
return a + b
agent = create_react_agent(llm, tools=[get_weather, add])
result = agent.invoke(
{"messages": [("user", "What is the weather in Cairo, and what is 17 + 25?")]}
)
print(result["messages"][-1].content)The model decides which tools to call, LangGraph runs them, feeds the results back, and the model writes the final answer.
You may see a warning that
create_react_agentmoved tolangchain.agents. It still works. If you have thelangchainpackage installed, the new form isfrom langchain.agents import create_agent(same arguments).
Step 4 — Memory across turns
Add a checkpointer and a thread_id so the agent remembers earlier messages:
from langgraph.checkpoint.memory import MemorySaver
agent = create_react_agent(llm, tools=[get_weather, add], checkpointer=MemorySaver())
config = {"configurable": {"thread_id": "user-1"}}
agent.invoke({"messages": [("user", "My name is Sara.")]}, config)
out = agent.invoke({"messages": [("user", "What is my name?")]}, config)
print(out["messages"][-1].content) # -> "Your name is Sara."Troubleshooting
| Problem | Fix |
|---|---|
| Agent never calls tools | Make sure temperature=0 and the tool has a clear docstring (the model reads it) |
KeyError: 'messages' | Every node must return {"messages": [...]} when using MessagesState |
| Loops forever | Add recursion_limit: agent.invoke(..., {"recursion_limit": 10}) |
Next: CrewAI