关于 langsmith-custom-apps
langsmith-custom-apps 是指导 LangSmith Custom Apps 开发、验证和分享的技能,面向构建嵌入式 React 界面的开发者。它涵盖 CLI 生命周期、认证问题排查、数据验证和发布前检查。
主要功能
- 01指导应用初始化、开发与推送
- 02排查 CLI 版本和认证陷阱
- 03验证数据聚合与查询结果
- 04检查工作区迁移和分享内容
- 05提供发布前构建与安全检查
适用场景
- 01在 LangSmith 工作区开发 Custom App
- 02排查应用数据为空或令牌失效
- 03验证追踪数据分析结果
- 04将应用源码移至其他工作区
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ langchain-ai/ langsmith-skills --skill langsmith-custom-apps安装后在 Claude Code 中输入/langsmith-custom-apps确认已加载。
详细介绍
<agents_md_is_authoritative>
langsmith apps init 会在入门代码旁生成一个 AGENTS.md。该文件是应用内契约的权威来源——包括 window.langsmith.call 桥接、沙箱所依赖的 render() 导出、筛选器 DSL 和端点菜单。编写应用代码前请先阅读,并以该文件为准,不要依赖记忆。
本技能特意不复述这些内容。这里介绍的是 AGENTS.md 无法涵盖的事项:目录创建前会发生什么,以及应用推送后会发生什么。
</agents_md_is_authoritative>
export LANGSMITH_ENDPOINT=<your-langsmith-endpoint> # only for self-hosted
export LANGSMITH_API_KEY=<workspace-api-key>
有三个身份验证陷阱,它们表现出来都不像是身份验证问题:
- 环境中的
LANGSMITH_API_KEY优先于已保存的 OAuth 配置文件。 过期的导出密钥会导致每次调用都返回 403,但langsmith auth info仍会报告“已通过身份验证”。如果要使用登录凭据,请通过env -u LANGSMITH_API_KEY -u LANGSMITH_WORKSPACE_ID langsmith …运行一次性命令。 LANGSMITH_WORKSPACE_ID可能指向与密钥不同的工作区,这会导致令人困惑的 403,而不是工作区错误。取消设置该变量,并显式传入--workspace <uuid>。langsmith apps dev需要工作区 API 密钥,而非 OAuth。 它会在启动时获取一个访问令牌,之后不会刷新,因此大约十分钟后,每次调用都会返回401 Invalid token——应用会将其显示为空下拉菜单和空列表,而不是身份验证错误。如果运行中的应用数据悄然变为空,请首先怀疑这一点。
<cli_feedback> 遇到实际 CLI 故障、未记录的变通方法、令人困惑的输出或缺失功能后,请针对任务中的每个不同问题提交一条简洁的产品反馈。不要报告常规成功,也不要报告应用自身代码中的故障。
CLI 要求: langsmith feedback 需要 LangSmith CLI v0.2.58 或更高版本。使用 langsmith --version 检查已安装的版本。
使用 langsmith feedback --help 检查是否支持 feedback <note> 和 --category;如果不支持,请跳过反馈,不要使用原始 HTTP 或未发布的构建。使用现有的已通过身份验证的配置文件、端点和工作区。反馈会发送到 LangSmith Cloud,包括通过 BYOC 中继发送的情况;如果是独立自托管环境,则跳过。遵守用户/组织限制;如果是否有权限发送反馈不明确,请先询问。
用自己的话概述 CLI 的预期行为与实际观察到的行为,以及任何变通方法。绝不要发送密钥、客户数据、追踪负载、提示词、完整堆栈跟踪、复制的命令输出、原始参数、环境变量值、本地路径或资源标识符。CLI 会添加版本/操作系统/架构信息,但不会对你的备注进行脱敏;如果无法安全脱敏,请跳过。
请选择 bug、feature-request、usability、documentation 或 other。这是 CLI 产品反馈,不是运行评估反馈。以下仅为示例格式——只有实际遇到问题时才提交:
langsmith feedback --category documentation --format json "The apps template flag rejected a value the documentation lists as valid."
不要重试提交失败或遭遇速率限制的反馈,不要切换凭据/端点以绕过故障,也不要因反馈而耽误原始任务。 </cli_feedback>
<check_the_cli_first> 已发布文档往往领先于已发布的 CLI 构建版本,因此在信任任何命令之前,请先查看帮助输出。
langsmith --version
langsmith apps --help
langsmith apps init --help # the --template error message lists the real template set
</check_the_cli_first> 以下差异是在 v0.2.42 上观察到的,你当前使用的版本中可能已经修复。每项都写成了回退方案:只有在帮助输出确认命令缺失或标志被拒绝时才应用。
| 如果文档说 | 但 CLI 不一致 | 那么 |
|---|---|---|
langsmith apps pull APP_ID_OR_NAME | apps 帮助信息中没有 pull | 从平台 API 获取源代码(见 <pull_source>) |
--template blank | --template must be one of: … | 使用列出的模板;错误消息是当前的准确信息来源 |
| init“在以应用命名的新目录中生成脚手架” | <dir> is not empty; pass --force to write anyway | 先运行 mkdir my-app && cd my-app——init 会写入当前目录 |
| </check_the_cli_first> |
apps dev 会将应用失败的 API 调用和未捕获的错误流式输出到该终端。添加 --verbose 可查看每次成功调用以及所有 console.* 输出;添加 --quiet 则可将其静音。
如果 package.json 中有 build 脚本,apps push 会先进行构建;--no-build 则会原样上传。首次推送会创建应用,并通过 .langsmith/app.json 将目录关联到该应用;后续推送会更新同一个应用。--name 仅在创建时生效,之后传入则会重命名。提交 .langsmith/app.json,以便队友推送到同一个应用。
<pull_source>
当 CLI 没有 pull 命令时,平台 API 会在响应中内联返回所有文件:
langsmith apps list --workspace <ws-uuid> --format json # find the app id
curl -s -H "X-API-Key: $LANGSMITH_API_KEY" \
"https://api.smith.langchain.com/v1/platform/custom-apps/<app-id>" \
| python3 -c "
import json, os, sys
app = json.load(sys.stdin)
for path, content in app['files'].items():
os.makedirs(os.path.dirname(path) or '.', exist_ok=True)
open(path, 'w').write(content)
print(f\"wrote {len(app['files'])} files\")"
该记录还包含 name、entrypoint、current_version、scope、created_by、updated_by 和 views_7d。如需获取完整列表,请使用 GET /v1/platform/custom-apps。
</pull_source>
<replicate_across_workspaces>
- 将源代码拉取到一个全新的目录。
- 删除
.langsmith/app.json。 它会将该目录关联到源应用 ID;如果保留它,下次推送就会更新原应用,而不是在目标工作区创建新应用。这是此工作流中后果最严重的错误。 - 使用目标工作区和名称进行推送:
langsmith apps push --name <name> --workspace <target-ws-uuid>
- 将应用配置中与工作区相关的内容(深层链接中的工作区 UUID、项目 ID、反馈键)改为指向目标工作区,然后重新构建——关于仅编辑源代码为何不够,请参见
<before_sharing_externally>。 </replicate_across_workspaces>
<app_facts>
- 应用按工作区限定(
"scope": "workspace")。工作区外的人无法打开该 URL,因此“分享此应用”始终意味着交付源代码,而不是链接。 - 推送后
is_enabled: false是正常状态。 这不代表部署失败——不要按部署失败来排查。 - 删除命令为
langsmith apps delete <app-id-or-name> --yes;删除后无法恢复,因此请先对照apps list确认 ID。 </app_facts>
<verify_without_browser> 你无法点击应用,而其数据层中的错误会呈现为看似合理的空状态,而不是错误提示。在这项技能中,这个循环是最有价值的习惯。
- 保持聚合逻辑纯粹。 解析和计数应放在不依赖 React 且不使用
window.langsmith的模块中(例如src/lib/<domain>.ts);API 模块只负责获取行数据并将其交给该模块。 - 使用 CLI 将真实行数据保存为测试数据:
langsmith api runs/query -X POST --workspace <ws-uuid> \
-F 'session[]=<project-uuid>' -F 'filter=eq(run_type, "tool")' \
-F 'select[]=id' -F 'select[]=trace_id' -F 'select[]=inputs' -F 'limit=100' \
> /tmp/fixtures/tools.json
- 在 node 中用应用实际使用的 TypeScript 处理这些数据,并使用 vite 已自带的 esbuild——无需新增依赖或测试框架:
npx esbuild /tmp/harness.ts --bundle --platform=node --format=cjs \
--outfile=/tmp/harness.cjs && node /tmp/harness.cjs
- 对照原始数据检查数值,不要只看“运行成功”。一个真实案例:某应用通过匹配
/skills/<name>/下的路径来统计技能加载次数,但目录列表会将条目输出为'/memories/skills/auth-sso-scim',末尾没有斜杠,而匹配模式却要求有斜杠。于是该功能的全部输出——从未使用过的技能列表——都是空的,看起来像是结果确实干净。只有将计数与已捕获的行数据进行对比,才发现了问题。
每次推送前都运行 npx tsc --noEmit 和 npm run build;沙盒提供服务的正是构建产物。
</verify_without_browser>
<query_gotchas>
POST /api/v1/runs/query将limit上限设为 100。使用response.cursors.next翻页,并设置自己的硬性分页上限,避免繁忙的项目导致扫描无限进行;如果扫描因达到上限而截断,请在 UI 中告知读者。- 过滤器 DSL 会拒绝
search(name, "x")。已验证可用的语法:eq(name, "read_file")、or(eq(name,"a"), eq(name,"b"))、eq(run_type, "tool")、eq(is_root, true)、eq(status, "error")、gte(start_time, "<iso>")、has(tags, "prod")。 - 元数据相等过滤需要使用两个配对的子句,而不是
eq(metadata.key, …):
and(eq(metadata_key, "ls_agent_purpose"), eq(metadata_value, "coding"))
- 对于任何关键指标,优先使用
POST /api/v1/runs/stats和POST /api/v1/runs/group/stats:服务端聚合没有行数限制;只有在确实需要检查具体行时,才使用runs/query。 - 工具调用的
inputs会以两种形式传入,具体取决于 Agent 的序列化方式:{"file_path": "/x"}和{"input": "{\"file_path\":\"/x\"}"}。请在try/catch中解析内层 JSON 并处理这两种形式,否则会在不知不觉中漏算部分数据。 - 先探查,再假设某个端点存在。 有些看起来理应可以查询的信息其实无法查询:没有公开端点可以列出某个 Agent 的技能或 Fleet 成员名单。如果不存在权威列表,请从追踪记录中推导,并在 UI 中说明这一限制,而不要暗示列表完整。
- 将从追踪记录中读取的所有内容都视为不可信:将名称作为文本呈现(绝不使用
dangerouslySetInnerHTML),在 ID 进入过滤器字符串前进行验证,并且只将允许列表中的值插入 DSL。 </query_gotchas>
对于任何图表类内容,请先加载 dataviz 技能,再编写图表代码;并将图表颜色定义为 CSS 自定义属性,再通过 html.dark 覆盖块设置暗色主题颜色,以便沿用与令牌相同的主题处理机制。
<before_sharing_externally> 应用的作用域限定在工作区,因此分享意味着移交源代码。请在单独的副本中操作,切勿使用准备推送的目录,并检查以下内容:
- 清空配置中的工作区或组织 UUID——然后重新构建。配置值会编译进
dist/bundle.js,因此只修改源文件会导致产物保留旧值。 - 从交付内容中移除
.langsmith/app.json(包含内部应用 ID 和工作区)以及node_modules/。 - 在整个目录树中搜索 UUID、电子邮件地址、
lsv2_密钥和内部项目名称——包括 README 中的示例文本。 - 将内部基准测试相关表述替换为接收方需要自行修改的占位内容,并且只保留你确实可以为之背书的引用。
- 检查
package-lock.json中是否包含私有注册表主机或身份验证令牌。 - 重新运行
npx tsc --noEmit和npm run build,然后再次搜索dist/。 </before_sharing_externally>