跳到主要内容
当您在自动化操作中添加Webhook URL时,每当您定义的规则匹配任何新运行,我们都会向您的Webhook端点发送POST请求。

Webhook有效载荷

我们发送到您的Webhook端点的有效载荷包含:
  • "rule_id":这是发送此有效载荷的自动化ID。
  • "start_time""end_time":这是我们找到匹配运行的时间边界。
  • "runs":这是一个运行数组,每个运行都是一个字典。如果您需要每个运行的更多信息,建议在您的端点中使用我们的SDK从API获取。
  • "feedback_stats":这是一个包含运行反馈统计信息的字典。此字段的示例有效载荷如下所示。
"feedback_stats": {
    "about_langchain": {
        "n": 1,
        "avg": 0.0,
        "show_feedback_arrow": true,
        "values": {}
    },
    "category": {
        "n": 0,
        "avg": null,
        "show_feedback_arrow": true,
        "values": {
            "CONCEPTUAL": 1
        }
    },
    "user_score": {
        "n": 2,
        "avg": 0.0,
        "show_feedback_arrow": false,
        "values": {}
    },
    "vagueness": {
        "n": 1,
        "avg": 0.0,
        "show_feedback_arrow": true,
        "values": {}
    }
}
从S3 URL获取根据您的运行时间,inputs_s3_urlsoutputs_s3_urls 字段可能包含指向实际数据的S3 URL,而不是数据本身。inputsoutputs 可以分别通过inputs_s3_urlsoutputs_s3_urls 中提供的 ROOT.presigned_url 获取。
这是我们发送到您的Webhook端点的完整有效载荷示例:
{
  "rule_id": "d75d7417-0c57-4655-88fe-1db3cda3a47a",
  "start_time": "2024-04-05T01:28:54.734491+00:00",
  "end_time": "2024-04-05T01:28:56.492563+00:00",
  "runs": [
    {
      "status": "success",
      "is_root": true,
      "trace_id": "6ab80f10-d79c-4fa2-b441-922ed6feb630",
      "dotted_order": "20230505T051324571809Z6ab80f10-d79c-4fa2-b441-922ed6feb630",
      "run_type": "tool",
      "modified_at": "2024-04-05T01:28:54.145062",
      "tenant_id": "2ebda79f-2946-4491-a9ad-d642f49e0815",
      "end_time": "2024-04-05T01:28:54.085649",
      "name": "Search",
      "start_time": "2024-04-05T01:28:54.085646",
      "id": "6ab80f10-d79c-4fa2-b441-922ed6feb630",
      "session_id": "6a3be6a2-9a8c-4fc8-b4c6-a8983b286cc5",
      "parent_run_ids": [],
      "child_run_ids": null,
      "direct_child_run_ids": null,
      "total_tokens": 0,
      "completion_tokens": 0,
      "prompt_tokens": 0,
      "total_cost": null,
      "completion_cost": null,
      "prompt_cost": null,
      "first_token_time": null,
      "app_path": "/o/2ebda79f-2946-4491-a9ad-d642f49e0815/projects/p/6a3be6a2-9a8c-4fc8-b4c6-a8983b286cc5/r/6ab80f10-d79c-4fa2-b441-922ed6feb630?trace_id=6ab80f10-d79c-4fa2-b441-922ed6feb630&start_time=2023-05-05T05:13:24.571809",
      "in_dataset": false,
      "last_queued_at": null,
      "inputs": null,
      "inputs_s3_urls": null,
      "outputs": null,
      "outputs_s3_urls": null,
      "extra": null,
      "events": null,
      "feedback_stats": null,
      "serialized": null,
      "share_token": null
    }
  ]
}

安全

我们强烈建议您在Webhook URL中添加一个秘密查询字符串参数,并在任何传入请求上进行验证。这确保了如果有人发现您的Webhook URL,您可以将这些调用与真实的Webhook通知区分开来。 例如:
https://api.example.com/langsmith_webhook?secret=38ee77617c3a489ab6e871fbeb2ec87d

Webhook自定义HTTP头

如果您想在Webhook中发送任何特定的Header,可以为每个URL进行配置。要进行设置,请点击URL字段旁边的Headers选项并添加您的Header。
Header以加密格式存储。

Webhook交付

当向您的Webhook端点交付事件时,我们遵循以下准则:
  • 如果我们无法连接到您的端点,我们会在声明交付失败之前重试传输连接最多2次。
  • 如果您的端点回复时间超过5秒,我们将声明交付失败并且不。
  • 如果您的端点在5秒内返回5xx状态码,我们将以指数退避的方式重试最多2次。
  • 如果您的端点返回4xx状态码,我们将声明交付失败并且不重试。
  • 您的端点在响应体中返回的任何内容都将被忽略。

Modal示例

设置

为了说明如何设置,我们将使用Modal。Modal提供用于推理和微调的自动扩缩GPU、用于代码代理的安全容器化以及无服务器Python Web端点。我们将在这里重点介绍Web端点。 首先,创建一个Modal帐户。然后,在本地安装Modal SDK:
pip install modal
要完成帐户设置,请运行命令:
modal setup
并按照说明操作

密钥

接下来,您需要在Modal中设置一些密钥。 首先,LangSmith需要通过传入密钥来向Modal进行身份验证。最简单的方法是通过查询参数传入密钥。为了验证此密钥,我们需要在 Modal 中添加一个密钥来验证它。我们将通过创建Modal密钥来完成此操作。您可以在此处查看有关密钥的说明。为此,我们将密钥命名为 ls-webhook,并将其设置为环境变量,名称为 LS_WEBHOOK 我们还可以设置LangSmith密钥——幸运的是,已经有一个集成模板了! LangSmith Modal Template

服务

之后,您可以创建一个Python文件作为您的端点。示例如下,并附有解释性注释:
from fastapi import HTTPException, status, Request, Query
from modal import Secret, Stub, web_endpoint, Image

stub = Stub("auth-example", image=Image.debian_slim().pip_install("langsmith"))


@stub.function(
    secrets=[Secret.from_name("ls-webhook"), Secret.from_name("my-langsmith-secret")]
)
# We want this to be a `POST` endpoint since we will post data here
@web_endpoint(method="POST")
# We set up a `secret` query parameter
def f(data: dict, secret: str = Query(...)):
    # You can import dependencies you don't have locally inside Modal functions
    from langsmith import Client

    # First, we validate the secret key we pass
    import os

    if secret != os.environ["LS_WEBHOOK"]:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect bearer token",
            headers={"WWW-Authenticate": "Bearer"},
        )

    # This is where we put the logic for what should happen inside this webhook
    ls_client = Client()
    runs = data["runs"]
    ids = [r["id"] for r in runs]
    feedback = list(ls_client.list_feedback(run_ids=ids))
    for r, f in zip(runs, feedback):
        try:
            ls_client.create_example(
                inputs=r["inputs"],
                outputs={"output": f.correction},
                dataset_name="classifier-github-issues",
            )
        except Exception:
            raise ValueError(f"{r} and {f}")
    # Function body
    return "success!"
我们现在可以使用 modal deploy ... 轻松部署此服务(请参阅此处的文档)。 您现在应该会得到类似以下内容:
✓ Created objects.
├── 🔨 Created mount /Users/harrisonchase/workplace/langsmith-docs/example-webhook.py
├── 🔨 Created mount PythonPackage:langsmith
└── 🔨 Created f => https://hwchase17--auth-example-f.modal.run
✓ App deployed! 🎉

View Deployment: https://modal.com/apps/hwchase17/auth-example
重要的是要记住 https://hwchase17--auth-example-f.modal.run - 这是我们创建的用于运行的函数。注意:这不是最终的部署URL,请确保不要不小心使用它。

如何连接

我们现在可以将上面创建的函数URL添加为Webhook。我们还必须记住将密钥作为查询参数传入。综合起来,它应该看起来像这样:
https://hwchase17--auth-example-f-dev.modal.run?secret={SECRET}
{SECRET} 替换为您为访问Modal服务而创建的密钥。
以编程方式连接这些文档到 Claude、VSCode 等,通过 MCP 获取实时答案。
© . This site is unofficial and not affiliated with LangChain, Inc.