跳转至

身份验证和访问控制

LangGraph Platform 提供了一个灵活的身份验证和授权系统,可以与大多数身份验证方案集成。

核心概念

身份验证与授权

虽然这些术语经常互换使用,但它们代表不同的安全概念:

  • 身份验证("AuthN")验证_你是谁_。这作为每个请求的中间件运行。
  • 授权("AuthZ")确定_你可以做什么_。这在每个资源的基础上验证用户的权限和角色。

在 LangGraph Platform 中,身份验证由你的 @auth.authenticate 处理器处理,授权由你的 @auth.on 处理器处理。

在 LangGraph Platform 中,身份验证由你的 @auth.authenticate 处理器处理,授权由你的 @auth.on 处理器处理。

默认安全模型

LangGraph Platform 提供不同的安全默认值:

LangGraph Platform

  • 默认使用 LangSmith API 密钥
  • 要求在 x-api-key 标头中提供有效的 API 密钥
  • 可以使用你的身份验证处理器进行自定义

自定义身份验证

LangGraph Platform 的所有计划都**支持**自定义身份验证。

自托管

  • 无默认身份验证
  • 完全灵活地实现你的安全模型
  • 你控制身份验证和授权的所有方面

系统架构

典型的身份验证设置涉及三个主要组件:

  1. 身份验证提供者(身份提供者/IdP)

  2. 管理用户身份和凭据的专用服务

  3. 处理用户注册、登录、密码重置等
  4. 在成功身份验证后颁发令牌(JWT、会话令牌等)
  5. 示例:Auth0、Supabase Auth、Okta 或你自己的身份验证服务器

  6. LangGraph 后端(资源服务器)

  7. 包含业务逻辑和受保护资源的 LangGraph 应用程序

  8. 与身份验证提供者验证令牌
  9. 基于用户身份和权限执行访问控制
  10. 不直接存储用户凭据

  11. 客户端应用程序(前端)

  12. Web 应用、移动应用或 API 客户端

  13. 收集时间敏感的用户凭据并发送到身份验证提供者
  14. 从身份验证提供者接收令牌
  15. 在对 LangGraph 后端的请求中包含这些令牌

以下是这些组件通常如何交互:

sequenceDiagram
    participant Client as Client App
    participant Auth as Auth Provider
    participant LG as LangGraph Backend

    Client->>Auth: 1. Login (username/password)
    Auth-->>Client: 2. Return token
    Client->>LG: 3. Request with token
    Note over LG: 4. Validate token (@auth.authenticate)
    LG-->>Auth:  5. Fetch user info
    Auth-->>LG: 6. Confirm validity
    Note over LG: 7. Apply access control (@auth.on.*)
    LG-->>Client: 8. Return resources

你在 LangGraph 中的 @auth.authenticate 处理器处理步骤 4-6,而你的 @auth.on 处理器实现步骤 7。

你在 LangGraph 中的 auth.authenticate 处理器处理步骤 4-6,而你的 auth.on 处理器实现步骤 7。

身份验证

LangGraph 中的身份验证作为每个请求的中间件运行。你的 @auth.authenticate 处理器接收请求信息并应该:

  1. 验证凭据
  2. 如果有效,返回包含用户身份和用户信息的用户信息
  3. 如果无效,引发 HTTPException 或 AssertionError
from langgraph_sdk import Auth

auth = Auth()

@auth.authenticate
async def authenticate(headers: dict) -> Auth.types.MinimalUserDict:
    # Validate credentials (e.g., API key, JWT token)
    api_key = headers.get("x-api-key")
    if not api_key or not is_valid_key(api_key):
        raise Auth.exceptions.HTTPException(
            status_code=401,
            detail="Invalid API key"
        )

    # Return user info - only identity and is_authenticated are required
    # Add any additional fields you need for authorization
    return {
        "identity": "user-123",        # Required: unique user identifier
        "is_authenticated": True,      # Optional: assumed True by default
        "permissions": ["read", "write"] # Optional: for permission-based auth
        # You can add more custom fields if you want to implement other auth patterns
        "role": "admin",
        "org_id": "org-456"

    }

返回的用户信息可用于:

  • 通过 ctx.user 提供给你的授权处理器
  • 通过 config["configuration"]["langgraph_auth_user"] 在你的应用程序中使用

LangGraph 中的身份验证作为每个请求的中间件运行。你的 authenticate 处理器接收请求信息并应该:

  1. 验证凭据
  2. 如果有效,返回包含用户身份和用户信息的用户信息
  3. 如果无效,引发 HTTPException
import { Auth, HTTPException } from "@langchain/langgraph-sdk";

export const auth = new Auth();

auth.authenticate(async (request) => {
  // Validate credentials (e.g., API key, JWT token)
  const apiKey = request.headers.get("x-api-key");
  if (!apiKey || !isValidKey(apiKey)) {
    throw new HTTPException(401, "Invalid API key");
  }

  // Return user info - only identity and isAuthenticated are required
  // Add any additional fields you need for authorization
  return {
    identity: "user-123", // Required: unique user identifier
    isAuthenticated: true, // Optional: assumed true by default
    permissions: ["read", "write"], // Optional: for permission-based auth
    // You can add more custom fields if you want to implement other auth patterns
    role: "admin",
    orgId: "org-456",
  };
});

返回的用户信息可用于:

  • 通过回调处理器中的 user 属性提供给你的授权处理器
  • 通过 config.configurable.langgraph_auth_user 在你的应用程序中使用
支持的参数

@auth.authenticate 处理器可以按名称接受以下任何参数:

  • request (Request): 原始 ASGI 请求对象
  • body (dict): 解析后的请求体
  • path (str): 请求路径,例如 "/threads/abcd-1234-abcd-1234/runs/abcd-1234-abcd-1234/stream"
  • method (str): HTTP 方法,例如 "GET"
  • path_params (dict[str, str]): URL 路径参数,例如 {"thread_id": "abcd-1234-abcd-1234", "run_id": "abcd-1234-abcd-1234"}
  • query_params (dict[str, str]): URL 查询参数,例如 {"stream": "true"}
  • headers (dict[bytes, bytes]): 请求标头
  • authorization (str | None): Authorization 标头值(例如 "Bearer ")

authenticate 处理器可以接受以下任何参数:

  • request (Request): 原始请求对象
  • body (object): 解析后的请求体
  • path (string): 请求路径,例如 "/threads/abcd-1234-abcd-1234/runs/abcd-1234-abcd-1234/stream"
  • method (string): HTTP 方法,例如 "GET"
  • pathParams (Record): URL 路径参数,例如 {"threadId": "abcd-1234-abcd-1234", "runId": "abcd-1234-abcd-1234"}
  • queryParams (Record): URL 查询参数,例如 {"stream": "true"}
  • headers (Record): 请求标头
  • authorization (string | null): Authorization 标头值(例如 "Bearer ")

在我们的许多教程中,为了简洁起见,我们只显示 "authorization" 参数,但你可以根据需要选择接受更多信息以实现自定义身份验证方案。

智能代理身份验证

自定义身份验证允许委托访问。你在 @auth.authenticate 中返回的值会添加到运行上下文中,为智能代理提供用户范围的凭据,让它们可以代表用户访问资源。

sequenceDiagram
  %% Actors
  participant ClientApp as Client
  participant AuthProv  as Auth Provider
  participant LangGraph as LangGraph Backend
  participant SecretStore as Secret Store
  participant ExternalService as External Service

  %% Platform login / AuthN
  ClientApp  ->> AuthProv: 1. Login (username / password)
  AuthProv   -->> ClientApp: 2. Return token
  ClientApp  ->> LangGraph: 3. Request with token

  Note over LangGraph: 4. Validate token (@auth.authenticate)
  LangGraph  -->> AuthProv: 5. Fetch user info
  AuthProv   -->> LangGraph: 6. Confirm validity

  %% Fetch user tokens from secret store
  LangGraph  ->> SecretStore: 6a. Fetch user tokens
  SecretStore -->> LangGraph: 6b. Return tokens

  Note over LangGraph: 7. Apply access control (@auth.on.*)

  %% External Service round-trip
  LangGraph  ->> ExternalService: 8. Call external service (with header)
  Note over ExternalService: 9. External service validates header and executes action
  ExternalService  -->> LangGraph: 10. Service response

  %% Return to caller
  LangGraph  -->> ClientApp: 11. Return resources

在身份验证之后,平台会创建一个特殊的配置对象,该对象通过可配置上下文传递给你的图和所有节点。 此对象包含有关当前用户的信息,包括你从 @auth.authenticate 处理器返回的任何自定义字段。

要使智能代理能够代表用户行事,请使用自定义身份验证中间件。这将允许智能代理与外部系统(如 MCP 服务器、外部数据库,甚至其他智能代理)进行交互,代表用户。

有关更多信息,请参阅使用自定义身份验证指南。

使用 MCP 进行智能代理身份验证

有关如何对 MCP 服务器进行智能代理身份验证的信息,请参阅 MCP 概念指南

授权

在身份验证之后,LangGraph 调用你的授权处理器来控制对特定资源(例如线程、助手、定时任务)的访问。这些处理器可以:

  1. 通过修改元数据来添加在资源创建期间保存的元数据。有关每个操作的值可以采用的类型列表,请参阅支持的操作表
  2. 在搜索/列表或读取操作期间通过返回过滤器来按元数据过滤资源。
  3. 如果访问被拒绝,则引发 HTTP 异常。

如果你只想实现简单的用户范围访问控制,可以为所有资源和操作使用单个授权处理器。如果你想根据资源和操作进行不同的控制,可以使用资源特定处理器。有关支持访问控制的资源的完整列表,请参阅支持的资源部分。

你的 @auth.on 处理器通过直接修改 value["metadata"] 字典并返回过滤器字典来控制访问。

@auth.on
async def add_owner(
    ctx: Auth.types.AuthContext,
    value: dict  # The payload being sent to this access method
) -> dict:  # Returns a filter dict that restricts access to resources
    """Authorize all access to threads, runs, crons, and assistants.

    This handler does two things:
        - Adds a value to resource metadata (to persist with the resource so it can be filtered later)
        - Returns a filter (to restrict access to existing resources)

    Args:
        ctx: Authentication context containing user info, permissions, the path, and
        value: The request payload sent to the endpoint. For creation
              operations, this contains the resource parameters. For read
              operations, this contains the resource being accessed.

    Returns:
        A filter dictionary that LangGraph uses to restrict access to resources.
        See [Filter Operations](#filter-operations) for supported operators.
    """
    # Create filter to restrict access to just this user's resources
    filters = {"owner": ctx.user.identity}

    # Get or create the metadata dictionary in the payload
    # This is where we store persistent info about the resource
    metadata = value.setdefault("metadata", {})

    # Add owner to metadata - if this is a create or update operation,
    # this information will be saved with the resource
    # So we can filter by it later in read operations
    metadata.update(filters)

    # Return filters to restrict access
    # These filters are applied to ALL operations (create, read, update, search, etc.)
    # to ensure users can only access their own resources
    return filters

你可以通过直接修改 value.metadata 对象并在注册 on() 处理器时返回过滤器对象来精细控制访问。

import { Auth, HTTPException } from "@langchain/langgraph-sdk/auth";

export const auth = new Auth()
  .authenticate(async (request: Request) => ({
    identity: "user-123",
    permissions: [],
  }))
  .on("*", ({ value, user }) => {
    // Create filter to restrict access to just this user's resources
    const filters = { owner: user.identity };

    // If the operation supports metadata, add the user identity
    // as metadata to the resource.
    if ("metadata" in value) {
      value.metadata ??= {};
      value.metadata.owner = user.identity;
    }

    // Return filters to restrict access
    // These filters are applied to ALL operations (create, read, update, search, etc.)
    // to ensure users can only access their own resources
    return filters;
  });

资源特定处理器

你可以通过将资源和操作名称与授权装饰器链接在一起来为特定资源和操作注册处理器。 当发出请求时,将调用与该资源和操作匹配的最具体的处理器。以下是如何为特定资源和操作注册处理器的示例。对于以下设置:

  1. 经过身份验证的用户能够创建线程、读取线程以及在线程上创建运行
  2. 只有具有 "assistants:create" 权限的用户才能创建新助手
  3. 所有其他端点(例如删除助手、定时任务、存储)对所有用户禁用。

支持的处理器

有关支持的资源和操作的完整列表,请参阅下面的支持的资源部分。

# Generic / global handler catches calls that aren't handled by more specific handlers
@auth.on
async def reject_unhandled_requests(ctx: Auth.types.AuthContext, value: Any) -> False:
    print(f"Request to {ctx.path} by {ctx.user.identity}")
    raise Auth.exceptions.HTTPException(
        status_code=403,
        detail="Forbidden"
    )

# Matches the "thread" resource and all actions - create, read, update, delete, search
# Since this is **more specific** than the generic @auth.on handler, it will take precedence
# over the generic handler for all actions on the "threads" resource
@auth.on.threads
async def on_thread_create(
    ctx: Auth.types.AuthContext,
    value: Auth.types.threads.create.value
):
    if "write" not in ctx.permissions:
        raise Auth.exceptions.HTTPException(
            status_code=403,
            detail="User lacks the required permissions."
        )
    # Setting metadata on the thread being created
    # will ensure that the resource contains an "owner" field
    # Then any time a user tries to access this thread or runs within the thread,
    # we can filter by owner
    metadata = value.setdefault("metadata", {})
    metadata["owner"] = ctx.user.identity
    return {"owner": ctx.user.identity}

# Thread creation. This will match only on thread create actions
# Since this is **more specific** than both the generic @auth.on handler and the @auth.on.threads handler,
# it will take precedence for any "create" actions on the "threads" resources
@auth.on.threads.create
async def on_thread_create(
    ctx: Auth.types.AuthContext,
    value: Auth.types.threads.create.value
):
    # Setting metadata on the thread being created
    # will ensure that the resource contains an "owner" field
    # Then any time a user tries to access this thread or runs within the thread,
    # we can filter by owner
    metadata = value.setdefault("metadata", {})
    metadata["owner"] = ctx.user.identity
    return {"owner": ctx.user.identity}

# Reading a thread. Since this is also more specific than the generic @auth.on handler, and the @auth.on.threads handler,
# it will take precedence for any "read" actions on the "threads" resource
@auth.on.threads.read
async def on_thread_read(
    ctx: Auth.types.AuthContext,
    value: Auth.types.threads.read.value
):
    # Since we are reading (and not creating) a thread,
    # we don't need to set metadata. We just need to
    # return a filter to ensure users can only see their own threads
    return {"owner": ctx.user.identity}

# Run creation, streaming, updates, etc.
# This takes precedenceover the generic @auth.on handler and the @auth.on.threads handler
@auth.on.threads.create_run
async def on_run_create(
    ctx: Auth.types.AuthContext,
    value: Auth.types.threads.create_run.value
):
    metadata = value.setdefault("metadata", {})
    metadata["owner"] = ctx.user.identity
    # Inherit thread's access control
    return {"owner": ctx.user.identity}

# Assistant creation
@auth.on.assistants.create
async def on_assistant_create(
    ctx: Auth.types.AuthContext,
    value: Auth.types.assistants.create.value
):
    if "assistants:create" not in ctx.permissions:
        raise Auth.exceptions.HTTPException(
            status_code=403,
            detail="User lacks the required permissions."
        )
import { Auth, HTTPException } from "@langchain/langgraph-sdk/auth";

export const auth = new Auth()
  .authenticate(async (request: Request) => ({
    identity: "user-123",
    permissions: ["threads:write", "threads:read"],
  }))
  .on("*", ({ event, user }) => {
    console.log(`Request for ${event} by ${user.identity}`);
    throw new HTTPException(403, { message: "Forbidden" });
  })

  // Matches the "threads" resource and all actions - create, read, update, delete, search
  // Since this is **more specific** than the generic `on("*")` handler, it will take precedence over the generic handler for all actions on the "threads" resource
  .on("threads", ({ permissions, value, user }) => {
    if (!permissions.includes("write")) {
      throw new HTTPException(403, {
        message: "User lacks the required permissions.",
      });
    }

    // Not all events do include `metadata` property in `value`.
    // So we need to add this type guard.
    if ("metadata" in value) {
      value.metadata ??= {};
      value.metadata.owner = user.identity;
    }

    return { owner: user.identity };
  })

  // Thread creation. This will match only on thread create actions.
  // Since this is **more specific** than both the generic `on("*")` handler and the `on("threads")` handler, it will take precedence for any "create" actions on the "threads" resources
  .on("threads:create", ({ value, user, permissions }) => {
    if (!permissions.includes("write")) {
      throw new HTTPException(403, {
        message: "User lacks the required permissions.",
      });
    }

    // Setting metadata on the thread being created will ensure that the resource contains an "owner" field
    // Then any time a user tries to access this thread or runs within the thread,
    // we can filter by owner
    value.metadata ??= {};
    value.metadata.owner = user.identity;

    return { owner: user.identity };
  })

  // Reading a thread. Since this is also more specific than the generic `on("*")` handler, and the `on("threads")` handler,
  .on("threads:read", ({ user }) => {
    // Since we are reading (and not creating) a thread,
    // we don't need to set metadata. We just need to
    // return a filter to ensure users can only see their own threads.
    return { owner: user.identity };
  })

  // Run creation, streaming, updates, etc.
  // This takes precedence over the generic `on("*")` handler and the `on("threads")` handler
  .on("threads:create_run", ({ value, user }) => {
    value.metadata ??= {};
    value.metadata.owner = user.identity;

    return { owner: user.identity };
  })

  // Assistant creation. This will match only on assistant create actions.
  // Since this is **more specific** than both the generic `on("*")` handler and the `on("assistants")` handler, it will take precedence for any "create" actions on the "assistants" resources
  .on("assistants:create", ({ value, user, permissions }) => {
    if (!permissions.includes("assistants:create")) {
      throw new HTTPException(403, {
        message: "User lacks the required permissions.",
      });
    }

    // Setting metadata on the assistant being created will ensure that the resource contains an "owner" field.
    // Then any time a user tries to access this assistant, we can filter by owner
    value.metadata ??= {};
    value.metadata.owner = user.identity;

    return { owner: user.identity };
  });

请注意,在上面的示例中,我们混合了全局和资源特定的处理器。由于每个请求由最具体的处理器处理,因此创建 thread 的请求将匹配 on_thread_create 处理器,但不会匹配 reject_unhandled_requests 处理器。但是,更新线程的请求将由全局处理器处理,因为我们没有用于该资源和操作的更具体的处理器。

过滤器操作

授权处理器可以返回不同类型的值:

  • NoneTrue 表示"授权访问所有底层资源"
  • False 表示"拒绝访问所有底层资源(引发 403 异常)"
  • 元数据过滤器字典将限制对资源的访问

过滤器字典是一个字典,其键与资源元数据匹配。它支持三个运算符:

  • 默认值是精确匹配的简写,或下面的 "$eq"。例如,{"owner": user_id} 将仅包括包含 {"owner": user_id} 的元数据的资源
  • $eq:精确匹配(例如 {"owner": {"$eq": user_id}})- 这等效于上面的简写 {"owner": user_id}
  • $contains:列表成员资格(例如 {"allowed_users": {"$contains": user_id}})此处的值必须是列表的元素。存储资源中的元数据必须是列表/容器类型。

具有多个键的字典使用逻辑 AND 过滤器处理。例如,{"owner": org_id, "allowed_users": {"$contains": user_id}} 将仅匹配其 "owner" 为 org_id 且其 "allowed_users" 列表包含 user_id 的元数据的资源。 有关更多信息,请参阅此处的参考。

授权处理器可以返回不同类型的值:

  • nulltrue 表示"授权访问所有底层资源"
  • false 表示"拒绝访问所有底层资源(引发 403 异常)"
  • 元数据过滤器对象将限制对资源的访问

过滤器对象是一个对象,其键与资源元数据匹配。它支持三个运算符:

  • 默认值是精确匹配的简写,或下面的 "$eq"。例如,{ owner: userId} 将仅包括包含 { owner: userId } 的元数据的资源
  • $eq:精确匹配(例如 { owner: { $eq: userId } })- 这等效于上面的简写 { owner: userId }
  • $contains:列表成员资格(例如 { allowedUsers: { $contains: userId} })此处的值必须是列表的元素。存储资源中的元数据必须是列表/容器类型。

具有多个键的对象使用逻辑 AND 过滤器处理。例如,{ owner: orgId, allowedUsers: { $contains: userId} } 将仅匹配其 "owner" 为 orgId 且其 "allowedUsers" 列表包含 userId 的元数据的资源。 有关更多信息,请参阅此处的参考。

常见访问模式

以下是一些典型的授权模式:

单所有者资源

这种常见模式让你将所有线程、助手、定时任务和运行范围限定到单个用户。它对于常见的单用户用例(如常规聊天机器人式应用程序)很有用。

@auth.on
async def owner_only(ctx: Auth.types.AuthContext, value: dict):
    metadata = value.setdefault("metadata", {})
    metadata["owner"] = ctx.user.identity
    return {"owner": ctx.user.identity}
export const auth = new Auth()
  .authenticate(async (request: Request) => ({
    identity: "user-123",
    permissions: ["threads:write", "threads:read"],
  }))
  .on("*", ({ value, user }) => {
    if ("metadata" in value) {
      value.metadata ??= {};
      value.metadata.owner = user.identity;
    }
    return { owner: user.identity };
  });

基于权限的访问

此模式让你根据**权限**控制访问。如果你希望某些角色对资源具有更广泛或更受限制的访问权限,这很有用。

# In your auth handler:
@auth.authenticate
async def authenticate(headers: dict) -> Auth.types.MinimalUserDict:
    ...
    return {
        "identity": "user-123",
        "is_authenticated": True,
        "permissions": ["threads:write", "threads:read"]  # Define permissions in auth
    }

def _default(ctx: Auth.types.AuthContext, value: dict):
    metadata = value.setdefault("metadata", {})
    metadata["owner"] = ctx.user.identity
    return {"owner": ctx.user.identity}

@auth.on.threads.create
async def create_thread(ctx: Auth.types.AuthContext, value: dict):
    if "threads:write" not in ctx.permissions:
        raise Auth.exceptions.HTTPException(
            status_code=403,
            detail="Unauthorized"
        )
    return _default(ctx, value)


@auth.on.threads.read
async def rbac_create(ctx: Auth.types.AuthContext, value: dict):
    if "threads:read" not in ctx.permissions and "threads:write" not in ctx.permissions:
        raise Auth.exceptions.HTTPException(
            status_code=403,
            detail="Unauthorized"
        )
    return _default(ctx, value)
import { Auth, HTTPException } from "@langchain/langgraph-sdk/auth";

export const auth = new Auth()
  .authenticate(async (request: Request) => ({
    identity: "user-123",
    // Define permissions in auth
    permissions: ["threads:write", "threads:read"],
  }))
  .on("threads:create", ({ value, user, permissions }) => {
    if (!permissions.includes("threads:write")) {
      throw new HTTPException(403, { message: "Unauthorized" });
    }

    if ("metadata" in value) {
      value.metadata ??= {};
      value.metadata.owner = user.identity;
    }
    return { owner: user.identity };
  })
  .on("threads:read", ({ user, permissions }) => {
    if (
      !permissions.includes("threads:read") &&
      !permissions.includes("threads:write")
    ) {
      throw new HTTPException(403, { message: "Unauthorized" });
    }

    return { owner: user.identity };
  });

支持的资源

LangGraph 提供三个级别的授权处理器,从最通用到最具体:

  1. 全局处理器@auth.on):匹配所有资源和操作
  2. 资源处理器(例如 @auth.on.threads@auth.on.assistants@auth.on.crons):匹配特定资源的所有操作
  3. 操作处理器(例如 @auth.on.threads.create@auth.on.threads.read):匹配特定资源上的特定操作

将使用最具体的匹配处理器。例如,@auth.on.threads.create 在线程创建时优先于 @auth.on.threads。 如果注册了更具体的处理器,则不会为该资源和操作调用更通用的处理器。

  1. 全局处理器on("*")):匹配所有资源和操作
  2. 资源处理器(例如 on("threads")on("assistants")on("crons")):匹配特定资源的所有操作
  3. 操作处理器(例如 on("threads:create")on("threads:read")):匹配特定资源上的特定操作

将使用最具体的匹配处理器。例如,on("threads:create") 在线程创建时优先于 on("threads")。 如果注册了更具体的处理器,则不会为该资源和操作调用更通用的处理器。

类型安全

每个处理器都有可用于其 value 参数的类型提示。例如:

```python
@auth.on.threads.create
async def on_thread_create(
    ctx: Auth.types.AuthContext,
    value: Auth.types.on.threads.create.value  # Specific type for thread creation
):
    ...

@auth.on.threads
async def on_threads(
    ctx: Auth.types.AuthContext,
    value: Auth.types.on.threads.value  # Union type of all thread actions
):
    ...

@auth.on
async def on_all(
    ctx: Auth.types.AuthContext,
    value: dict  # Union type of all possible actions
):
    ...
```

更具体的处理器提供更好的类型提示,因为它们处理更少的操作类型。

支持的操作和类型

以下是所有支持的操作处理器:

资源 处理器 描述 值类型
Threads @auth.on.threads.create 线程创建 ThreadsCreate
@auth.on.threads.read 线程检索 ThreadsRead
@auth.on.threads.update 线程更新 ThreadsUpdate
@auth.on.threads.delete 线程删除 ThreadsDelete
@auth.on.threads.search 列出线程 ThreadsSearch
@auth.on.threads.create_run 创建或更新运行 RunsCreate
Assistants @auth.on.assistants.create 助手创建 AssistantsCreate
@auth.on.assistants.read 助手检索 AssistantsRead
@auth.on.assistants.update 助手更新 AssistantsUpdate
@auth.on.assistants.delete 助手删除 AssistantsDelete
@auth.on.assistants.search 列出助手 AssistantsSearch
Crons @auth.on.crons.create 定时任务创建 CronsCreate
@auth.on.crons.read 定时任务检索 CronsRead
@auth.on.crons.update 定时任务更新 CronsUpdate
@auth.on.crons.delete 定时任务删除 CronsDelete
@auth.on.crons.search 列出定时任务 CronsSearch
资源 事件 描述 值类型
Threads threads:create 线程创建 ThreadsCreate
threads:read 线程检索 ThreadsRead
threads:update 线程更新 ThreadsUpdate
threads:delete 线程删除 ThreadsDelete
threads:search 列出线程 ThreadsSearch
threads:create_run 创建或更新运行 RunsCreate
Assistants assistants:create 助手创建 AssistantsCreate
assistants:read 助手检索 AssistantsRead
assistants:update 助手更新 AssistantsUpdate
assistants:delete 助手删除 AssistantsDelete
assistants:search 列出助手 AssistantsSearch
Crons crons:create 定时任务创建 CronsCreate
crons:read 定时任务检索 CronsRead
crons:update 定时任务更新 CronsUpdate
crons:delete 定时任务删除 CronsDelete
crons:search 列出定时任务 CronsSearch
关于运行

运行的访问控制范围限定为其父线程。这意味着权限通常从线程继承,反映了数据模型的对话性质。除创建外的所有运行操作(读取、列出)都由线程的处理器控制。

有一个特定的 create_run 处理器用于创建新运行,因为它有更多参数,你可以在处理器中查看。

有一个特定的 threads:create_run 处理器用于创建新运行,因为它有更多参数,你可以在处理器中查看。

下一步

有关实现详细信息: