Skip to content

LangSmith Studio

前置阅读:Agent 实战指南 · 中间件概览

本节解决什么问题

create_agent 返回的是一个 LangGraph CompiledStateGraph--它内部有模型节点、工具节点和循环边。当 Agent 行为不符合预期时,仅靠 print 调试消息列表很难定位问题出在模型推理、工具参数还是中间件拦截。LangSmith Studio 提供了一个可视化界面,让你看到图的拓扑结构、每一步的 state 快照、工具调用的入参出参,以及中间件对消息的修改。

核心概念

必须深刻理解,不能跳过:create_agent 的返回值就是一个 LangGraph 图。

create_agent(model, tools, system_prompt=..., middleware=...) 返回 CompiledStateGraph。这意味着:

  • 它有节点(model node、tools node)和边(模型→工具→模型的循环)。
  • 它的执行状态是 {"messages": [...]},每一步都会向 messages 追加消息。
  • LangSmith Studio 可视化的就是这个图--Studio 不是 LangChain 独有的调试器,它是 LangGraph 的通用可视化工具。
  • 中间件(middleware)会注入额外的节点或修改 state,在 Studio 的图拓扑中可以看到这些变化。

前端类比

LangSmith Studio 之于 Agent,类似于 React DevTools 之于 React 应用。React DevTools 让你检查组件树(component tree)、查看 props/state 变化、定位渲染性能瓶颈;Studio 让你检查 Agent 的图拓扑(graph topology)、查看 messages state 变化、定位工具调用和中间件的行为差异。两者的核心理念相同:让不可见的执行过程变得可视化、可回溯

原生语义:Studio 连接到一个运行中的 LangGraph 服务器(本地 langgraph dev 或远程 Agent Server),通过 LangGraph 的 introspection API 读取图结构和运行状态。它不是一个独立的运行时,而是一个观察和控制层--你在 Studio 中看到的执行,就是 agent.invoke() 的真实执行过程。

当前推荐写法:langgraph dev + langgraph.json

安装 CLI

bash
# 使用 uv(推荐)
uv pip install "langgraph-cli[inmem]"

# 或使用 pip
pip install "langgraph-cli[inmem]"

[inmem] extra 安装内存模式的依赖,适合本地开发调试。生产部署使用 langgraph uplanggraph build(见 部署)。

项目结构

my-agent/
├── app.py              # Agent 定义
├── langgraph.json      # Studio 配置
├── pyproject.toml      # 依赖声明
└── .env                # 环境变量(API Key 等)

langgraph.json 配置

json
{
  "graphs": {
    "enviro_agent": "./app:agent"
  },
  "dependencies": ["."],
  "env": ".env"
}
  • graphs:键是图名称(在 Studio 中显示),值是 模块路径:变量名
  • dependencies:项目依赖目录列表(含 pyproject.toml 的目录)。
  • env:环境变量文件路径。

最小可运行示例

python
# app.py
import os

from langchain.agents import create_agent
from langchain.agents.middleware import PIIMiddleware
from langchain.chat_models import init_chat_model
from langchain.tools import tool


@tool
def lookup_factor(keyword: str) -> str:
    """根据关键词查询环保因子信息。

    Args:
        keyword: 因子名称或别名(如 COD、二氧化硫)
    """
    # EnviroNexus 知识库的确定性实体匹配示例
    factors = {
        "COD": {"unit": "mg/L", "standard": "GB 11914-89"},
        "二氧化硫": {"unit": "mg/m³", "standard": "HJ 482-2009"},
    }
    result = factors.get(keyword)
    return str(result) if result else f"未找到因子: {keyword}"


# 模型配置使用环境变量,不写死具体版本
model = init_chat_model(os.environ["LLM_MODEL"])

agent = create_agent(
    model=model,
    tools=[lookup_factor],
    system_prompt=(
        "你是 EnviroNexus 环保知识库助手。"
        "用户询问环保因子时,使用 lookup_factor 工具查询。"
        "回答中必须包含标准号和单位。"
    ),
    middleware=[
        PIIMiddleware("email", strategy="redact"),
    ],
)

启动 Studio

bash
langgraph dev

启动后终端会输出类似:

Started server on http://127.0.0.1:2024
Opening Studio at https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024

在浏览器中打开 Studio 链接,即可看到 enviro_agent 图的可视化界面。

Studio 核心能力

能力描述
图拓扑可视化展示 create_agent 生成的节点和边(model node、tools node、middleware 注入的节点)
交互式运行在 Playground 中输入消息,实时查看 Agent 执行过程
State 快照每一步执行后的完整 {"messages": [...]} 状态
工具调用检查查看工具名称、入参 JSON、返回值和延迟
中间件行为观察中间件如何修改消息(如 PII 脱敏、摘要压缩)
时间旅行回溯到历史 checkpoint,从任意节点重新执行(fork)
运行对比并排比较不同输入或不同配置的运行结果

可视化 create_agent 的图结构

create_agent 生成的图在 Studio 中呈现为以下拓扑:

当添加中间件后,Studio 会显示中间件注入的额外节点。例如 PIIMiddleware 会在模型调用前后增加 PII 处理步骤,SummarizationMiddleware 会在消息数量超过阈值时触发摘要节点。

查看 State 和 Messages

在 Studio 的 Playground 中运行 Agent 后,右侧面板显示每一步的 state 快照:

Step 1 - agent (model node)
  messages:
    [0] HumanMessage: "查询 COD 的标准号"
    [1] AIMessage (tool_calls):
        - lookup_factor(keyword="COD")

Step 2 - tools (tool node)
  messages:
    [0] HumanMessage: "查询 COD 的标准号"
    [1] AIMessage (tool_calls): lookup_factor(keyword="COD")
    [2] ToolMessage: "{'unit': 'mg/L', 'standard': 'GB 11914-89'}"

Step 3 - agent (model node)
  messages:
    ...
    [3] AIMessage: "COD 的检测标准是 GB 11914-89,单位为 mg/L。"

每个消息对象可以展开查看完整属性:contenttool_callsusage(token 用量)、response_metadata 等。

调试中间件

中间件是 create_agent 最难调试的部分--它们在模型调用前后修改 state,但 print 只能看到最终结果。Studio 让你看到中间件在每个步骤的行为。

示例:调试 PII 脱敏

python
import os

from langchain.agents import create_agent
from langchain.agents.middleware import PIIMiddleware
from langchain.chat_models import init_chat_model

agent = create_agent(
    model=init_chat_model(os.environ["LLM_MODEL"]),
    tools=[],
    system_prompt="你是客服助手,回答用户问题。",
    middleware=[
        PIIMiddleware("email", strategy="redact"),
        PIIMiddleware("phone", strategy="mask"),
    ],
)

result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "我的邮箱是 alice@example.com,电话是 13800138000,帮我修改密码。",
    }],
})

for msg in result["messages"]:
    print(f"[{type(msg).__name__}] {msg.content}")

在 Studio 中运行这段代码,你可以看到:

  1. before_model 阶段:PIIMiddleware 将输入消息中的 alice@example.com 替换为 [REDACTED_EMAIL]13800138000 替换为 138****8000
  2. 模型调用:模型收到的是脱敏后的消息,不会看到真实邮箱和电话。
  3. after_model 阶段:模型输出不包含 PII(因为输入已脱敏)。

示例:调试 SummarizationMiddleware

python
from langchain.agents.middleware import SummarizationMiddleware

agent = create_agent(
    model=init_chat_model(os.environ["LLM_MODEL"]),
    tools=[lookup_factor],
    system_prompt="你是环保知识库助手。",
    middleware=[
        SummarizationMiddleware(
            model=init_chat_model(os.environ["LLM_MODEL"]),
            trigger=("messages", 6),  # 消息数超过 6 条时触发摘要
            keep=("messages", 2),     # 保留最近 2 条消息
        ),
    ],
)

在 Studio 中持续对话直到消息超过 6 条,你可以看到摘要节点被触发,旧消息被压缩为一条 SystemMessage 摘要。

使用 @traceable 追踪自定义函数

除了 Agent 内部的自动追踪,你可以在自定义函数上使用 @traceable 装饰器,让它们在 Studio 和 LangSmith Trace 中可见:

python
from langsmith import traceable


@traceable(name="enrich_query")
def enrich_query(query: str) -> str:
    """对用户查询做预处理(如同义词扩展)。"""
    synonyms = {"化学需氧量": "COD", "SO2": "二氧化硫"}
    for full, abbr in synonyms.items():
        query = query.replace(full, abbr)
    return query


@traceable(name="build_response")
def build_response(factor_info: str) -> dict:
    """将因子信息组装为结构化响应。"""
    return {"factor": factor_info, "source": "EnviroNexus"}


# 调用 Agent 时,这些函数会作为子节点出现在 Trace 中
user_query = "查询化学需氧量的标准号"
enriched = enrich_query(user_query)
result = agent.invoke({"messages": [{"role": "user", "content": enriched}]})

在 Studio 的 Trace 视图中,enrich_querybuild_response 会作为嵌套节点显示,帮助你定位预处理或后处理逻辑中的问题。

实战:调试一个工具调用失败的 Agent

问题场景

Agent 在查询环保因子时返回了错误的因子信息:

python
import os

from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.tools import tool


@tool
def lookup_factor(keyword: str) -> str:
    """根据关键词查询环保因子信息。

    Args:
        keyword: 因子名称或别名
    """
    factors = {
        "COD": {"unit": "mg/L", "standard": "GB 11914-89"},
        "二氧化硫": {"unit": "mg/m³", "standard": "HJ 482-2009"},
    }
    result = factors.get(keyword)
    return str(result) if result else f"未找到因子: {keyword}"


agent = create_agent(
    model=init_chat_model(os.environ["LLM_MODEL"]),
    tools=[lookup_factor],
    system_prompt="你是环保知识库助手。用户询问因子时使用 lookup_factor 工具。",
)

# 用户输入"化学需氧量",但工具只接受"COD"
result = agent.invoke({
    "messages": [{"role": "user", "content": "查询化学需氧量的标准号"}],
})
print(result["messages"][-1].content)
# 输出可能包含"未找到因子: 化学需氧量"

在 Studio 中调试

  1. 启动 Studiolanggraph dev,在浏览器中打开 Studio。
  2. 运行 Agent:在 Playground 中输入"查询化学需氧量的标准号"。
  3. 查看工具调用:展开 Step 1 的 AIMessage,发现 tool_callskeyword="化学需氧量"
  4. 查看工具返回:展开 Step 2 的 ToolMessage,内容是 "未找到因子: 化学需氧量"
  5. 定位根因:工具的 factors 字典只支持缩写"COD",不支持中文全称"化学需氧量"。

修复方案

在工具中加入别名映射:

python
@tool
def lookup_factor(keyword: str) -> str:
    """根据关键词查询环保因子信息。

    Args:
        keyword: 因子名称或别名(如 COD、化学需氧量、二氧化硫、SO2)
    """
    # 别名到标准名的映射
    alias_map = {
        "化学需氧量": "COD",
        "SO2": "二氧化硫",
    }
    normalized = alias_map.get(keyword, keyword)

    factors = {
        "COD": {"unit": "mg/L", "standard": "GB 11914-89"},
        "二氧化硫": {"unit": "mg/m³", "standard": "HJ 482-2009"},
    }
    result = factors.get(normalized)
    return str(result) if result else f"未找到因子: {keyword}"

修复后在 Studio 中重新运行,确认工具返回了正确的因子信息。

时间旅行与状态回溯

Studio 支持 LangGraph 的 time travel 能力。每次运行 Agent 时,如果配置了 Checkpointer,每一步都会生成一个 checkpoint。在 Studio 中你可以:

  1. 回溯:点击任意历史 checkpoint,查看该步的完整 state。
  2. Fork:从某个 checkpoint 创建一个副本,修改输入后重新执行。
  3. 重放:使用相同的输入重新运行,对比行为差异。
python
from langgraph.checkpoint.memory import InMemorySaver

agent = create_agent(
    model=init_chat_model(os.environ["LLM_MODEL"]),
    tools=[lookup_factor],
    system_prompt="你是环保知识库助手。",
    checkpointer=InMemorySaver(),  # 启用 checkpoint 后 Studio 才能时间旅行
)

config = {"configurable": {"thread_id": "debug-session-1"}}
result = agent.invoke(
    {"messages": [{"role": "user", "content": "查询 COD 标准"}]},
    config=config,
)

TIP

本地开发时使用 InMemorySaver 即可。生产环境使用 PostgresSaver 或 Agent Server 的自动持久化。详见 短期记忆部署

常见错误与旧版 API 对照

旧版(仅用于读旧项目,新项目不得采用)

LangChain 0.x 时代使用 create_tool_calling_agent + AgentExecutor + LangServe Playground 做可视化调试。以下代码在 LangChain 1.0 中 无法运行ImportError):

python
# ❌ 0.x 写法 -- 1.0 已删除,仅用于理解旧项目
from langchain.agents import create_tool_calling_agent, AgentExecutor  # ImportError
from langchain.prompts import ChatPromptTemplate
from langserve import add_routes  # LangServe 2024-11 弃用

prompt = ChatPromptTemplate.from_messages([
    ("system", "..."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),  # 0.x 专属占位符
])
agent = create_tool_calling_agent(llm, tools, prompt)  # 已删除
executor = AgentExecutor(agent=agent, tools=tools)      # 已删除
add_routes(app, executor, path="/agent")                # LangServe 弃用

迁移方式:改用 create_agent + langgraph dev + LangSmith Studio。create_agent 不需要 ChatPromptTemplateagent_scratchpad,系统提示词通过 system_prompt= 参数传入。

常见问题排查

问题原因解决方案
langgraph devModuleNotFoundErrorlanggraph.json 中的模块路径不对确认 ./app:agent 对应 app.py 中的 agent 变量
Studio 中看不到图langgraph.jsongraphs 字段为空添加 "graphs": {"name": "./module:var"}
Studio 连接失败本地服务器未启动或端口被占用检查 langgraph dev 是否在运行,默认端口 2024
中间件行为不可见中间件未正确添加到 middleware= 列表确认中间件实例传入 create_agent(middleware=[...])
时间旅行不可用未配置 Checkpointer添加 checkpointer=InMemorySaver()

适用与不适用场景

适用

  • 开发阶段调试 Agent 的工具调用链路
  • 验证中间件(PII 脱敏、摘要压缩、HITL 中断)的行为
  • 对比不同 system_prompt 或不同模型对同一输入的行为差异
  • 回溯历史运行,定位偶发性错误
  • 向非技术人员展示 Agent 的决策过程

不适用

  • 生产环境监控(使用 可观测性 和 LangSmith Trace)
  • 自动化回归测试(使用 测试
  • 性能基准测试(Studio 有额外 introspection 开销,不代表生产性能)
  • 需要 CI/CD 集成的场景(使用 pytest + LangSmith Evaluation)

层级边界

LangSmith Studio 调试的是 LangGraph 图。create_agent 产生的图相对简单(model + tools 循环),如果需要更复杂的图拓扑(条件分支、并行节点、子图),应直接使用 LangGraph 的 StateGraph API,详见 LangGraph 入门。如果你在构建长周期研究、多文件多 Subagent 的高级 Agent,Studio 同样可以调试 Deep Agents 产生的图,详见 Deep Agents 生态定位

下一步

  • 阅读 测试 掌握 Agent 的自动化测试方法
  • 了解 可观测性 在生产环境中监控 Agent 行为
  • 学习 流式响应 优化用户体验
  • 掌握 部署 将调试好的 Agent 推向生产

参考资源

学习文档整合站点