主题
管理批量导出目的地
为 LangSmith 批量导出配置并管理 S3 兼容的导出目的地。
NOTE
对于自托管、GCP EU、GCP APAC 和 AWS US SaaS
对于自托管安装、GCP EU(eu.api.smith.langchain.com)、GCP APAC(apac.api.smith.langchain.com)或 AWS US(aws.api.smith.langchain.com),请更新下方请求中的 LangSmith URL。
目的地是一个命名配置,告诉 LangSmith 把导出的追踪数据写到何处。你创建一个目的地一次,然后在创建导出作业时按 ID 引用它。LangSmith 目前支持 S3 和任何 S3 兼容的存储桶(如 GCS 或 MinIO)作为目的地。导出数据以 Parquet 列式格式写入,含与运行数据格式等价的字段。
本页涵盖:
- 设置一个目的地所需的配置字段。
- AWS S3 和 GCS 所需的存储桶权限。
- 如何通过 API 创建一个目的地,包括提供商专属示例和凭据选项。
- 如何在无需重建目的地的情况下轮换目的地凭据。
- 如何在静态凭据与 AWS IAM 角色承担之间切换身份验证模式。
- 如何调试目的地错误。
配置字段
配置一个目的地需要以下信息:
- 存储桶名:数据将被导出到的 S3 存储桶的名字。
- 前缀:数据将被导出到的存储桶内的根前缀。
- S3 区域:存储桶的区域——AWS S3 存储桶必需。
- 端点 URL:S3 存储桶的端点 URL——S3 API 兼容存储桶必需。
- 访问密钥:S3 存储桶的访问密钥。
- 机密密钥:S3 存储桶的机密密钥。
- 在路径前缀中包含存储桶名(可选):是否把存储桶名作为路径前缀的一部分。默认为
true。当使用存储桶名已在端点 URL 中的 virtual-hosted 风格端点时,设为false。 - S3 配置选项(
config_kwargs_s3,可选):传给 botocore 的高级 S3 寻址风格和请求设置。最常见的用途是为那些需要 virtual-hosted 或 path 风格请求的 S3 兼容服务设置addressing_style:"virtual":存储桶名是主机名的一部分(例如bucket.endpoint/key)。对某些 S3 兼容服务(如 Volcengine TOS)必需。"path":存储桶名是 URL 路径的一部分(例如endpoint/bucket/key)。"auto"(默认):boto3 依据端点决定。
我们支持任何 S3 兼容的存储桶。对于非 AWS 存储桶(如 GCS 或 MinIO),你需要提供端点 URL。
所需权限
backend 和 queue 两个服务都需要对目的地存储桶的写入访问权:
- 当创建导出目的地时,
backend服务会尝试向目的地存储桶写一个测试文件。若它有权删除就删掉该测试文件(删除访问可选)。 queue服务负责批量导出执行和把文件上传到存储桶。
AWS S3 权限
最小的 AWS S3 权限策略依赖以下权限:
s3:PutObject(必需):允许向存储桶写 Parquet 文件。s3:DeleteObject(可选):在创建目的地期间清理测试文件。若缺少此权限,文件会在创建目的地后被留在/tmp目录下。s3:GetObject(可选但推荐):写入后验证文件大小。s3:AbortMultipartUpload(可选但推荐):避免悬空的分片上传。
最小 IAM 策略示例:
json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::YOUR_BUCKET_NAME/*"
]
}
]
}带额外权限的推荐 IAM 策略示例:
json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::YOUR_BUCKET_NAME/*"
]
}
]
}Google Cloud Storage(GCS)权限
当用 S3 兼容 XML API 使用 GCS 时,需要以下 IAM 权限:
storage.objects.create(必需):允许向存储桶写文件。storage.objects.delete(可选):在创建目的地期间清理测试文件。若缺少此权限,文件会在创建目的地后被留在/tmp目录下。storage.objects.get(可选但推荐):写入后验证文件大小。
这些权限可以通过“Storage Object Admin”预定义角色或一个自定义角色授予。
创建一个目的地
下面的示例演示如何用 cURL 创建一个目的地。把占位符值替换为你的实际配置详情。 注意凭据会被安全地以加密形式存储在我们的系统中。
bash
curl --request POST \
--url 'https://api.smith.langchain.com/api/v1/bulk-exports/destinations' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--header 'X-Tenant-Id: YOUR_WORKSPACE_ID' \
--data '{
"destination_type": "s3",
"display_name": "My S3 Destination",
"config": {
"bucket_name": "your-s3-bucket-name",
"prefix": "root_folder_prefix",
"region": "your aws s3 region",
"endpoint_url": "your endpoint url for s3 compatible buckets",
"include_bucket_in_prefix": true // defaults to true, can be omitted
},
"credentials": {
"access_key_id": "YOUR_S3_ACCESS_KEY_ID",
"secret_access_key": "YOUR_S3_SECRET_ACCESS_KEY"
}
}'用返回的 id 在后续的批量导出操作中引用这个目的地。
如果创建目的地时收到错误,见调试目的地错误了解如何调试。
凭据配置
NOTE
需要 LangSmith Helm 版本 0.10.34 或更高(应用版本 0.10.91 或更高)
除了静态的 access_key_id 和 secret_access_key,我们还支持以下额外的凭据格式:
- 要使用带一个 AWS session 令牌的临时凭据, 在创建批量导出目的地时额外提供
credentials.session_token键。 - (仅自托管):要使用基于环境的凭据(如 AWS IAM Roles for Service Accounts(IRSA)), 在创建批量导出目的地时从请求中省略
credentials键。 在这种情况下,会按该库定义的顺序检查标准 Boto3 凭据位置。
AWS S3 存储桶
对于 AWS S3,你可以省略 endpoint_url 并提供一个与你存储桶区域匹配的区域。
bash
curl --request POST \
--url 'https://api.smith.langchain.com/api/v1/bulk-exports/destinations' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--header 'X-Tenant-Id: YOUR_WORKSPACE_ID' \
--data '{
"destination_type": "s3",
"display_name": "My AWS S3 Destination",
"config": {
"bucket_name": "my_bucket",
"prefix": "data_exports",
"region": "us-east-1"
},
"credentials": {
"access_key_id": "YOUR_S3_ACCESS_KEY_ID",
"secret_access_key": "YOUR_S3_SECRET_ACCESS_KEY"
}
}'Google GCS XML S3 兼容存储桶
使用 Google 的 GCS 存储桶时,你需要使用 XML S3 兼容 API,并提供 endpoint_url, 它通常是 https://storage.googleapis.com。 下面是使用与 S3 兼容的 GCS XML API 时的 API 请求示例:
bash
curl --request POST \
--url 'https://api.smith.langchain.com/api/v1/bulk-exports/destinations' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--header 'X-Tenant-Id: YOUR_WORKSPACE_ID' \
--data '{
"destination_type": "s3",
"display_name": "My GCS Destination",
"config": {
"bucket_name": "my_bucket",
"prefix": "data_exports",
"endpoint_url": "https://storage.googleapis.com"
"include_bucket_in_prefix": true // defaults to true, can be omitted
},
"credentials": {
"access_key_id": "YOUR_S3_ACCESS_KEY_ID",
"secret_access_key": "YOUR_S3_SECRET_ACCESS_KEY"
}
}'更多信息参阅 Google 文档
用 virtual-hosted 风格寻址的 S3 兼容存储桶
某些 S3 兼容服务(如 Volcengine TOS)要求 virtual-hosted 风格寻址,其中存储桶名是主机名的一部分而非 URL 路径的一部分。用带 addressing_style: "virtual" 的 config_kwargs_s3 来启用它:
bash
curl --request POST \
--url 'https://api.smith.langchain.com/api/v1/bulk-exports/destinations' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--header 'X-Tenant-Id: YOUR_WORKSPACE_ID' \
--data '{
"destination_type": "s3",
"display_name": "My Volcengine TOS Destination",
"config": {
"bucket_name": "my_bucket",
"prefix": "data_exports",
"endpoint_url": "https://tos-s3-cn-beijing.volces.com",
"config_kwargs_s3": {
"addressing_style": "virtual"
}
},
"credentials": {
"access_key_id": "YOUR_ACCESS_KEY_ID",
"secret_access_key": "YOUR_SECRET_ACCESS_KEY"
}
}'用 virtual-hosted 风格端点的 S3 兼容存储桶
如果你的端点 URL 已包含存储桶名(virtual-hosted 风格),把 include_bucket_in_prefix 设为 false 以避免在路径中重复存储桶名:
bash
curl --request POST \
--url 'https://api.smith.langchain.com/api/v1/bulk-exports/destinations' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--header 'X-Tenant-Id: YOUR_WORKSPACE_ID' \
--data '{
"destination_type": "s3",
"display_name": "My Virtual-Hosted Destination",
"config": {
"bucket_name": "my_bucket",
"prefix": "data_exports",
"endpoint_url": "https://my_bucket.s3.us-east-1.amazonaws.com",
"include_bucket_in_prefix": false
},
"credentials": {
"access_key_id": "YOUR_S3_ACCESS_KEY_ID",
"secret_access_key": "YOUR_S3_SECRET_ACCESS_KEY"
}
}'轮换目的地凭据
用 PATCH /api/v1/bulk-exports/destinations/{destination_id} 更新一个现有目的地上的凭据。这让你能轮换或替换凭据而无需重建目的地或其相关的批量导出。目的地配置(存储桶、前缀、区域、端点等)不变——只替换凭据。
凭据轮换行为
切换不是即时的:
- 新的批量导出运行 在 PATCH 完成后立即使用更新后的凭据。
- 已在运行的批量导出运行 继续使用先前的凭据直到完成。
- 两组凭据在过渡期内同时有效。 这个窗口持续至多到单次批量导出运行的最大运行时长。
相应地规划你的轮换:旧凭据必须保持有效直到所有进行中的运行完成。
请求
bash
curl --request PATCH \
--url 'https://api.smith.langchain.com/api/v1/bulk-exports/destinations/{destination_id}' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--header 'X-Tenant-Id: YOUR_WORKSPACE_ID' \
--data '{
"credentials": {
"access_key_id": "YOUR_NEW_ACCESS_KEY_ID",
"secret_access_key": "YOUR_NEW_SECRET_ACCESS_KEY"
}
}'session_token 字段是可选的,你可以为临时凭据包含它。
所需权限:bulk-exports:manage。
在存储新凭据之前,LangSmith 会用现有的目的地配置做一次测试写来验证它们。如果凭据没有足够的写入权限,请求会以 400 失败。如果请求失败,参阅调试目的地错误。
响应
返回更新后的目的地对象。凭据值从不返回——响应中在 credentials_keys 下只包含凭据字段名。
json
{
"id": "destination-uuid",
"tenant_id": "tenant-uuid",
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-06-01T00:00:00Z",
"credentials_keys": ["access_key_id", "secret_access_key"]
}轮换清单
- 在你的云提供商中预配对目的地存储桶和前缀有写入访问的新凭据。
- 用新凭据调用 PATCH 端点。LangSmith 在保存前验证它们。
- 保持旧凭据活动直到所有进行中的批量导出运行完成(至多到最大运行时长)。
- 一旦没有运行在用旧凭据,就撤销它们。
用一个 AWS IAM 角色身份验证
AWS IAM 角色承担让 GCP 托管的 LangSmith SaaS 能导出到 S3 而无需存静态 AWS 凭据。配置一个信任你生产区域 LangSmith 服务账户的 AWS 角色,然后在创建或更新目的地时提供它的 ARN。
传 aws_role_arn 而非 credentials 以使用 IAM 角色承担。
NOTE
IAM 角色承担仅在 GCP 托管的 LangSmith SaaS 上可用。它在 AWS 托管的 SaaS 或自托管部署上不可用。
创建 AWS 角色
创建一个 AWS IAM 角色,其信任策略允许来自你区域三个 subject ID 的 web 身份联合。给该角色授予对你导出存储桶的访问。选择你的 LangSmith 区域以使用对应的 subject ID。每个 Terraform 示例都用所需的最小 s3:PutObject 权限:
hcl
resource "aws_iam_role" "langsmith_bulk_export" {
name = "langsmith-bulk-export"
max_session_duration = 43200
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Federated = "accounts.google.com" }
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"accounts.google.com:oaud" = "langsmith-bulk-export"
"accounts.google.com:sub" = [
"110136955440523778103",
"116331607438151298187",
"115251468294701876731",
]
}
}
}]
})
inline_policy {
name = "langsmith-bulk-export-s3"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "s3:PutObject"
Resource = "arn:aws:s3:::YOUR_BUCKET_NAME/*"
}]
})
}
}hcl
resource "aws_iam_role" "langsmith_bulk_export" {
name = "langsmith-bulk-export"
max_session_duration = 43200
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Federated = "accounts.google.com" }
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"accounts.google.com:oaud" = "langsmith-bulk-export"
"accounts.google.com:sub" = [
"110207823358662523645",
"115689110758588220909",
"109691164801275818274",
]
}
}
}]
})
inline_policy {
name = "langsmith-bulk-export-s3"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "s3:PutObject"
Resource = "arn:aws:s3:::YOUR_BUCKET_NAME/*"
}]
})
}
}hcl
resource "aws_iam_role" "langsmith_bulk_export" {
name = "langsmith-bulk-export"
max_session_duration = 43200
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Federated = "accounts.google.com" }
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"accounts.google.com:oaud" = "langsmith-bulk-export"
"accounts.google.com:sub" = [
"105923862603785245337",
"114288557158507552617",
"116622461022404604716",
]
}
}
}]
})
inline_policy {
name = "langsmith-bulk-export-s3"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "s3:PutObject"
Resource = "arn:aws:s3:::YOUR_BUCKET_NAME/*"
}]
})
}
}可选权限见 AWS S3 权限。
切换身份验证模式
在不重建现有目的地的情况下,在静态凭据和 AWS IAM 角色承担之间切换它。用 PATCH /api/v1/bulk-exports/destinations/{destination_id}。
所需权限:bulk-exports:manage。
LangSmith 支持两种互斥的模式:
- 静态凭据(
credentials):一个access_key_id和一个secret_access_key(临时凭据带可选的session_token)。 - IAM 角色承担(
aws_role_arn):LangSmith 承担指定的 AWS IAM 角色,因此不存静态凭据。
要切换到 AWS IAM 角色承担,在 PATCH 请求体中提供 aws_role_arn。要切换到静态凭据,提供 credentials。当任一字段存在且非空时,LangSmith 会清除另一个。
切换之前,确保新的身份验证配置对目的地存储桶有写入访问。LangSmith 用一次测试写在保存前验证配置。
从静态凭据切换到 AWS IAM 角色
在 PATCH 请求体中提供 aws_role_arn。这会清除任何先前存储的凭据。
bash
curl --request PATCH \
--url 'https://api.smith.langchain.com/api/v1/bulk-exports/destinations/{destination_id}' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--header 'X-Tenant-Id: YOUR_WORKSPACE_ID' \
--data '{
"aws_role_arn": "arn:aws:iam::123456789012:role/LangSmithBulkExportRole"
}'从 AWS IAM 角色切换到静态凭据
在 PATCH 请求体中提供一个 credentials 对象。这会清除存储的角色 ARN。
bash
curl --request PATCH \
--url 'https://api.smith.langchain.com/api/v1/bulk-exports/destinations/{destination_id}' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--header 'X-Tenant-Id: YOUR_WORKSPACE_ID' \
--data '{
"credentials": {
"access_key_id": "YOUR_NEW_ACCESS_KEY_ID",
"secret_access_key": "YOUR_NEW_SECRET_ACCESS_KEY"
}
}'切换期间的行为
凭据轮换中描述的同样的过渡行为,也适用于切换身份验证模式时:
- 新的批量导出运行 在 PATCH 完成后立即使用新的身份验证模式。
- 已在运行的批量导出运行 继续使用先前的身份验证模式直到完成。
如果因新配置没有足够写入权限导致测试写失败,请求返回 400。
调试目的地错误
目的地 API 端点会验证目的地和凭据有效,且对该存储桶 存在写入访问。
如果你收到一个错误并想调试它,你可以用 AWS CLI 测试到存储桶的连通性。你应该能用你在上面提供给目的地 API 的同样数据,用 CLI 写一个文件。
AWS S3:
bash
aws configure
# set the same access key credentials and region as you used for the destination
> AWS Access Key ID: <access_key_id>
> AWS Secret Access Key: <secret_access_key>
> Default region name [us-east-1]: <region>
# List buckets
aws s3 ls /
# test write permissions
touch ./test.txt
aws s3 cp ./test.txt s3://<bucket-name>/tmp/test.txtGCS 兼容存储桶:
你需要用 --endpoint-url 选项提供 endpoint_url。 对于 GCS,endpoint_url 通常是 https://storage.googleapis.com:
bash
aws configure
# set the same access key credentials and region as you used for the destination
> AWS Access Key ID: <access_key_id>
> AWS Secret Access Key: <secret_access_key>
> Default region name [us-east-1]: <region>
# List buckets
aws s3 --endpoint-url=<endpoint_url> ls /
# test write permissions
touch ./test.txt
aws s3 --endpoint-url=<endpoint_url> cp ./test.txt s3://<bucket-name>/tmp/test.txt常见错误
以下是一些常见错误:
| 错误 | 描述 |
|---|---|
| 访问被拒 | blob 存储凭据或存储桶无效。当提供的访问密钥和机密密钥组合没有访问指定存储桶或执行所需操作所必需的权限时,发生此错误。 |
| 存储桶不合法 | 指定的 blob 存储桶不合法。当存储桶不存在、或没有足够权限在存储桶上执行写入时,抛出此错误。 |
| 你提供的 Key ID 不存在 | 提供的 blob 存储凭据不合法。当用于身份验证的访问密钥 ID 不是有效密钥时,发生此错误。 |
| 端点无效 | 提供的 endpoint_url 无效。当指定的端点是一个无效端点时抛出此错误。只支持 S3 兼容的端点,例如 GCS 用 https://storage.googleapis.com、minio 用 https://play.min.io 等。若用 AWS,你应省略 endpoint_url。 |
| InvalidBucketName | S3 兼容服务因寻址风格不匹配而拒绝请求。某些服务要求 virtual-hosted 风格寻址。在你的目的地配置中设 config_kwargs_s3: {"addressing_style": "virtual"} 来解决此问题。 |