I have been experimenting with the prebuilt agents recently and tried to improve the efficiency of my RAG chatbot by making the retrieval part of tools that an LLM can use.
I guess the way I compiled the workflow, I have two starts and ends haha.
My second question revolves around why my input value from the graph view is always {}. Even when declaring my state as messages, it shows up like this which makes it hard for me to run evals.
You’re essentially building an Agentic RAG system, where the retrieval step is abstracted into tools the LLM can call. In this setup, the LLM acts as the agent and decides whether, when, and how to retrieve external information. This is a valid and increasingly popular approach, especially in cases where retrieval isn’t always necessary or when multiple queries might improve the result quality.
However, it’s not the only way to implement RAG. Other strategies include:
Single-step retrieval, where retrieval is performed before the LLM sees any context and the results are injected directly into the prompt.
Orchestrated pipelines, where retrieval and generation are clearly separated stages in a workflow.
On “Best Practice”
“Best” depends on what efficiency means in your context. Are you optimizing for:
Latency (response time)?
Cost (number of tool calls)?
Accuracy or quality of the final response?
Simplicity or maintainability of your architecture?
For instance, Agentic RAG can support additional reasoning like validating retrieved content or retrying bad results, but it introduces complexity and potential cost. If you’re aiming for predictable cost and performance, a simpler, non-agentic RAG might suit better.
@JarredR092699 for your question regarding why the input value in LangGraph Studio always shows {}, someone asked a similar question in the Slack community and I answered it here (question #3). In short, the first node should accept a BaseMessage or some other type that can accept string as the input.
from langchain_core.messages import BaseMessage
from langgraph.graph.messages import add_messages
class MessagesState(TypedDict):
messages: Annotated[list[BaseMessage], add_messages]
Messages should be a list of messages
You will likely want to specify the add_messages reducer
Studio is likely interpreting BaseMessage as an object and giving you an option of filling it in as a dict {}