mcpField
L
langsmith-custom-apps

langsmith-custom-apps

github.com/langchain-ai开发164429 次安装1 天前更新
代码仓库

关于 langsmith-custom-apps

langsmith-custom-apps 是指导 LangSmith Custom Apps 开发、验证和分享的技能,面向构建嵌入式 React 界面的开发者。它涵盖 CLI 生命周期、认证问题排查、数据验证和发布前检查。

主要功能

  1. 01指导应用初始化、开发与推送
  2. 02排查 CLI 版本和认证陷阱
  3. 03验证数据聚合与查询结果
  4. 04检查工作区迁移和分享内容
  5. 05提供发布前构建与安全检查

适用场景

  1. 01在 LangSmith 工作区开发 Custom App
  2. 02排查应用数据为空或令牌失效
  3. 03验证追踪数据分析结果
  4. 04将应用源码移至其他工作区

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/langchain-ai/langsmith-skills --skill langsmith-custom-apps

安装后在 Claude Code 中输入/langsmith-custom-apps确认已加载。

详细介绍

Custom Apps 是 Enterprise 计划中的 React UI,可在 LangSmith 内部渲染,并通过宿主注入的桥接读取 LangSmith API。你可以使用 `langsmith apps` 在本地构建一个应用,推送后,它会显示在工作区侧边栏的 **Custom Apps** 下。本技能涵盖与应用目录相关的工作:CLI 接口、应用生命周期、验证和共享。

<agents_md_is_authoritative> langsmith apps init 会在入门代码旁生成一个 AGENTS.md。该文件是应用内契约的权威来源——包括 window.langsmith.call 桥接、沙箱所依赖的 render() 导出、筛选器 DSL 和端点菜单。编写应用代码前请先阅读,并以该文件为准,不要依赖记忆。

本技能特意不复述这些内容。这里介绍的是 AGENTS.md 无法涵盖的事项:目录创建前会发生什么,以及应用推送后会发生什么。 </agents_md_is_authoritative>

Custom Apps 需要 **Enterprise** 计划。向不支持此功能的工作区推送会失败,并显示 `this workspace doesn't support custom apps`。
export LANGSMITH_ENDPOINT=<your-langsmith-endpoint>   # only for self-hosted
export LANGSMITH_API_KEY=<workspace-api-key>

有三个身份验证陷阱,它们表现出来都不像是身份验证问题:

  1. 环境中的 LANGSMITH_API_KEY 优先于已保存的 OAuth 配置文件。 过期的导出密钥会导致每次调用都返回 403,但 langsmith auth info 仍会报告“已通过身份验证”。如果要使用登录凭据,请通过 env -u LANGSMITH_API_KEY -u LANGSMITH_WORKSPACE_ID langsmith … 运行一次性命令。
  2. LANGSMITH_WORKSPACE_ID 可能指向与密钥不同的工作区,这会导致令人困惑的 403,而不是工作区错误。取消设置该变量,并显式传入 --workspace <uuid>。
  3. 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_NAMEapps 帮助信息中没有 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>
```bash mkdir my-app && cd my-app langsmith apps init --name my-app --template --workspace npm install export LANGSMITH_API_KEY= # see setup trap 3 langsmith apps dev # live sandbox against LangSmith npm run build langsmith apps push --name my-app --workspace ```

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>

  1. 将源代码拉取到一个全新的目录。
  2. 删除 .langsmith/app.json。 它会将该目录关联到源应用 ID;如果保留它,下次推送就会更新原应用,而不是在目标工作区创建新应用。这是此工作流中后果最严重的错误。
  3. 使用目标工作区和名称进行推送:
langsmith apps push --name <name> --workspace <target-ws-uuid>
  1. 将应用配置中与工作区相关的内容(深层链接中的工作区 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> 你无法点击应用,而其数据层中的错误会呈现为看似合理的空状态,而不是错误提示。在这项技能中,这个循环是最有价值的习惯。

  1. 保持聚合逻辑纯粹。 解析和计数应放在不依赖 React 且不使用 window.langsmith 的模块中(例如 src/lib/<domain>.ts);API 模块只负责获取行数据并将其交给该模块。
  2. 使用 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
  1. 在 node 中用应用实际使用的 TypeScript 处理这些数据,并使用 vite 已自带的 esbuild——无需新增依赖或测试框架:
npx esbuild /tmp/harness.ts --bundle --platform=node --format=cjs \
  --outfile=/tmp/harness.cjs && node /tmp/harness.cjs
  1. 对照原始数据检查数值,不要只看“运行成功”。一个真实案例:某应用通过匹配 /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>
脚手架在 `src/index.css` 和 `tailwind.config.js` 中提供了 LangSmith 设计令牌。沙盒会在每次渲染前根据 `metadata.mode` 设置 `html.dark`,因此基于令牌的 UI 会自动适配主题,无需分支处理——只有内联样式才根据 `metadata.mode` 分支,并且每次渲染时都要重新检查,因为它可能在不卸载组件的情况下发生变化。

对于任何图表类内容,请先加载 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>

评论

支持 Markdown