I was recently debugging a support bot built with LangGraph, where the agent would consistently forget the context of the conversation after a few turns. The bot would ask the user to repeat information they had already provided, leading to a frustrating experience. Upon closer inspection, I realized that the issue stemmed from the fact that the agent's knowledge graph was not being properly updated and retrieved across multiple tool calls. The agent was essentially starting from scratch every time it received a new input, which made it impossible to maintain a coherent conversation.
This is where MCP's Resource primitive comes into play. The Resource primitive allows us to define a knowledge graph that can be efficiently updated and retrieved across multiple tool calls and conversation turns. By using the Resource primitive, we can create a centralized store of information that the agent can draw upon to inform its decisions and actions.
To illustrate this, let's consider an example where we're building a support bot that helps users troubleshoot issues with their devices. We can define a Resource that represents the user's device information, which includes details such as the device type, operating system, and any error messages they've encountered. We can then use this Resource to inform the agent's responses and actions, such as providing troubleshooting steps or escalating the issue to a human support agent.
Here's an example of how we might implement this using MCP's Resource primitive and LangGraph:
import langgraph
from mcp import Resource
device_info_resource = Resource(
name="device_info",
attributes=[
{"name": "device_type", "type": "string"},
{"name": "operating_system", "type": "string"},
{"name": "error_messages", "type": "list<string>"}
]
)
agent = langgraph.Agent()
device_info_node = agent.add_node(
name="get_device_info",
func=lambda: device_info_resource.get()
)
update_device_info_node = agent.add_node(
name="update_device_info",
func=lambda device_type, operating_system, error_messages: device_info_resource.update(
device_type=device_type,
operating_system=operating_system,
error_messages=error_messages
)
)
agent.add_conditional_edges(
from_node=device_info_node,
to_node=update_device_info_node,
condition=lambda device_info: device_info is None
)
agent.run()
In this example, we define a Resource called device_info
that represents the user's device information. We then create a LangGraph agent that uses this Resource to inform its decisions and actions. The agent has two nodes: one that retrieves the device information Resource, and another that updates the Resource. The agent uses a conditional edge to determine which node to execute based on the current state of the Resource.
One practical gotcha to watch out for when using MCP's Resource primitive is that it can be easy to over-engineer the Resource, leading to a complex and brittle knowledge graph. It's essential to strike a balance between providing enough information to inform the agent's decisions and actions, and avoiding unnecessary complexity.
As we continue to build more sophisticated agentic AI systems, we'll need to explore new ways to manage complexity and ensure that our agents are able to effectively retrieve and update information across multiple tool calls and conversation turns. Tomorrow, we'll dive deeper into the challenges of scaling LangGraph agents to handle increasingly complex tasks and scenarios.