Merge branch 'main' into v1

This commit is contained in:
Sydney Runkle
2025-07-16 18:32:07 -04:00
37 changed files with 1023 additions and 546 deletions
+41 -14
View File
@@ -55,14 +55,16 @@ The `langchain-mcp-adapters` package enables agents to use tools defined across
=== "In a workflow"
```python
```python title="Workflow using MCP tools with ToolNode"
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.graph import StateGraph, MessagesState, START
from langgraph.prebuilt import ToolNode, tools_condition
from langchain.chat_models import init_chat_model
model = init_chat_model("openai:gpt-4.1")
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.prebuilt import ToolNode
# Initialize the model
model = init_chat_model("anthropic:claude-3-5-sonnet-latest")
# Set up MCP client
client = MultiServerMCPClient(
{
"math": {
@@ -80,22 +82,47 @@ The `langchain-mcp-adapters` package enables agents to use tools defined across
)
tools = await client.get_tools()
def call_model(state: MessagesState):
response = model.bind_tools(tools).invoke(state["messages"])
return {"messages": response}
# Bind tools to model
model_with_tools = model.bind_tools(tools)
# Create ToolNode
tool_node = ToolNode(tools)
def should_continue(state: MessagesState):
messages = state["messages"]
last_message = messages[-1]
if last_message.tool_calls:
return "tools"
return END
# Define call_model function
async def call_model(state: MessagesState):
messages = state["messages"]
response = await model_with_tools.ainvoke(messages)
return {"messages": [response]}
# Build the graph
builder = StateGraph(MessagesState)
builder.add_node(call_model)
builder.add_node(ToolNode(tools))
builder.add_node("call_model", call_model)
builder.add_node("tools", tool_node)
builder.add_edge(START, "call_model")
builder.add_conditional_edges(
"call_model",
tools_condition,
should_continue,
)
builder.add_edge("tools", "call_model")
# Compile the graph
graph = builder.compile()
math_response = await graph.ainvoke({"messages": "what's (3 + 5) x 12?"})
weather_response = await graph.ainvoke({"messages": "what is the weather in nyc?"})
# Test the graph
math_response = await graph.ainvoke(
{"messages": [{"role": "user", "content": "what's (3 + 5) x 12?"}]}
)
weather_response = await graph.ainvoke(
{"messages": [{"role": "user", "content": "what is the weather in nyc?"}]}
)
```
@@ -148,4 +175,4 @@ if __name__ == "__main__":
- [MCP documentation](https://modelcontextprotocol.io/introduction)
- [MCP Transport documentation](https://modelcontextprotocol.io/docs/concepts/transports)
- [langchain_mcp_adapters](https://github.com/langchain-ai/langchain-mcp-adapters)
- [langchain_mcp_adapters](https://github.com/langchain-ai/langchain-mcp-adapters)
@@ -4,6 +4,28 @@
---
## v0.2.93 (2025-07-16)
- Removed the GIN index for run metadata to improve performance.
## v0.2.92 (2025-07-16)
- Enabled copying functionality for blobs and checkpoints, improving data management flexibility.
## v0.2.91 (2025-07-16)
- Reduced writes to the `checkpoint_blobs` table by inlining small values (null, numeric, str, etc.). This means we don't need to store extra values for channels that haven't been updated.
## v0.2.90 (2025-07-16)
- Improve checkpoint writes via node-local background queueing.
## v0.2.89 (2025-07-15)
- Decoupled checkpoint writing from thread/run state by removing foreign keys and updated logger to prevent timeout-related failures.
## v0.2.88 (2025-07-14)
- Removed the foreign key constraint for `thread` in the `run` table to simplify database schema.
## v0.2.87 (2025-07-14)
- Added more detailed logs for Redis worker signaling to improve debugging.
## v0.2.86 (2025-07-11)
- Honored tool descriptions in the `/mcp` endpoint to align with expected functionality.
+1 -1
View File
@@ -298,7 +298,7 @@ print(graph.invoke({"x": 5}, stream_mode='updates')) # (2)!
[{'expensive_node': {'result': 10}, '__metadata__': {'cached': True}}]
```
1. First run takes the full second to run (due to mocked expensive computation).
1. First run takes two seconds to run (due to mocked expensive computation).
2. Second run utilizes cache and returns quickly.
## Edges
+43 -14
View File
@@ -31,12 +31,12 @@ To leverage custom authentication and access user-level metadata in your deploym
api_key = headers.get("x-api-key")
if not api_key or not is_valid_key(api_key):
raise Auth.exceptions.HTTPException(status_code=401, detail="Invalid API key")
# Fetch user-specific tokens from your secret store
# Fetch user-specific tokens from your secret store
user_tokens = await fetch_user_tokens(api_key)
return { # (2)!
"identity": api_key, # fetch user ID from LangSmith
"identity": api_key, # fetch user ID from LangSmith
"github_token" : user_tokens.github_token
"jira_token" : user_tokens.jira_token
# ... custom fields/secrets here
@@ -50,14 +50,14 @@ To leverage custom authentication and access user-level metadata in your deploym
```json hl_lines="7-9"
{
"dependencies": ["."],
"graphs": {
"dependencies": ["."],
"graphs": {
"agent": "./agent.py:graph"
},
"env": ".env",
"auth": {
},
"env": ".env",
"auth": {
"path": "./auth.py:my_auth"
}
}
}
```
@@ -80,7 +80,7 @@ To leverage custom authentication and access user-level metadata in your deploym
```python
from langgraph.pregel.remote import RemoteGraph
my_token = "your-token" # In practice, you would generate a signed token with your auth provider
remote_graph = RemoteGraph(
"agent",
@@ -133,15 +133,44 @@ To allow an agent to perform authenticated actions on behalf of the user, access
def my_node(state, config):
user_config = config["configurable"].get("langgraph_auth_user")
# token was resolved during the @auth.authenticate function
token = user_config.get("github_token","")
token = user_config.get("github_token","")
...
```
!!! note
Fetch user credentials from a secure secret store. Storing secrets in graph state is not recommended.
### Authorizing a Studio user
By default, if you add custom authorization on your resources, this will also apply to interactions made from the Studio. If you want, you can handle logged-in Studio users differently by checking [is_studio_user()](../../reference/functions/sdk_auth.isStudioUser.html).
!!! note
`is_studio_user` was added in version 0.1.73 of the langgraph-sdk. If you're on an older version, you can still check whether `isinstance(ctx.user, StudioUser)`.
```python
from langgraph_sdk.auth import is_studio_user, Auth
auth = Auth()
# ... Setup authenticate, etc.
@auth.on
async def add_owner(
ctx: Auth.types.AuthContext,
value: dict # The payload being sent to this access method
) -> dict: # Returns a filter dict that restricts access to resources
if is_studio_user(ctx.user):
return {}
filters = {"owner": ctx.user.identity}
metadata = value.setdefault("metadata", {})
metadata.update(filters)
return filters
```
Only use this if you want to permit developer access to a graph deployed on the managed LangGraph Platform SaaS.
## Learn more
* [Authentication & Access Control](../../concepts/auth.md)
* [LangGraph Platform](../../concepts/langgraph_platform.md)
* [Setting up custom authentication tutorial](../../tutorials/auth/getting_started.md)
- [Authentication & Access Control](../../concepts/auth.md)
- [LangGraph Platform](../../concepts/langgraph_platform.md)
- [Setting up custom authentication tutorial](../../tutorials/auth/getting_started.md)
+2 -2
View File
@@ -1194,7 +1194,7 @@ from IPython.display import Image, display
display(Image(graph.get_graph().draw_mermaid_png()))
```
![Map-reduce graph with fanout](assets/graph_api_image_2.png)
![Map-reduce graph with fanout](assets/graph_api_image_6.png)
```python
# Call the graph: here we call it to generate a list of jokes
@@ -1446,7 +1446,7 @@ Recursion Error
display(Image(graph.get_graph().draw_mermaid_png()))
```
![Complex loop graph with branches](assets/graph_api_image_4.png)
![Complex loop graph with branches](assets/graph_api_image_8.png)
This graph looks complex, but can be conceptualized as loop of [supersteps](../concepts/low_level.md#graphs):
+21
View File
@@ -0,0 +1,21 @@
# Observability
Use [LangSmith](https://smith.langchain.com/) to visualize the execution of a LangGraph application and do the following:
- [Enable tracing for your application](#enable-tracing-for-your-application).
- [Debug a locally running application](../cloud/how-tos/clone_traces_studio.md).
- [Evaluate the application performance](../agents/evals.md).
- [Monitor the application](https://docs.smith.langchain.com/observability/how_to_guides/dashboards).
To get started, sign up for a free account at [LangSmith](https://smith.langchain.com/).
## Enable tracing for your application
To use LangSmith with your LangGraph application, enable tracing:
```python
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<your-api-key>
```
For more information, see [Trace with LangGraph](https://docs.smith.langchain.com/observability/how_to_guides/trace_with_langgraph).