# Authenticate Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/authenticate https://api.host.langchain.com/openapi.json post /v2/auth/authenticate Get OAuth token or start authentication flow if needed. # Check Oauth Token Exists Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/check-oauth-token-exists https://api.host.langchain.com/openapi.json get /v2/auth/tokens/exists Return whether the current user has any tokens for a given provider (across agents). # Check Workspace Slack Tokens Exist Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/check-workspace-slack-tokens-exist https://api.host.langchain.com/openapi.json get /v2/auth/tokens/workspace/slack/exists Check if the workspace has any Slack tokens. # Create Mcp Oauth Provider Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/create-mcp-oauth-provider https://api.host.langchain.com/openapi.json post /v2/auth/providers/mcp-discover Create an OAuth provider via MCP auto-discovery. # Create Oauth Provider Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/create-oauth-provider https://api.host.langchain.com/openapi.json post /v2/auth/providers Create a new OAuth provider manually. # Delete Oauth Provider Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/delete-oauth-provider https://api.host.langchain.com/openapi.json delete /v2/auth/providers/{provider_id} Delete an OAuth provider. # Delete Oauth Tokens For User Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/delete-oauth-tokens-for-user https://api.host.langchain.com/openapi.json delete /v2/auth/tokens Delete all tokens for the current user for the given provider (across agents). # Get Oauth Provider Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/get-oauth-provider https://api.host.langchain.com/openapi.json get /v2/auth/providers/{provider_id} Get a specific OAuth provider. # List Oauth Providers Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/list-oauth-providers https://api.host.langchain.com/openapi.json get /v2/auth/providers List OAuth providers. # Oauth Callback Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/oauth-callback https://api.host.langchain.com/openapi.json post /v2/auth/callback/{provider_id} # Oauth Callback Get Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/oauth-callback-get https://api.host.langchain.com/openapi.json get /v2/auth/callback/{provider_id} Handle OAuth callback redirect from OAuth providers. Processes the OAuth token exchange, then redirects to the frontend callback page for a consistent UI experience. # Oauth Setup Callback Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/oauth-setup-callback https://api.host.langchain.com/openapi.json get /v2/auth/setup/{provider_id} Handle OAuth setup callback redirect from GitHub Apps. This endpoint handles the "Setup URL" callback from GitHub Apps, which is triggered when a user installs or updates their GitHub App installation. For "update" actions (user modified repo access via GitHub), we just show a success page since no token exchange is needed. For new installations with code/state, we process similar to the regular OAuth callback. # Revoke All Slack Tokens For Workspace Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/revoke-all-slack-tokens-for-workspace https://api.host.langchain.com/openapi.json delete /v2/auth/tokens/workspace/slack Revoke ALL Slack tokens for the workspace. Admin-only action that disconnects Slack entirely. This is a destructive operation that: - Revokes all Slack tokens on Slack's side for all users in the workspace - Deletes all Slack tokens from the database # Update Oauth Provider Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/update-oauth-provider https://api.host.langchain.com/openapi.json patch /v2/auth/providers/{provider_id} Update an OAuth provider. # Wait For Auth Completion Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/auth-service-v2/wait-for-auth-completion https://api.host.langchain.com/openapi.json get /v2/auth/wait/{auth_id} Wait for OAuth authentication completion. # Create Deployment Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/deployments-v2/create-deployment https://api.host.langchain.com/openapi.json post /v2/deployments Create a new deployment. # Delete Deployment Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/deployments-v2/delete-deployment https://api.host.langchain.com/openapi.json delete /v2/deployments/{deployment_id} Delete a deployment by ID. # Delete Deployments Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/deployments-v2/delete-deployments https://api.host.langchain.com/openapi.json delete /v2/deployments Delete multiple deployments with partial success support. Returns: - 200: All deployments deleted successfully - 207: Some deployments deleted successfully, some failed # Get Deployment Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/deployments-v2/get-deployment https://api.host.langchain.com/openapi.json get /v2/deployments/{deployment_id} Get a deployment by ID. # Get Revision Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/deployments-v2/get-revision https://api.host.langchain.com/openapi.json get /v2/deployments/{deployment_id}/revisions/{revision_id} Get a revision by ID for a deployment. # List Deployments Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/deployments-v2/list-deployments https://api.host.langchain.com/openapi.json get /v2/deployments List all deployments. # List Revisions Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/deployments-v2/list-revisions https://api.host.langchain.com/openapi.json get /v2/deployments/{deployment_id}/revisions List all revisions for a deployment. # Patch Deployment Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/deployments-v2/patch-deployment https://api.host.langchain.com/openapi.json patch /v2/deployments/{deployment_id} Patch a deployment by ID. # Redeploy Revision Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/deployments-v2/redeploy-revision https://api.host.langchain.com/openapi.json post /v2/deployments/{deployment_id}/revisions/{revision_id}/redeploy Redeploy a specific revision ID. # List GitHub Integrations Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/integrations-v1/list-github-integrations https://api.host.langchain.com/openapi.json get /v1/integrations/github/install List available GitHub integrations for LangGraph Platfom Cloud SaaS. # List GitHub Repositories Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/integrations-v1/list-github-repositories https://api.host.langchain.com/openapi.json get /v1/integrations/github/{integration_id}/repos List available GitHub repositories for an integration that are available to deploy to LangSmith Deployment. # Create Listener Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/listeners-v2/create-listener https://api.host.langchain.com/openapi.json post /v2/listeners Create a listener.

Creating a listener is only allowed for LangSmith organizations with self-hosted enterprise plans. # Delete Listener Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/listeners-v2/delete-listener https://api.host.langchain.com/openapi.json delete /v2/listeners/{listener_id} Delete a listener by ID. # Get Listener Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/listeners-v2/get-listener https://api.host.langchain.com/openapi.json get /v2/listeners/{listener_id} Get a listener by ID. # List Listeners Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/listeners-v2/list-listeners https://api.host.langchain.com/openapi.json get /v2/listeners List all listeners. # Patch Listener Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/listeners-v2/patch-listener https://api.host.langchain.com/openapi.json patch /v2/listeners/{listener_id} Patch a listener by ID. # Create a Sandbox Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/create-a-sandbox https://api.host.langchain.com/openapi.json post /v2/sandboxes/boxes Create a new SandboxClaim in tenant's namespace. If wait_for_ready is True (default), this will block until the sandbox is ready or the timeout is reached. The sandbox creation can fail for several reasons: - Image pull errors (invalid image, registry auth issues) - Container crashes (bad entrypoint, missing dependencies, health check failures) - Scheduling failures (no suitable nodes available) Sandbox creation is subject to quota limits (count, CPU, memory) configured via Metronome org config. On failure, the claim is automatically cleaned up and a descriptive error is returned. # Create a Sandbox Pool Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/create-a-sandbox-pool https://api.host.langchain.com/openapi.json post /v2/sandboxes/pools Create a new Sandbox Pool in tenant's namespace. Pools pre-provision sandboxes from a template for faster claim binding. Requirements: - The referenced template must exist - The template must not have any volume mounts (volumes are stateful) Pool creation is subject to quota limits. The total resource usage (replicas * per-replica resources) is checked against the organization's quota limits. # Create a SandboxTemplate Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/create-a-sandboxtemplate https://api.host.langchain.com/openapi.json post /v2/sandboxes/templates Create a new SandboxTemplate in tenant's namespace. # Create a Volume Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/create-a-volume https://api.host.langchain.com/openapi.json post /v2/sandboxes/volumes Create a new persistent volume in the tenant's sandbox namespace. This creates both a PersistentVolume (PV) and PersistentVolumeClaim (PVC). The volume can then be referenced in sandbox templates. Volume creation is subject to quota limits (count and total storage) configured via Metronome org config. If wait_for_ready is True (default), this blocks until the PVC is bound or the timeout is reached. # Delete a Registry Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/delete-a-registry https://api.host.langchain.com/openapi.json delete /v2/sandboxes/registries/{name} Delete a private container registry. This will fail if any templates reference this registry. Delete or update those templates first before deleting the registry. # Delete a Sandbox Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/delete-a-sandbox https://api.host.langchain.com/openapi.json delete /v2/sandboxes/boxes/{name} Delete a SandboxClaim from tenant's namespace. # Delete a Sandbox Pool Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/delete-a-sandbox-pool https://api.host.langchain.com/openapi.json delete /v2/sandboxes/pools/{name} Delete a Sandbox Pool from tenant's namespace. This will terminate all sandboxes in the pool. # Delete a SandboxTemplate Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/delete-a-sandboxtemplate https://api.host.langchain.com/openapi.json delete /v2/sandboxes/templates/{name} Delete a SandboxTemplate from tenant's namespace. Deletion will fail if the template is in use by any sandboxes or pools. # Delete a Volume Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/delete-a-volume https://api.host.langchain.com/openapi.json delete /v2/sandboxes/volumes/{name} Delete a persistent volume (both PV and PVC) from tenant's namespace. This will fail if any templates reference this volume. Delete or update those templates first before deleting the volume. # Get a Registry Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/get-a-registry https://api.host.langchain.com/openapi.json get /v2/sandboxes/registries/{name} Get a specific registry by name. Returns metadata only -- credentials are never included in responses. # Get a Sandbox Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/get-a-sandbox https://api.host.langchain.com/openapi.json get /v2/sandboxes/boxes/{name} Get a specific Sandbox by name in tenant's namespace. This endpoint queries the database for fast performance. # Get a Sandbox Pool Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/get-a-sandbox-pool https://api.host.langchain.com/openapi.json get /v2/sandboxes/pools/{name} Get a specific Sandbox Pool by name in tenant's namespace. This endpoint queries the database for fast performance. # Get a SandboxTemplate Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/get-a-sandboxtemplate https://api.host.langchain.com/openapi.json get /v2/sandboxes/templates/{name} Get a specific SandboxTemplate by name in tenant's namespace. This endpoint queries the database for fast performance. # Get a Volume Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/get-a-volume https://api.host.langchain.com/openapi.json get /v2/sandboxes/volumes/{name} Get a specific volume by name in the tenant's sandbox namespace. This endpoint queries the database for fast performance. # Get sandbox resource usage and quota limits Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/get-sandbox-resource-usage-and-quota-limits https://api.host.langchain.com/openapi.json get /v2/sandboxes/usage Return current resource consumption and organisation quota limits. Sandbox counts include both direct claims and warmpool replicas. For self-hosted deployments limit fields are 0 (quotas not enforced). # List all Registries Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/list-all-registries https://api.host.langchain.com/openapi.json get /v2/sandboxes/registries List all registered private container registries for the tenant. Returns metadata only -- credentials are never included in responses. Supports optional pagination via `limit` and `offset` query parameters. # List all Sandbox Pools Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/list-all-sandbox-pools https://api.host.langchain.com/openapi.json get /v2/sandboxes/pools List all Sandbox Pools in the tenant's namespace. This endpoint queries the database for fast performance. Supports optional pagination via `limit` and `offset` query parameters. # List all Sandboxes Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/list-all-sandboxes https://api.host.langchain.com/openapi.json get /v2/sandboxes/boxes List all Sandboxes in the tenant's namespace. This endpoint queries the database for fast performance. Supports optional pagination via `limit` and `offset` query parameters. # List all SandboxTemplates Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/list-all-sandboxtemplates https://api.host.langchain.com/openapi.json get /v2/sandboxes/templates List all SandboxTemplates in the tenant's sandbox namespace. This endpoint queries the database for fast performance. Supports optional pagination via `limit` and `offset` query parameters. # List all Volumes Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/list-all-volumes https://api.host.langchain.com/openapi.json get /v2/sandboxes/volumes List all persistent volumes in the tenant's sandbox namespace. This endpoint queries the database for fast performance. Supports optional pagination via `limit` and `offset` query parameters. # Register a Private Container Registry Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/register-a-private-container-registry https://api.host.langchain.com/openapi.json post /v2/sandboxes/registries Register a private container registry for pulling sandbox images. Provide the registry URL, username, and password (or access token). The backend builds the K8s dockerconfigjson secret internally. The registry can then be referenced in sandbox templates via the `registry_name` field to pull images from private registries. # Update a Registry Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/update-a-registry https://api.host.langchain.com/openapi.json patch /v2/sandboxes/registries/{name} Update a registry's display name and/or credentials. You can update: - **name**: New display name (must be unique within the organization) - **url**, **username**, **password**: New credentials (all three must be provided together) # Update a Sandbox Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/update-a-sandbox https://api.host.langchain.com/openapi.json patch /v2/sandboxes/boxes/{name} Update a Sandbox's display name. Currently only the display name can be updated. # Update a Sandbox Pool Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/update-a-sandbox-pool https://api.host.langchain.com/openapi.json patch /v2/sandboxes/pools/{name} Update a Sandbox Pool's display name and/or replica count. You can update: - **name**: New display name (must be unique within the organization) - **replicas**: New replica count (scaling up is subject to quota limits) The template reference cannot be changed after creation. Set replicas to 0 to pause the pool without deleting it. # Update a SandboxTemplate Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/update-a-sandboxtemplate https://api.host.langchain.com/openapi.json patch /v2/sandboxes/templates/{name} Update a SandboxTemplate's display name. Currently only the display name can be updated. The image, resources, and volume mounts cannot be changed after creation. # Update a Volume Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/api-reference/sandboxes-v2/update-a-volume https://api.host.langchain.com/openapi.json patch /v2/sandboxes/volumes/{name} Update a volume's display name and/or storage size. You can update: - **name**: New display name (must be unique within the organization) - **size**: New storage size (only increases allowed, cannot decrease) The storage increase is subject to quota limits configured via Metronome org config. # null Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/index

Documentation

LangChain is the platform for agent engineering. AI teams at Replit, Clay, Rippling, Cloudflare, Workday, and more trust LangChain's products to engineer reliable agents.

LangSmith

[**LangSmith**](/langsmith/home) is a platform that helps AI teams use live production data for continuous testing and improvement. LangSmith provides: See exactly how your agent thinks and acts with detailed tracing and aggregate trend metrics. Test and score agent behavior on production data or offline datasets to continuously improve performance. Iterate on prompts with version control, prompt optimization, and collaboration features. Ship your agent in one click, using scalable infrastructure built for long-running tasks. LangSmith meets the highest standards of data security and privacy with HIPAA, SOC 2 Type 2, and GDPR compliance. For more information, see the [Trust Center](https://trust.langchain.com/).

LangSmith Agent Builder

Create helpful AI agents without code. Start from a template, connect your accounts, and let the agent handle routine work while you stay in control.

Open source agent frameworks

Quickly build agents that can tackle any task. Customize the building blocks of your agents. Control every step of your custom agent with low-level orchestration, memory, and human-in-the-loop support. Quickly build agents that can tackle any task. Customize the building blocks of your agents. Control every step of your custom agent with low-level orchestration, memory, and human-in-the-loop support.

Get started

Additional resources

Ask questions, share solutions, and discuss best practices. Connect with other builders and get quick help. Submit tickets and track support requests. Real-time status of LangSmith services and APIs.
*** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/index.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Attribute-based access control Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/abac This reference explains LangSmith's Attribute-Based Access Control (ABAC) system, which enables fine-grained access control based on resource attributes, complementing [RBAC](/langsmith/rbac). For automated user provisioning into roles, see [SCIM](/langsmith/user-management#set-up-scim-for-your-organization). ABAC complements [Role-Based Access Control (RBAC)](/langsmith/rbac) by adding tag-based conditions to access decisions. While RBAC grants blanket permissions based on a user's role (e.g., "can read all projects"), ABAC lets you restrict or grant access based on resource tags (e.g., "can only read projects tagged with Environment=Development"). ABAC (Attribute-Based Access Control) is an Enterprise feature in private beta. If you are interested in upgrading to Enterprise, [contact our sales team](https://www.langchain.com/contact-sales). Roles and resource tags can be managed via the UI or API. ABAC policies are currently only configurable via the [API](https://api.smith.langchain.com/docs#/access_policies). ## Before you begin * [Set up resource tags](/langsmith/set-up-resource-tags) in your workspace. * ABAC currently only supports `resource_tag_key` as an `attribute_name` in policies, for evaluating against resource tags. No other attributes are supported yet. ## Access policy structure An access policy defines conditions under which access is granted or denied. Here's the structure: ```json theme={null} { "name": "Policy Name", "description": "Optional description", "effect": "allow | deny", "condition_groups": [ { "permission": "projects:read", "resource_type": "project", "conditions": [ { "attribute_name": "resource_tag_key", "attribute_key": "Environment", "operator": "equals", "attribute_value": "Production" } ] } ], "role_ids": [""] } ``` ### Effect The `effect` determines what happens when conditions match: * **`allow`** - Grant access when conditions match * **`deny`** - Block access when conditions match Deny policies always take precedence. If both an allow and deny policy match, access is denied. ### Condition groups The `condition_groups` array contains one or more condition groups. Multiple condition groups are evaluated with **OR logic** - if any group matches, the policy applies. Each condition group specifies: * **`permission`** - The permission this group applies to * **`resource_type`** - The resource type to match * **`conditions`** - Array of conditions (evaluated with **AND logic** within the group) #### Resource types and permissions | Resource type | Supported permissions | | ------------- | ----------------------------------------------------------------------- | | `project` | `projects:read`, `runs:read` | | `prompt` | `prompts:read`, `prompts:update`, `prompts:delete` | | `dataset` | `datasets:read`, `datasets:update`, `datasets:delete`, `datasets:share` | Runs don't have their own tags. Run permissions (`runs:read`) are evaluated against the parent project's tags. #### Conditions Each condition in the `conditions` array specifies: * **`attribute_name`** - Currently only `resource_tag_key` is supported * **`attribute_key`** - The tag key to match (e.g., `Environment`, `Team`) * **`operator`** - The comparison operator * **`attribute_value`** - The value to compare against ##### Operators | Operator | Description | | ------------------------ | ------------------------------------------------ | | `equals` | Exact match (case sensitive) | | `not_equals` | Values differ (case sensitive) | | `equals_ignore_case` | Exact match (case insensitive) | | `not_equals_ignore_case` | Values differ (case insensitive) | | `matches` | Glob pattern matching with `*` and `?` wildcards | | `not_matches` | Match when value doesn't match glob pattern | ##### `_if_exists` variants Each operator has an `_if_exists` variant that matches by default when the tag key is absent, or evaluates the condition normally when the tag exists: | Operator | Description | | ---------------------------------- | ----------------------------------------------------------------- | | `equals_if_exists` | Exact match (case sensitive), or if tag key absent | | `not_equals_if_exists` | Values differ (case sensitive), or if tag key absent | | `equals_ignore_case_if_exists` | Exact match (case insensitive), or if tag key absent | | `not_equals_ignore_case_if_exists` | Values differ (case insensitive), or if tag key absent | | `matches_if_exists` | Glob pattern match, or if tag key absent | | `not_matches_if_exists` | Match when value doesn't match glob pattern, or if tag key absent | In an **allow** policy, `_if_exists` variants grant access to resources that either match the condition or don't have the specified tag key. In a **deny** policy, they block resources that either match the condition or don't have the tag key. ### Roles The `role_ids` array specifies which workspace roles the policy applies to. When a user with that role accesses a resource, the policy conditions are evaluated. Policies can be attached to roles when creating the policy, or attached later via the API. ## Managing access policies Access policies are managed via the LangSmith API by [Organization Admins](/langsmith/rbac#organization-admin). Before creating policies, [set up resource tags](/langsmith/set-up-resource-tags) in your workspace. ## How ABAC works with RBAC [RBAC](/langsmith/rbac) permissions and ABAC policies are both considered when determining access to resources: * ABAC **deny** policies override RBAC permissions * ABAC **allow** policies can grant access even without RBAC permissions * If no ABAC policies match, the system falls back to RBAC ### Policy evaluation outcomes **Feature combinations:** | RBAC enabled | ABAC enabled | Behavior | | ------------ | ------------ | --------------------------------------------------- | | ✗ | ✗ | All workspace members have Admin-level access | | ✓ | ✗ | Standard RBAC - access based on role permissions | | ✓ | ✓ | RBAC + ABAC - fine-grained tag-based access control | **When both RBAC and ABAC are enabled:** | RBAC permits | Allow policy matches | Deny policy matches | Result | | ------------ | -------------------- | ------------------- | -------------------------------- | | ✓ | ✓ | ✗ | **Allowed** | | ✓ | ✗ | ✗ | **Allowed** (RBAC fallback) | | ✓ | ✓ | ✓ | **Denied** (deny wins) | | ✓ | ✗ | ✓ | **Denied** (deny wins) | | ✗ | ✓ | ✗ | **Allowed** (ABAC grants access) | | ✗ | ✗ | ✗ | **Denied** | | ✗ | ✓ | ✓ | **Denied** (deny wins) | ## Example scenarios ### 1. Annotator team assignment Allow annotators to only access datasets tagged for their team: ```json theme={null} { "name": "Annotator Team A Access", "effect": "allow", "condition_groups": [{ "permission": "datasets:read", "resource_type": "dataset", "conditions": [{ "attribute_name": "resource_tag_key", "attribute_key": "Annotation-Team", "operator": "equals", "attribute_value": "Team-A" }] }] } ``` ### 2. Block sensitive data Deny access to datasets containing PII. Since deny policies override allow policies, this blocks access even for users with RBAC permissions: ```json theme={null} { "name": "Block PII Datasets", "effect": "deny", "condition_groups": [{ "permission": "datasets:read", "resource_type": "dataset", "conditions": [{ "attribute_name": "resource_tag_key", "attribute_key": "Contains-PII", "operator": "equals", "attribute_value": "true" }] }] } ``` ### 3. Application-based access with wildcards Allow engineers to access projects for any application in the "chatbot" family using glob patterns: ```json theme={null} { "name": "Chatbot Apps Access", "effect": "allow", "condition_groups": [{ "permission": "projects:read", "resource_type": "project", "conditions": [{ "attribute_name": "resource_tag_key", "attribute_key": "Application", "operator": "matches", "attribute_value": "chatbot-*" }] }] } ``` ### 4. Client and purpose isolation (AND logic) Grant access only if both conditions are met - dataset is for training AND belongs to a specific client: ```json theme={null} { "name": "Client Training Data Access", "effect": "allow", "condition_groups": [{ "permission": "datasets:read", "resource_type": "dataset", "conditions": [ { "attribute_name": "resource_tag_key", "attribute_key": "Purpose", "operator": "equals", "attribute_value": "Training" }, { "attribute_name": "resource_tag_key", "attribute_key": "Client", "operator": "equals", "attribute_value": "Acme-Corp" } ] }] } ``` ### 5. Client data plus resources without a `Client` tag using `_if_exists` Consultants don't have RBAC `datasets:read` permission, but this policy grants them access to datasets tagged `Client=Acme-Corp`, as well as datasets that don't have a `Client` tag at all. Datasets tagged with a different client (e.g., `Client=Other-Corp`) remain blocked: ```json theme={null} { "name": "Acme Consultant Access", "effect": "allow", "condition_groups": [{ "permission": "datasets:read", "resource_type": "dataset", "conditions": [{ "attribute_name": "resource_tag_key", "attribute_key": "Client", "operator": "equals_if_exists", "attribute_value": "Acme-Corp" }] }] } ``` ## Troubleshooting **Access unexpectedly denied?** * Check if a deny policy is matching (deny always takes precedence) * Check if the user has RBAC permissions or a matching allow policy * Verify the resource has the expected tag and value * Deny policies with `_if_exists` operators block resources missing that tag key * For case-sensitive operators (`equals`, `not_equals`), check for case mismatches * With multiple conditions in a group, all must match (AND logic) **Access unexpectedly granted?** * Review RBAC permissions (users may have access via their role) * Check if an allow policy is too broad (e.g., using wildcards) * `_if_exists` operators match resources missing that tag key **Policy not taking effect?** * Confirm the policy is attached to the correct role * Verify the user has that role in the workspace * Check that `resource_type` and `permission` match the resource being accessed *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/abac.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Connect an authentication provider Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/add-auth-server In [the last tutorial](/langsmith/resource-auth), you added resource authorization to give users private conversations. However, you are still using hard-coded tokens for authentication, which is not secure. Now you'll replace those tokens with real user accounts using [OAuth2](/langsmith/deployment-quickstart). You'll keep the same [`Auth`](https://reference.langchain.com/python/langsmith/deployment/sdk/#langgraph_sdk.auth.Auth) object and [resource-level access control](/langsmith/auth#single-owner-resources), but upgrade authentication to use Supabase as your identity provider. While Supabase is used in this tutorial, the concepts apply to any OAuth2 provider. You'll learn how to: 1. Replace test tokens with real JWT tokens 2. Integrate with OAuth2 providers for secure user authentication 3. Handle user sessions and metadata while maintaining our existing authorization logic ## Background OAuth2 involves three main roles: 1. **Authorization server**: The identity provider (e.g., Supabase, Auth0, Google) that handles user authentication and issues tokens 2. **Application backend**: Your LangGraph application. This validates tokens and serves protected resources (conversation data) 3. **Client application**: The web or mobile app where users interact with your service A standard OAuth2 flow works something like this: ```mermaid theme={null} sequenceDiagram participant User participant Client participant AuthServer participant Agent Server User->>Client: Initiate login User->>AuthServer: Enter credentials AuthServer->>Client: Send tokens Client->>Agent Server: Request with token Agent Server->>AuthServer: Validate token AuthServer->>Agent Server: Token valid Agent Server->>Client: Serve request (e.g., run agent or graph) ``` ## Prerequisites Before you start this tutorial, ensure you have: * The [bot from the second tutorial](/langsmith/resource-auth) running without errors. * A [Supabase project](https://supabase.com/dashboard) to use its authentication server. ## 1. Install dependencies Install the required dependencies. Start in your `custom-auth` directory and ensure you have the `langgraph-cli` installed: ```bash pip theme={null} cd custom-auth pip install -U "langgraph-cli[inmem]" ``` ```bash uv theme={null} cd custom-auth uv add "langgraph-cli[inmem]" ``` ## 2. Set up the authentication provider Next, fetch the URL of your auth server and the private key for authentication. Since you're using Supabase for this, you can do this in the Supabase dashboard: 1. In the left sidebar, click on t️⚙ Project Settings" and then click "API" 2. Copy your project URL and add it to your `.env` file ```shell theme={null} echo "SUPABASE_URL=your-project-url" >> .env ``` 3. Copy your service role secret key and add it to your `.env` file: ```shell theme={null} echo "SUPABASE_SERVICE_KEY=your-service-role-key" >> .env ``` 4. Copy your "anon public" key and note it down. This will be used later when you set up our client code. ```bash theme={null} SUPABASE_URL=your-project-url SUPABASE_SERVICE_KEY=your-service-role-key ``` ## 3. Implement token validation In the previous tutorials, you used the [`Auth`](https://reference.langchain.com/python/langsmith/deployment/sdk/#langgraph_sdk.auth.Auth) object to [validate hard-coded tokens](/langsmith/set-up-custom-auth) and [add resource ownership](/langsmith/resource-auth). Now you'll upgrade your authentication to validate real JWT tokens from Supabase. The main changes will all be in the [`@auth.authenticate`](https://reference.langchain.com/python/langsmith/deployment/sdk/#langgraph_sdk.auth.Auth.authenticate) decorated function: * Instead of checking against a hard-coded list of tokens, you'll make an HTTP request to Supabase to validate the token. * You'll extract real user information (ID, email) from the validated token. * The existing resource authorization logic remains unchanged. Update `src/security/auth.py` to implement this: ```python {highlight={8-9,20-30}} title="src/security/auth.py" theme={null} import os import httpx from langgraph_sdk import Auth auth = Auth() # This is loaded from the `.env` file you created above SUPABASE_URL = os.environ["SUPABASE_URL"] SUPABASE_SERVICE_KEY = os.environ["SUPABASE_SERVICE_KEY"] @auth.authenticate async def get_current_user(authorization: str | None): """Validate JWT tokens and extract user information.""" assert authorization scheme, token = authorization.split() assert scheme.lower() == "bearer" try: # Verify token with auth provider async with httpx.AsyncClient() as client: response = await client.get( f"{SUPABASE_URL}/auth/v1/user", headers={ "Authorization": authorization, "apiKey": SUPABASE_SERVICE_KEY, }, ) assert response.status_code == 200 user = response.json() return { "identity": user["id"], # Unique user identifier "email": user["email"], "is_authenticated": True, } except Exception as e: raise Auth.exceptions.HTTPException(status_code=401, detail=str(e)) # ... the rest is the same as before # Keep our resource authorization from the previous tutorial @auth.on async def add_owner(ctx, value): """Make resources private to their creator using resource metadata.""" filters = {"owner": ctx.user.identity} metadata = value.setdefault("metadata", {}) metadata.update(filters) return filters ``` The most important change is that we're now validating tokens with a real authentication server. Our authentication handler has the private key for our Supabase project, which we can use to validate the user's token and extract their information. ## 4. Test authentication flow Let's test out the new authentication flow. You can run the following code in a file or notebook. You will need to provide: * A valid email address * A Supabase project URL (from [above](#setup-auth-provider)) * A Supabase anon **public key** (also from [above](#setup-auth-provider)) ```python theme={null} import os import httpx from getpass import getpass from langgraph_sdk import get_client # Get email from command line email = getpass("Enter your email: ") base_email = email.split("@") password = "secure-password" # CHANGEME email1 = f"{base_email[0]}+1@{base_email[1]}" email2 = f"{base_email[0]}+2@{base_email[1]}" SUPABASE_URL = os.environ.get("SUPABASE_URL") if not SUPABASE_URL: SUPABASE_URL = getpass("Enter your Supabase project URL: ") # This is your PUBLIC anon key (which is safe to use client-side) # Do NOT mistake this for the secret service role key SUPABASE_ANON_KEY = os.environ.get("SUPABASE_ANON_KEY") if not SUPABASE_ANON_KEY: SUPABASE_ANON_KEY = getpass("Enter your public Supabase anon key: ") async def sign_up(email: str, password: str): """Create a new user account.""" async with httpx.AsyncClient() as client: response = await client.post( f"{SUPABASE_URL}/auth/v1/signup", json={"email": email, "password": password}, headers={"apiKey": SUPABASE_ANON_KEY}, ) assert response.status_code == 200 return response.json() # Create two test users print(f"Creating test users: {email1} and {email2}") await sign_up(email1, password) await sign_up(email2, password) ``` ⚠️ Before continuing: Check your email and click both confirmation links. Supabase will reject `/login` requests until after you have confirmed your users' email. Now test that users can only see their own data. Make sure the server is running (run `langgraph dev`) before proceeding. The following snippet requires the "anon public" key that you copied from the Supabase dashboard while [setting up the auth provider](#setup-auth-provider) previously. ```python theme={null} async def login(email: str, password: str): """Get an access token for an existing user.""" async with httpx.AsyncClient() as client: response = await client.post( f"{SUPABASE_URL}/auth/v1/token?grant_type=password", json={ "email": email, "password": password }, headers={ "apikey": SUPABASE_ANON_KEY, "Content-Type": "application/json" }, ) assert response.status_code == 200 return response.json()["access_token"] # Log in as user 1 user1_token = await login(email1, password) user1_client = get_client( url="http://localhost:2024", headers={"Authorization": f"Bearer {user1_token}"} ) # Create a thread as user 1 thread = await user1_client.threads.create() print(f"✅ User 1 created thread: {thread['thread_id']}") # Try to access without a token unauthenticated_client = get_client(url="http://localhost:2024") try: await unauthenticated_client.threads.create() print("❌ Unauthenticated access should fail!") except Exception as e: print("✅ Unauthenticated access blocked:", e) # Try to access user 1's thread as user 2 user2_token = await login(email2, password) user2_client = get_client( url="http://localhost:2024", headers={"Authorization": f"Bearer {user2_token}"} ) try: await user2_client.threads.get(thread["thread_id"]) print("❌ User 2 shouldn't see User 1's thread!") except Exception as e: print("✅ User 2 blocked from User 1's thread:", e) ``` The output should look like this: ```shell theme={null} ✅ User 1 created thread: d6af3754-95df-4176-aa10-dbd8dca40f1a ✅ Unauthenticated access blocked: Client error '403 Forbidden' for url 'http://localhost:2024/threads' ✅ User 2 blocked from User 1's thread: Client error '404 Not Found' for url 'http://localhost:2024/threads/d6af3754-95df-4176-aa10-dbd8dca40f1a' ``` Your authentication and authorization are working together: 1. Users must log in to access the bot 2. Each user can only see their own threads All users are managed by the Supabase auth provider, so you don't need to implement any additional user management logic. ## Next steps You've successfully built a production-ready authentication system for your LangGraph application! Let's review what you've accomplished: 1. Set up an authentication provider (Supabase in this case) 2. Added real user accounts with email/password authentication 3. Integrated JWT token validation into your Agent Server 4. Implemented proper authorization to ensure users can only access their own data 5. Created a foundation that's ready to handle your next authentication challenge Now that you have production authentication, consider: 1. Building a web UI with your preferred framework (see the [Custom Auth](https://github.com/langchain-ai/custom-auth) template for an example) 2. Learn more about the other aspects of authentication and authorization in the [conceptual guide on authentication](/langsmith/auth). 3. Customize your handlers and setup further after reading the [reference docs](https://reference.langchain.com/python/langsmith/deployment/sdk/#langgraph_sdk.auth.Auth). *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/add-auth-server.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Human-in-the-loop using server API Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/add-human-in-the-loop To review, edit, and approve tool calls in an agent or workflow, use LangGraph's [human-in-the-loop](/oss/python/langgraph/interrupts) features. ## Dynamic interrupts ```python {highlight={2,34}} theme={null} from langgraph_sdk import get_client from langgraph_sdk.schema import Command client = get_client(url=) # Using the graph deployed with the name "agent" assistant_id = "agent" # create a thread thread = await client.threads.create() thread_id = thread["thread_id"] # Run the graph until the interrupt is hit. result = await client.runs.wait( thread_id, assistant_id, input={"some_text": "original text"} # (1)! ) print(result['__interrupt__']) # (2)! # > [ # > { # > 'value': {'text_to_revise': 'original text'}, # > 'resumable': True, # > 'ns': ['human_node:fc722478-2f21-0578-c572-d9fc4dd07c3b'], # > 'when': 'during' # > } # > ] # Resume the graph print(await client.runs.wait( thread_id, assistant_id, command=Command(resume="Edited text") # (3)! )) # > {'some_text': 'Edited text'} ``` 1. The graph is invoked with some initial state. 2. When the graph hits the interrupt, it returns an interrupt object with the payload and metadata. 3\. The graph is resumed with a `Command(resume=...)`, injecting the human's input and continuing execution. ```javascript {highlight={32}} theme={null} import { Client } from "@langchain/langgraph-sdk"; const client = new Client({ apiUrl: }); // Using the graph deployed with the name "agent" const assistantID = "agent"; // create a thread const thread = await client.threads.create(); const threadID = thread["thread_id"]; // Run the graph until the interrupt is hit. const result = await client.runs.wait( threadID, assistantID, { input: { "some_text": "original text" } } # (1)! ); console.log(result['__interrupt__']); # (2)! // > [ # > { # > 'value': {'text_to_revise': 'original text'}, # > 'resumable': True, # > 'ns': ['human_node:fc722478-2f21-0578-c572-d9fc4dd07c3b'], # > 'when': 'during' # > } # > ] // Resume the graph console.log(await client.runs.wait( threadID, assistantID, { command: { resume: "Edited text" }} # (3)! )); # > {'some_text': 'Edited text'} ``` 1. The graph is invoked with some initial state. 2. When the graph hits the interrupt, it returns an interrupt object with the payload and metadata. 3. The graph is resumed with a `{ resume: ... }` command object, injecting the human's input and continuing execution. Create a thread: ```bash theme={null} curl --request POST \ --url /threads \ --header 'Content-Type: application/json' \ --data '{}' ``` Run the graph until the interrupt is hit.: ```bash theme={null} curl --request POST \ --url /threads//runs/wait \ --header 'Content-Type: application/json' \ --data "{ \"assistant_id\": \"agent\", \"input\": {\"some_text\": \"original text\"} }" ``` Resume the graph: ```bash theme={null} curl --request POST \ --url /threads//runs/wait \ --header 'Content-Type: application/json' \ --data "{ \"assistant_id\": \"agent\", \"command\": { \"resume\": \"Edited text\" } }" ``` This is an example graph you can run in the Agent Server. See [LangSmith quickstart](/langsmith/deployment-quickstart) for more details. ```python {highlight={7,13}} theme={null} from typing import TypedDict import uuid from langgraph.checkpoint.memory import InMemorySaver from langgraph.constants import START from langgraph.graph import StateGraph from langgraph.types import interrupt, Command class State(TypedDict): some_text: str def human_node(state: State): value = interrupt( # (1)! { "text_to_revise": state["some_text"] # (2)! } ) return { "some_text": value # (3)! } # Build the graph graph_builder = StateGraph(State) graph_builder.add_node("human_node", human_node) graph_builder.add_edge(START, "human_node") graph = graph_builder.compile() ``` 1. `interrupt(...)` pauses execution at `human_node`, surfacing the given payload to a human. 2. Any JSON serializable value can be passed to the [`interrupt`](https://reference.langchain.com/python/langgraph/types/#langgraph.types.interrupt) function. Here, a dict containing the text to revise. 3. Once resumed, the return value of `interrupt(...)` is the human-provided input, which is used to update the state. Once you have a running Agent Server, you can interact with it using [LangGraph SDK](/langsmith/langgraph-python-sdk) ```python {highlight={2,34}} theme={null} from langgraph_sdk import get_client from langgraph_sdk.schema import Command client = get_client(url=) # Using the graph deployed with the name "agent" assistant_id = "agent" # create a thread thread = await client.threads.create() thread_id = thread["thread_id"] # Run the graph until the interrupt is hit. result = await client.runs.wait( thread_id, assistant_id, input={"some_text": "original text"} # (1)! ) print(result['__interrupt__']) # (2)! # > [ # > { # > 'value': {'text_to_revise': 'original text'}, # > 'resumable': True, # > 'ns': ['human_node:fc722478-2f21-0578-c572-d9fc4dd07c3b'], # > 'when': 'during' # > } # > ] # Resume the graph print(await client.runs.wait( thread_id, assistant_id, command=Command(resume="Edited text") # (3)! )) # > {'some_text': 'Edited text'} ``` 1. The graph is invoked with some initial state. 2. When the graph hits the interrupt, it returns an interrupt object with the payload and metadata. 3\. The graph is resumed with a `Command(resume=...)`, injecting the human's input and continuing execution. ```javascript {highlight={32}} theme={null} import { Client } from "@langchain/langgraph-sdk"; const client = new Client({ apiUrl: }); // Using the graph deployed with the name "agent" const assistantID = "agent"; // create a thread const thread = await client.threads.create(); const threadID = thread["thread_id"]; // Run the graph until the interrupt is hit. const result = await client.runs.wait( threadID, assistantID, { input: { "some_text": "original text" } } # (1)! ); console.log(result['__interrupt__']); # (2)! # > [ # > { # > 'value': {'text_to_revise': 'original text'}, # > 'resumable': True, # > 'ns': ['human_node:fc722478-2f21-0578-c572-d9fc4dd07c3b'], # > 'when': 'during' # > } # > ] // Resume the graph console.log(await client.runs.wait( threadID, assistantID, { command: { resume: "Edited text" }} # (3)! )); # > {'some_text': 'Edited text'} ``` 1. The graph is invoked with some initial state. 2. When the graph hits the interrupt, it returns an interrupt object with the payload and metadata. 3. The graph is resumed with a `{ resume: ... }` command object, injecting the human's input and continuing execution. Create a thread: ```bash theme={null} curl --request POST \ --url /threads \ --header 'Content-Type: application/json' \ --data '{}' ``` Run the graph until the interrupt is hit: ```bash theme={null} curl --request POST \ --url /threads//runs/wait \ --header 'Content-Type: application/json' \ --data "{ \"assistant_id\": \"agent\", \"input\": {\"some_text\": \"original text\"} }" ``` Resume the graph: ```bash theme={null} curl --request POST \ --url /threads//runs/wait \ --header 'Content-Type: application/json' \ --data "{ \"assistant_id\": \"agent\", \"command\": { \"resume\": \"Edited text\" } }" ``` ## Static interrupts Static interrupts (also known as static breakpoints) are triggered either before or after a node executes. Static interrupts are **not** recommended for human-in-the-loop workflows. They are best used for debugging and testing. You can set static interrupts by specifying `interrupt_before` and `interrupt_after` at compile time: ```python {highlight={1,2,3}} theme={null} graph = graph_builder.compile( # (1)! interrupt_before=["node_a"], # (2)! interrupt_after=["node_b", "node_c"], # (3)! ) ``` 1. The breakpoints are set during `compile` time. 2. `interrupt_before` specifies the nodes where execution should pause before the node is executed. 3. `interrupt_after` specifies the nodes where execution should pause after the node is executed. Alternatively, you can set static interrupts at run time: ```python {highlight={1,5,6}} theme={null} await client.runs.wait( # (1)! thread_id, assistant_id, inputs=inputs, interrupt_before=["node_a"], # (2)! interrupt_after=["node_b", "node_c"] # (3)! ) ``` 1. `client.runs.wait` is called with the `interrupt_before` and `interrupt_after` parameters. This is a run-time configuration and can be changed for every invocation. 2. `interrupt_before` specifies the nodes where execution should pause before the node is executed. 3. `interrupt_after` specifies the nodes where execution should pause after the node is executed. ```javascript {highlight={1,6,7}} theme={null} await client.runs.wait( // (1)! threadID, assistantID, { input: input, interruptBefore: ["node_a"], // (2)! interruptAfter: ["node_b", "node_c"] // (3)! } ) ``` 1. `client.runs.wait` is called with the `interruptBefore` and `interruptAfter` parameters. This is a run-time configuration and can be changed for every invocation. 2. `interruptBefore` specifies the nodes where execution should pause before the node is executed. 3. `interruptAfter` specifies the nodes where execution should pause after the node is executed. ```bash theme={null} curl --request POST \ --url /threads//runs/wait \ --header 'Content-Type: application/json' \ --data "{ \"assistant_id\": \"agent\", \"interrupt_before\": [\"node_a\"], \"interrupt_after\": [\"node_b\", \"node_c\"], \"input\": }" ``` The following example shows how to add static interrupts: ```python theme={null} from langgraph_sdk import get_client client = get_client(url=) # Using the graph deployed with the name "agent" assistant_id = "agent" # create a thread thread = await client.threads.create() thread_id = thread["thread_id"] # Run the graph until the breakpoint result = await client.runs.wait( thread_id, assistant_id, input=inputs # (1)! ) # Resume the graph await client.runs.wait( thread_id, assistant_id, input=None # (2)! ) ``` 1. The graph is run until the first breakpoint is hit. 2. The graph is resumed by passing in `None` for the input. This will run the graph until the next breakpoint is hit. ```js theme={null} import { Client } from "@langchain/langgraph-sdk"; const client = new Client({ apiUrl: }); // Using the graph deployed with the name "agent" const assistantID = "agent"; // create a thread const thread = await client.threads.create(); const threadID = thread["thread_id"]; // Run the graph until the breakpoint const result = await client.runs.wait( threadID, assistantID, { input: input } # (1)! ); // Resume the graph await client.runs.wait( threadID, assistantID, { input: null } # (2)! ); ``` 1. The graph is run until the first breakpoint is hit. 2. The graph is resumed by passing in `null` for the input. This will run the graph until the next breakpoint is hit. Create a thread: ```bash theme={null} curl --request POST \ --url /threads \ --header 'Content-Type: application/json' \ --data '{}' ``` Run the graph until the breakpoint: ```bash theme={null} curl --request POST \ --url /threads//runs/wait \ --header 'Content-Type: application/json' \ --data "{ \"assistant_id\": \"agent\", \"input\": }" ``` Resume the graph: ```bash theme={null} curl --request POST \ --url /threads//runs/wait \ --header 'Content-Type: application/json' \ --data "{ \"assistant_id\": \"agent\" }" ``` ## Learn more * [Human-in-the-loop conceptual guide](/oss/python/langgraph/interrupts): learn more about LangGraph human-in-the-loop features. * [Common patterns](/oss/python/langgraph/interrupts#common-patterns): learn how to implement patterns like approving/rejecting actions, requesting user input, tool call review, and validating human input. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/add-human-in-the-loop.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Add metadata and tags to traces Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/add-metadata-tags LangSmith supports sending arbitrary metadata and tags along with traces. Tags are strings that can be used to categorize or label a trace. Metadata is a dictionary of key-value pairs that can be used to store additional information about a trace. Both are useful for associating additional information with a trace, such as the environment in which it was executed, the user who initiated it, or an internal correlation ID. For more information on tags and metadata, see the [Concepts](/langsmith/observability-concepts#tags) page. For information on how to query traces and runs by metadata and tags, see the [Filter traces in the application](/langsmith/filter-traces-in-application) page. ```python Python theme={null} import openai import langsmith as ls from langsmith.wrappers import wrap_openai client = openai.Client() messages = [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Hello!"} ] # You can set metadata & tags **statically** when decorating a function # Use the @traceable decorator with tags and metadata # Ensure that the LANGSMITH_TRACING environment variables are set for @traceable to work @ls.traceable( run_type="llm", name="OpenAI Call Decorator", tags=["my-tag"], metadata={"my-key": "my-value"} ) def call_openai( messages: list[dict], model: str = "gpt-4.1-mini" ) -> str: # You can also dynamically set metadata on the parent run: rt = ls.get_current_run_tree() rt.metadata["some-conditional-key"] = "some-val" rt.tags.extend(["another-tag"]) return client.chat.completions.create( model=model, messages=messages, ).choices[0].message.content call_openai( messages, # To add at **invocation time**, when calling the function. # via the langsmith_extra parameter langsmith_extra={"tags": ["my-other-tag"], "metadata": {"my-other-key": "my-value"}} ) # Alternatively, you can use the context manager with ls.trace( name="OpenAI Call Trace", run_type="llm", inputs={"messages": messages}, tags=["my-tag"], metadata={"my-key": "my-value"}, ) as rt: chat_completion = client.chat.completions.create( model="gpt-4.1-mini", messages=messages, ) rt.metadata["some-conditional-key"] = "some-val" rt.end(outputs={"output": chat_completion}) # You can use the same techniques with the wrapped client patched_client = wrap_openai( client, tracing_extra={"metadata": {"my-key": "my-value"}, "tags": ["a-tag"]} ) chat_completion = patched_client.chat.completions.create( model="gpt-4.1-mini", messages=messages, langsmith_extra={ "tags": ["my-other-tag"], "metadata": {"my-other-key": "my-value"}, }, ) ``` ```typescript TypeScript theme={null} import OpenAI from "openai"; import { traceable, getCurrentRunTree } from "langsmith/traceable"; import { wrapOpenAI } from "langsmith/wrappers"; const client = wrapOpenAI(new OpenAI()); const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [ { role: "system", content: "You are a helpful assistant." }, { role: "user", content: "Hello!" }, ]; const traceableCallOpenAI = traceable( async (messages: OpenAI.Chat.ChatCompletionMessageParam[]) => { const completion = await client.chat.completions.create({ model: "gpt-4.1-mini", messages, }); const runTree = getCurrentRunTree(); runTree.extra.metadata = { ...runTree.extra.metadata, someKey: "someValue", }; runTree.tags = [...(runTree.tags ?? []), "runtime-tag"]; return completion.choices[0].message.content; }, { run_type: "llm", name: "OpenAI Call Traceable", tags: ["my-tag"], metadata: { "my-key": "my-value" }, } ); // Call the traceable function await traceableCallOpenAI(messages); ``` *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/add-metadata-tags.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Overview Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/administration-overview This overview covers topics related to managing users, organizations, workspaces, and applications within LangSmith. ## Resource hierarchy ### Organizations An organization is a logical grouping of users within LangSmith that defines shared settings applying across all of its workspaces. These settings govern organization-wide concerns rather than individual projects within a workspace. Common organization-level configurations include user management, single sign-on (SSO), OAuth provider configuration, custom role creation, billing, and usage tracking. Typically, there is one organization per company. An organization can have multiple workspaces. For more details, see the [setup guide](/langsmith/set-up-hierarchy#set-up-an-organization). When you log in for the first time, a personal organization will be created for you automatically. If you'd like to collaborate with others, you can create a separate organization and invite your team members to join. There are a few important differences between your personal organization and shared organizations: | Feature | Personal | Shared | | ------------------- | ------------------- | -------------------------------------------------------------------------------------------- | | Maximum workspaces | 1 | Variable, depending on plan (see [pricing page](https://www.langchain.com/pricing-langsmith) | | Collaboration | Cannot invite users | Can invite users | | Billing: paid plans | Developer plan only | All other plans available | ### Workspaces Workspaces were formerly called Tenants. Some code and APIs may still reference the old name for a period of time during the transition. A workspace is a logical grouping of users and resources within an organization. Workspaces are commonly used to isolate teams or business units, providing separation between projects and their associated resources. A workspace separates trust boundaries for resources and access control. Users are granted permissions at the workspace level, which determine their access to resources in that workspace, including tracing projects, datasets, annotation queues, and prompts. For details on setup, see the [setup guide](/langsmith/set-up-hierarchy#set-up-a-workspace) and for details on permissions see [Workspaces (RBAC)](/langsmith/administration-overview#workspace-roles-rbac). It is recommended to create a separate workspace for each team within your organization. To organize resources even further, you can use [Applications](#applications) to group resources within a workspace. For guidance on different workspace organization models based on your team's isolation requirements, refer to [Workload isolation](/langsmith/workload-isolation). The following image shows a sample workspace settings page: Sample Workspace ### Applications An application is a logical grouping of resources within a workspace. Applications are often agents, but they can be used for any project within a team. Applications keep the UI organized by only surfacing the resources associated with the application currently in context. Applications are built on top of [resource tags](/langsmith/administration-overview#resource-tags) and can be used to control resource access using [ABAC (private beta)](/langsmith/organization-workspace-operations#access-policies). The following image shows how to manage and switch applications in the main navbar: Sample Application Selector Any resource can be created without being tagged to an application. These resources will be visible when the `Show all applications` option is selected. ### Resources Resources are the concrete entities used to build, run, and observe applications and agents, such as tracing projects, prompts, datasets, and deployments. Resources are scoped to a specific application. ### Additional info The following diagram explains the relationship between organizations, workspaces, applications, and resources: Resource Hierarchy See the table below for details on which features are available in which scope(s): | Resource/Setting | Scope | | --------------------------------------------------------------------------- | ------------------------ | | Trace Projects | Workspace or Application | | Annotation Queues | Workspace or Application | | Deployments | Workspace or Application | | Datasets & Experiments | Workspace or Application | | Prompts | Workspace or Application | | Resource Tags | Workspace | | API Keys | Workspace | | Settings including Secrets, Feedback config, Models, Rules, and Shared URLs | Workspace | | User management: Invite User to Workspace | Workspace | | RBAC: Assigning Workspace Roles | Workspace | | Data Retention, Usage Limits | Workspace\* | | Plans and Billing, Credits, Invoices | Organization | | User management: Invite User to Organization | Organization\*\* | | Adding Workspaces | Organization | | Assigning Organization Roles | Organization | | RBAC: Creating/Editing/Deleting Custom Roles | Organization | \* Data retention settings and usage limits will be available soon for the organization level as well \*\* Self-hosted installations may enable workspace-level invites of users to the organization via a feature flag. See the [self-hosted user management docs](/langsmith/self-host-user-management) for details. ### Resource tags Resource tags allow you to further segregate resources within a workspace for use with [ABAC](/langsmith/organization-workspace-operations#access-policies). Each tag is a key-value pair that can be assigned to a resource. LangSmith resource tags are very similar to tags in cloud services like [AWS](https://docs.aws.amazon.com/tag-editor/latest/userguide/tagging.html). Sample Resource Tags ## User management and RBAC ### Users A user is a person who has access to LangSmith. Users can be members of one or more organizations and workspaces within those organizations. Organization members are managed in organization settings: Sample Organization Members And workspace members are managed in workspace settings: Sample Workspace Members ### API keys We ended support for legacy API keys prefixed with `ls__` on October 22, 2024 in favor of personal access tokens (PATs) and service keys. We require using PATs and service keys for all new integrations. API keys prefixed with `ls__` will no longer work as of October 22, 2024. #### Expiration dates When you create an API key, you have the option to set an expiration date. Adding an expiration date to keys enhances security and minimizes the risk of unauthorized access. For example, you may set expiration dates on keys for temporary tasks that require elevated access. By default, keys never expire. Once expired, an API key is no longer valid and cannot be reactivated or have its expiration modified. #### Personal access tokens (PATs) Personal Access Tokens (PATs) are used to authenticate requests to the LangSmith API. They are created by users and scoped to a user. The PAT will have the same permissions as the user that created it. We recommend not using these to authenticate requests from your application, but rather using them for personal scripts or tools that interact with the LangSmith API. If the user associated with the PAT is removed from the organization, the PAT will no longer work. PATs are prefixed with `lsv2_pt_` #### Service keys Service keys are similar to PATs, but are used to authenticate requests to the LangSmith API on behalf of a service account. Only admins can create service keys. We recommend using these for applications / services that need to interact with the LangSmith API, such as LangGraph agents or other integrations. Service keys may be scoped to a single workspace, multiple workspaces, or the entire organization, and can be used to authenticate requests to the LangSmith API for whichever workspace(s) it has access to. Service keys are prefixed with `lsv2_sk_` Use the `X-Tenant-Id` header to specify the target workspace. * **When using PATs**: If this header is omitted, requests will run against the default workspace associated with the key. * **When using organization-scoped service keys**: You must include the `X-Tenant-Id` header when accessing workspace-scoped resources. Without it, the request will fail with a `403 Forbidden` error. To see how to create a service key or Personal Access Token, see the [setup guide](/langsmith/create-account-api-key) ### Organization roles Organization roles are distinct from the [Enterprise feature workspace RBAC](#workspace-roles-rbac) and are used in the context of multiple [workspaces](#workspaces). Your organization role determines your workspace membership characteristics and your [organization-level permissions](/langsmith/organization-workspace-operations). The organization role selected also impacts workspace membership as described here: * [Organization Admin](/langsmith/rbac#organization-admin) grants full access to manage all organization configuration, users, billing, and workspaces. * An Organization Admin has `Admin` access to all workspaces in an organization. * [Organization User](/langsmith/rbac#organization-user) may read organization information but cannot execute any write actions at the organization level. An Organization User may create [Personal Access Tokens](#personal-access-tokens-pats). * An Organization User can be added to a subset of workspaces and assigned workspace roles as usual (if RBAC is enabled), which specify permissions at the workspace level. * [Organization Viewer](/langsmith/rbac#organization-viewer) is equivalent to Organization User, but **cannot** create Personal Access Tokens. (for self-hosted, available in Helm chart version 0.11.25+). The Organization User and Organization Viewer roles are only available in organizations on [plans](https://langchain.com/pricing) with multiple workspaces. In organizations limited to a single workspace, all users have the Organization Admin role. See [security settings](/langsmith/manage-organization-by-api#security-settings) for instructions on how to disable PAT creation for the entire organization. For more information on setting up organizations and workspaces, refer to the [organization setup guide](/langsmith/set-up-hierarchy#organization-roles) for more information. The following table provides an overview of organization level permissions: | | Organization Viewer | Organization User | Organization Admin | | ------------------------------------------- | ------------------- | ----------------- | ------------------ | | View organization configuration | ✅ | ✅ | ✅ | | View organization roles | ✅ | ✅ | ✅ | | View organization members | ✅ | ✅ | ✅ | | View data retention settings | ✅ | ✅ | ✅ | | View usage limits | ✅ | ✅ | ✅ | | Create personal access tokens (PATs) | ❌ | ✅ | ✅ | | Admin access to all workspaces | ❌ | ❌ | ✅ | | Manage billing settings | ❌ | ❌ | ✅ | | Create workspaces | ❌ | ❌ | ✅ | | Create, edit, and delete organization roles | ❌ | ❌ | ✅ | | Invite new users to organization | ❌ | ❌ | ✅ | | Delete user invites | ❌ | ❌ | ✅ | | Remove users from an organization | ❌ | ❌ | ✅ | | Update data retention settings | ❌ | ❌ | ✅ | | Update usage limits | ❌ | ❌ | ✅ | For a comprehensive list of required permissions along with the operations and roles that can perform them, refer to the [Organization and workspace reference](/langsmith/organization-workspace-operations). ### Workspace roles (RBAC) RBAC (Role-Based Access Control) is a feature that is only available to Enterprise customers. If you are interested in this feature, [contact our sales team](https://www.langchain.com/contact-sales). Other plans default to using the Admin role for all users. Roles are used to define the set of permissions that a user has within a workspace. There are three built-in system roles that cannot be edited: * [Workspace Admin](/langsmith/rbac#workspace-admin) has full access to all resources within the workspace. * [Workspace Editor](/langsmith/rbac#workspace-editor) has full permissions except for workspace management (adding/removing users, changing roles, configuring service keys). * [Workspace Viewer](/langsmith/rbac#workspace-viewer) has read-only access to all resources within the workspace. [Organization admins](/langsmith/rbac#organization-admin) can also create/edit custom roles with specific permissions for different resources. Roles can be managed in **Organization Settings** under the **Roles** tab: The Organization members and roles view showing a list of the roles. * For comprehensive documentation on roles and permissions, refer to the [Role-based access control](/langsmith/rbac) guide. * For more details on assigning and creating roles, refer to the [User Management](/langsmith/user-management) guide. * For a comprehensive list of required permissions along with the operations and roles that can perform them, refer to the [Organization and workspace reference](/langsmith/organization-workspace-operations). ## Best practices ### Environment separation Use [resource tags](#resource-tags) to organize resources by environment using the default tag key `Environment` and different values for the environment (e.g., `dev`, `staging`, `prod`). We do not recommend using separate workspaces for environment separation because resources cannot be shared across workspaces, which would prevent you from promoting resources (like prompts) between environments. **Resource tags vs. commit tags for prompt management** While both types of tags can use environment terminology like `dev`, `staging`, and `prod`, they serve different purposes: * **Resource tags** (`Environment: prod`): Use these to *organize and filter* resources across your workspace. Apply resource tags to tracing projects, datasets, and other resources (including prompts) to group them by environment, which enables filtering in the UI. * [Commit tags](/langsmith/manage-prompts#commit-tags) (`prod` tag): Use these to manage which [prompt version](/langsmith/prompt-engineering) your code references. Commit tags are labels that point to specific commits in a prompt's history. When your code pulls a prompt by tag name (e.g., `client.pull_prompt("prompt-name:prod")`), it retrieves whichever commit that tag currently points to. To promote a prompt from `staging` to `prod`, move the commit tag to point to the desired version. Resource tags organize **which resources** belong to an environment. Commit tags let you control **which version** of a prompt your code references without changing the code itself. ## Usage and billing ### Data retention This section covers how data retention works and how it's priced in LangSmith. #### Why retention matters * **Privacy**: Many data privacy regulations, such as GDPR in Europe or CCPA in California, require organizations to delete personal data once it's no longer necessary for the purposes for which it was collected. Setting retention periods aids in compliance with such regulations. * **Cost**: LangSmith charges less for traces that have low data retention. See our tutorial on how to [optimize spend](/langsmith/billing#optimize-your-tracing-spend) for details. #### How it works LangSmith has two tiers of traces based on Data Retention with the following characteristics: | | Base | Extended | | -------------------- | --------------------------------------------------------------- | --------------------------------------------------------------- | | **Price** | [See pricing page](https://www.langchain.com/pricing-langsmith) | [See pricing page](https://www.langchain.com/pricing-langsmith) | | **Retention Period** | 14 days | 400 days | **Data deletion after retention ends** After the specified retention period, traces are no longer accessible in the tracing project UI or via the API. All user data associated with the trace (e.g. inputs and outputs) is deleted from our internal systems within a day thereafter. Some metadata associated with each trace may be retained indefinitely for analytics and billing purposes. **Data retention auto-upgrades** Auto upgrades can have an impact on your bill. Please read this section carefully to fully understand your estimated LangSmith tracing costs. When you use certain features with `base` tier traces, their data retention will be automatically upgraded to `extended` tier. This will increase both the retention period, and the cost of the trace. The complete list of scenarios in which a trace will upgrade when: * **Feedback** is added to any run on the trace (or any trace in the thread), whether through [manual annotation](/langsmith/annotate-traces-inline#annotate-traces-and-runs-inline), automatically with [an online evaluator](/langsmith/online-evaluations-llm-as-judge), or programmatically [via the SDK](/langsmith/attach-user-feedback#log-user-feedback-using-the-sdk). * An **[annotation queue](/langsmith/annotation-queues#assign-runs-to-an-annotation-queue)** receives any run from the trace. * An **[automation rule](/langsmith/rules#set-up-automation-rules)** matches any run within a trace. **Why auto-upgrade traces?** We have two reasons behind the auto-upgrade model for tracing: 1. We think that traces that match any of these conditions are fundamentally more interesting than other traces, and therefore it is good for users to be able to keep them around longer. 2. We philosophically want to charge customers an order of magnitude lower for traces that may not be interacted with meaningfully. We think auto-upgrades align our pricing model with the value that LangSmith brings, where only traces with meaningful interaction are charged at a higher rate. If you have questions or concerns about our pricing model, please feel free to contact support via [support.langchain.com](https://support.langchain.com) and let us know your thoughts! **How does data retention affect downstream features?** * **Annotation Queues, Run Rules, and Feedback**: Traces that use these features will be [auto-upgraded](#data-retention-auto-upgrades). * **Monitoring**: The monitoring tab will continue to work even after a base tier trace's data retention period ends. It is powered by trace metadata that exists for >30 days, meaning that your monitoring graphs will continue to stay accurate even on `base` tier traces. * **Datasets**: Datasets have an indefinite data retention period. Restated differently, if you add a trace's inputs and outputs to a dataset, they will never be deleted. We suggest that if you are using LangSmith for data collection, you take advantage of the datasets feature. #### Billing model **Billable metrics** On your LangSmith invoice, you will see two metrics that we charge for: * LangSmith Traces (Base Charge) * LangSmith Traces (Extended Data Retention Upgrades). The first metric includes all traces, regardless of tier. The second metric just counts the number of extended retention traces. **Why measure all traces + upgrades instead of base and extended traces?** A natural question to ask when considering our pricing is why not just show the number of `base` tier and `extended` tier traces directly on the invoice? While we understand this would be more straightforward, it doesn't fit trace upgrades properly. Consider a `base` tier trace that was recorded on June 30, and upgraded to `extended` tier on July 3. The `base` tier trace occurred in the June billing period, but the upgrade occurred in the July billing period. Therefore, we need to be able to measure these two events independently to properly bill our customers. If your trace was recorded as an extended retention trace, then the `base` and `extended` metrics will both be recorded with the same timestamp. **Cost breakdown** The Base Charge for a trace is .05¢ per trace. We priced the upgrade such that an `extended` retention trace costs 10x the price of a base tier trace (.50¢ per trace) including both metrics. Thus, each upgrade costs .45¢. ### Rate limits LangSmith has rate limits which are designed to ensure the stability of the service for all users. To ensure access and stability, LangSmith will respond with HTTP Status Code 429 indicating that rate or usage limits have been exceeded under the following circumstances: #### Temporary throughput limit over a 1 minute period at our application load balancer This 429 is the result of exceeding a fixed number of API calls over a 1 minute window on a per API key/access token basis. The start of the window will vary slightly — it is not guaranteed to start at the start of a clock minute — and may change depending on application deployment events. After the max events are received we will respond with a 429 until 60 seconds from the start of the evaluation window has been reached and then the process repeats. This 429 is thrown by our application load balancer and is a mechanism in place for all LangSmith users independent of plan tier to ensure continuity of service for all users. | Method | Endpoints | Limit | Window | | ----------------- | ------------- | ----- | -------- | | `DELETE` | `/sessions*` | 30 | 1 minute | | `POST` OR `PATCH` | `/runs*` | 5000 | 1 minute | | `GET` | `/runs/:id` | 30 | 1 minute | | `POST` | `/feedbacks*` | 5000 | 1 minute | | `*` | `*` | 2000 | 1 minute | The LangSmith SDK takes steps to minimize the likelihood of reaching these limits on run-related endpoints by batching up to 100 runs from a single session ID into a single API call. #### Plan-level hourly trace event limit This 429 is the result of reaching your maximum hourly events ingested and is evaluated in a fixed window starting at the beginning of each clock hour in UTC and resets at the top of each new hour. An event in this context is the creation or update of a run. So if run is created, then subsequently updated in the same hourly window, that will count as 2 events against this limit. This is thrown by our application and varies by plan tier, with organizations on our Startup/Plus and Enterprise plan tiers having higher hourly limits than our Free and Developer Plan Tiers which are designed for personal use. | Plan | Limit | Window | | -------------------------------- | -------------- | ------ | | Developer (no payment on file) | 50,000 events | 1 hour | | Developer (with payment on file) | 250,000 events | 1 hour | | Startup/Plus | 500,000 events | 1 hour | | Enterprise | Custom | Custom | #### Plan-level hourly trace data ingest limit This 429 is the result of reaching the maximum amount of data ingested across your trace inputs, outputs, and metadata and is evaluated in a fixed window starting at the beginning of each clock hour in UTC and resets at the top of each new hour. Typically, inputs, outputs, and metadata are send on both run creation and update events. So if a run is created and is 2.0MB in size at creation, and 3.0MB in size when updated in the same hourly window, that will count as 5.0MB of storage against this limit. This is thrown by our application and varies by plan tier, with organizations on our Startup/Plus and Enterprise plan tiers having higher hourly limits than our Free and Developer Plan Tiers which are designed for personal use. | Plan | Limit | Window | | -------------------------------- | ------ | ------ | | Developer (no payment on file) | 500MB | 1 hour | | Developer (with payment on file) | 2.5GB | 1 hour | | Startup/Plus | 5.0GB | 1 hour | | Enterprise | Custom | Custom | #### Plan-level monthly unique traces limit This 429 is the result of reaching your maximum monthly traces ingested and is evaluated in a fixed window starting at the beginning of each calendar month in UTC and resets at the beginning of each new month. This is thrown by our application and applies only to the Developer Plan Tier when there is no payment method on file. | Plan | Limit | Window | | ------------------------------ | ------------ | ------- | | Developer (no payment on file) | 5,000 traces | 1 month | #### Self-configured monthly usage limits This 429 is the result of reaching your usage limit as configured by your organization admin and is evaluated in a fixed window starting at the beginning of each calendar month in UTC and resets at the beginning of each new month. This is thrown by our application and varies by organization based on their configured settings. #### Handling 429s responses in your application Since some 429 responses are temporary and may succeed on a successive call, if you are directly calling the LangSmith API in your application we recommend implementing retry logic with exponential backoff and jitter. For convenience, LangChain applications built with the LangSmith SDK has this capability built-in. It is important to note that if you are saturating the endpoints for extended periods of time, retries may not be effective as your application will eventually run large enough backlogs to exhaust all retries. If that is the case, we would like to discuss your needs more specifically. Please contact support via [LangSmith Support](https://support.langchain.com) with details about your applications throughput needs and sample code and we can work with you to better understand whether the best approach is fixing a bug, changes to your application code, or a different LangSmith plan. ### Usage limits LangSmith lets you configure usage limits on tracing. Note that these are *usage* limits, not *spend* limits, which mean they let you limit the quantity of occurrences of some event rather than the total amount you will spend. LangSmith lets you set two different monthly limits, mirroring our Billable Metrics discussed in the aforementioned data retention guide: * All traces limit * Extended data retention traces limit These let you limit the number of total traces, and extended data retention traces respectively. #### Properties of usage limiting Usage limiting is approximate, meaning that we do not guarantee the exactness of the limit. In rare cases, there may be a small period of time where additional traces are processed above the limit threshold before usage limiting begins to apply. #### Side effects of extended data retention traces limit The extended data retention traces limit has side effects. If the limit is already reached, any feature that could cause an auto-upgrade of tracing tiers becomes inaccessible. This is because an auto-upgrade of a trace would cause another extended retention trace to be created, which in turn should not be allowed by the limit. Therefore, you can no longer: 1. match run rules 2. add feedback to traces 3. add runs to annotation queues Each of these features may cause an auto upgrade, so we shut them off when the limit is reached. #### Updating usage limits Usage limits can be updated from the `Settings` page under `Usage and Billing`. Limit values are cached, so it may take a minute or two before the new limits apply. ### Related content * Tutorial on how to [optimize spend](/langsmith/billing#optimize-your-tracing-spend) ## Additional resources * **[Release Versions](/langsmith/release-versions)**: Learn about LangSmith's version support policy, including Active, Critical, End of Life, and Deprecated support levels. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/administration-overview.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Set up Agent Auth (Beta) Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-auth Enable secure access from agents to any system using OAuth 2.0 credentials with Agent Auth. Agent Auth is in **Beta** and under active development. To provide feedback or use this feature, reach out to the [LangChain team](https://forum.langchain.com/c/help/langsmith/). ## Installation ```bash pip theme={null} pip install langchain-auth ``` ```bash uv theme={null} uv add langchain-auth ``` ```bash theme={null} npm install @langchain/auth ``` ## Quickstart ### 1. Initialize the client ```python theme={null} from langchain_auth import Client client = Client(api_key="your-langsmith-api-key") ``` ```javascript theme={null} import { Client } from '@langchain/auth'; const client = new Client({ apiKey: 'your-langsmith-api-key' }); ``` #### Self-hosted configuration For self-hosted LangSmith instances, specify the API URL using the `/api-host` path on your instance. ```bash theme={null} export LANGSMITH_API_URL="https://your-langsmith-instance.com/api-host" ``` Then initialize the client normally: ```python theme={null} client = Client(api_key="your-langsmith-api-key") ``` ```python theme={null} client = Client( api_key="your-langsmith-api-key", api_url="https://your-langsmith-instance.com/api-host" ) ``` ```javascript theme={null} const client = new Client({ apiKey: 'your-langsmith-api-key', apiUrl: 'https://your-langsmith-instance.com/api-host' }); ``` ### 2. Set up OAuth providers Before agents can authenticate, you need to configure an OAuth provider using the following process: 1. Select a unique identifier for your OAuth provider to use in LangChain's platform (e.g., "github-local-dev", "google-workspace-prod"). 2. Go to your OAuth provider's developer console and create a new OAuth application. 3. Set the callback URL in your OAuth provider: ``` https://smith.langchain.com/host-oauth-callback/{provider_id} ``` For example, if your provider\_id is "github-local-dev", use: ``` https://smith.langchain.com/host-oauth-callback/github-local-dev ``` ``` https://{your-langsmith-instance}/host-oauth-callback/{provider_id} ``` For example, if your instance is `langsmith.example.com` and provider\_id is "github", use: ``` https://langsmith.example.com/host-oauth-callback/github ``` 4. Use `client.create_oauth_provider()` with the credentials from your OAuth app: ```python theme={null} new_provider = await client.create_oauth_provider( provider_id="{provider_id}", # Provide any unique ID name="{provider_display_name}", # Provide any display name client_id="{your_client_id}", client_secret="{your_client_secret}", auth_url="{auth_url_of_your_provider}", token_url="{token_url_of_your_provider}", ) ``` ```javascript theme={null} const newProvider = await client.createOAuthProvider({ providerId: '{provider_id}', // Provide any unique ID name: '{provider_display_name}', // Provide any display name clientId: '{your_client_id}', clientSecret: '{your_client_secret}', authUrl: '{auth_url_of_your_provider}', tokenUrl: '{token_url_of_your_provider}', }); ``` ### 3. Authenticate from an agent The client `authenticate()` API is used to get OAuth tokens from pre-configured providers. On the first call, it takes the caller through an OAuth 2.0 auth flow. #### In LangGraph context By default, tokens are scoped to the calling agent using the Assistant ID parameter. ```python theme={null} auth_result = await client.authenticate( provider="{provider_id}", scopes=["scopeA"], user_id="your_user_id" # Any unique identifier to scope this token to the human caller ) # Or explicitly specify an agent_id for agent-scoped tokens auth_result = await client.authenticate( provider="{provider_id}", scopes=["scopeA"], user_id="your_user_id", agent_id="specific-agent-id" # Optional: explicitly set agent scope ) ``` During execution, if authentication is required, the SDK will throw an [interrupt](https://langchain-ai.github.io/langgraph/how-tos/human_in_the_loop/add-human-in-the-loop/#pause-using-interrupt). The agent execution pauses and presents the OAuth URL to the user: After the user completes OAuth authentication and we receive the callback from the provider, they will see the auth success page. The agent then resumes execution from the point it left off at, and the token can be used for any API calls. We store and refresh OAuth tokens so that future uses of the service by either the user or agent do not require an OAuth flow. ```python theme={null} token = auth_result.token ``` #### Outside LangGraph context Provide the `auth_url` to the user for out-of-band OAuth flows. ```python theme={null} auth_result = await client.authenticate( provider="{provider_id}", scopes=["scopeA"], user_id="your_user_id" ) if auth_result.status == "pending": print(f"Complete OAuth at: {auth_result.url}") # Wait for user to complete OAuth completed_auth = await client.wait_for_completion(auth_result.auth_id) print("Authentication completed!") else: token = auth_result.token print(f"Already authenticated, token: {token}") ``` ```javascript theme={null} const authResult = await client.authenticate({ provider: '{provider_id}', scopes: ['scopeA'], userId: 'your_user_id' }); if (authResult.status === 'pending') { console.log(`Complete OAuth at: ${authResult.authUrl}`); // Wait for user to complete OAuth const completedAuth = await client.waitForCompletion(authResult.authId); console.log('Authentication completed!'); } else { const token = authResult.token; console.log(`Already authenticated, token: ${token}`); } ``` ## Troubleshooting ### Self-hosted: 405 Method Not Allowed If you receive a `405 Method Not Allowed` error, ensure `LANGSMITH_API_URL` points to the `/api-host` path: ```bash theme={null} export LANGSMITH_API_URL="https://your-instance.com/api-host" ``` ### Self-hosted: Malformed OAuth callback URL Ensure your OAuth provider's redirect URI matches your LangSmith instance URL: ``` https://your-instance.com/host-oauth-callback/{provider_id} ``` *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-auth.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # LangSmith Agent Builder Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder Create helpful AI agents without code. Start from a template, connect your accounts, and let the agent handle routine work while you stay in control. ## What you can do * Automate everyday tasks like drafting emails, summarizing updates, and organizing information. * Connect your favorite apps to bring context into your agent's work. * Use in chat or where you work (e.g., Slack) to get help in the flow. * Stay in control with simple approvals for important actions. ## Start building Pick a ready-made starter (e.g., email assistant or team updates) and customize. Describe your goal in plain English and let AI draft your agent's configuration. Review and edit before running. ## Get started Sign up for a [LangSmith account](https://smith.langchain.com/agents?skipOnboarding=true). Start from a ready-to-use template, or describe your goal and let AI draft your agent's instructions. You can edit details before running. [Browse templates](https://www.langchain.com/templates). Securely sign in to the services you want the agent to use. Run the agent and iterate on its instructions in a few clicks. ## Privacy policy and disclaimers The LangSmith Agent Builder App for Slack collects, manages, and stores third-party data in accordance with our privacy policy. For full details on how your data is handled, please see [our privacy policy](https://www.langchain.com/privacy-policy). Agent Builder uses the following approach to AI: * **Model**: Uses LLMs provided through the LangSmith platform * **Data retention**: User data is retained according to LangSmith's data retention policies * **Data tenancy**: Data is handled according to your LangSmith organization settings * **Data residency**: Data residency follows your LangSmith configuration Disclaimers: * **AI-generated content**: All responses from agents are generated by AI and may contain errors or inaccuracies. Always verify important information. * **Data usage**: Slack data is not used to train LLMs. Your workspace data remains private and is only used to provide agent functionality. * **Transparency**: The Agent Builder is transparent about the actions it will take once added to your workspace, as outlined in the permissions section above. ## Learn more * [Essentials: connections, automation, memory, approvals](/langsmith/agent-builder-essentials) * [Create from a template](/langsmith/agent-builder-templates) * [Set up your workspace](/langsmith/agent-builder-setup) * [Connect apps and services](/langsmith/agent-builder-tools) and [use remote connections](/langsmith/agent-builder-mcp-framework) * [Choose between workspace and private agents](/langsmith/agent-builder-manage-agent-settings) * [Authorize accounts when prompted](/langsmith/agent-builder-auth-format) * [Call agents from your app](/langsmith/agent-builder-code) **Self-hosting for Agent Builder is available in Beta.** For more information, see [Enable Agent Builder](/langsmith/agent-builder-self-hosted). *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Auth-aware tool responses Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-auth-format Format tool responses to trigger OAuth flows and resume execution automatically. Some [tools](/langsmith/agent-builder-tools) require user authorization (for example, Google, Slack, GitHub). Agent Builder includes middleware to detect when a tool needs authorization and to pause the run with a clear prompt to the user. After the user completes auth, the same tool call is retried automatically. ## Return shape to request auth If a tool detects missing authorization, return a JSON string containing the following fields: ```json theme={null} { "auth_required": true, "auth_url": "https://auth.example.com/start", "auth_id": "opaque-tracking-id" } ``` * `auth_required`: set to `true` to signal an interrupt is needed. * `auth_url`: where the user should be redirected to authorize. * `auth_id`: optional correlation ID to track the auth session. When Agent Builder detects this response, it interrupts the run, displays the authentication UI to the user, and automatically retries the tool call once authorization completes. If you want your custom tools to reuse the same authentication required interrupt + UI, ensure your tools return the same shape of JSON. Return only this JSON as the tool's output. Avoid including additional text or content. Agent Builder parses the response to trigger the authentication flow. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-auth-format.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Call agents from code Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-code Invoke Agent Builder agents from Python, JavaScript, or any language through the REST API. You can invoke Agent Builder agents from your applications using the [LangGraph SDK](/langsmith/reference) or the REST API. Agent Builder agents run on [Agent Server](/langsmith/agent-server), so you can use the same API methods as any other [LangSmith deployment](/langsmith/deployments). The REST API lets you call your agent from any language or platform that supports HTTP requests. ## Prerequisites * A LangSmith account with an Agent Builder agent * A [Personal Access Token (PAT)](/langsmith/create-account-api-key) for authentication * (SDK only) The [LangGraph SDK](/langsmith/reference) installed: ```bash Python theme={null} pip install langgraph-sdk python-dotenv ``` ```bash TypeScript theme={null} yarn add @langchain/langgraph-sdk ``` ## Authentication To authenticate with your agent's Agent Builder deployment, provide a LangSmith [Personal Access Token (PAT)](/langsmith/create-account-api-key) to the `api_key` argument when instantiating the LangGraph SDK client, or via the `X-API-Key` header. If using `X-API-Key`, you must also set the `X-Auth-Scheme` header to `langsmith-api-key`. If the PAT you pass is not tied to the owner of the agent, your request will be rejected with a `404 Not Found` error. If the agent you're trying to invoke is a workspace agent and you're not the owner, you can perform all the same operations as you would in the UI (read-only). ## 1. Get the agent ID and URL To get your agent's `agent_id` and `api_url`: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to your agent's inbox. 2. Next to the agent name, click the **Edit Agent** icon. 3. Click the **Settings** icon in the top right corner. 4. Click **View code snippets** to see pre-populated values for your agent. Copy the code below and replace `agent_id` and `api_url` with the values from your agent's code snippets. Create a `.env` file in your project root with your [Personal Access Token](/langsmith/create-account-api-key): ```bash .env theme={null} LANGGRAPH_API_KEY=your-personal-access-token ``` ## 2. Fetch agent configuration Verify your connection by fetching your agent's configuration: ```python theme={null} import os from dotenv import load_dotenv from langgraph_sdk.client import get_client load_dotenv() agent_id = "your-agent-id" api_key = os.getenv("LANGGRAPH_API_KEY") api_url = ".us.langgraph.app" client = get_client( url=api_url, api_key=api_key, headers={ "X-Auth-Scheme": "langsmith-api-key", }, ) async def get_assistant(agent_id: str): agent = await client.assistants.get(agent_id) print(agent) if __name__ == "__main__": import asyncio asyncio.run(get_assistant(agent_id)) ``` ```ts theme={null} import "dotenv/config"; import { Client } from "@langchain/langgraph-sdk"; const agentId = "your-agent-id"; const apiKey = process.env.LANGGRAPH_API_KEY; const apiUrl = ".us.langgraph.app"; const client = new Client({ apiUrl, apiKey, defaultHeaders: { "X-Auth-Scheme": "langsmith-api-key", }, }); async function main(agentId: string) { const agent = await client.assistants.get(agentId); console.log(agent); } main(agentId).catch(console.error); ``` ```bash theme={null} curl --request GET \ --url ".us.langgraph.app/assistants/your-agent-id" \ --header 'Content-Type: application/json' \ --header 'X-Api-Key: your-personal-access-token' \ --header 'X-Auth-Scheme: langsmith-api-key' ``` Use a [Personal Access Token (PAT)](/langsmith/create-account-api-key) tied to your LangSmith account. Set the `X-Auth-Scheme` header to `langsmith-api-key` for authentication. If you implemented custom authentication, pass the user's token in headers so the agent can use user-scoped tools. See [Add custom authentication](/langsmith/custom-auth). ## 3. Invoke agent The examples below show how to send a message to your agent and receive a response. You can use either a **stateless** run (no thread, no conversation history) or a **stateful** run (with a thread to maintain conversation history across multiple turns). ### Stateless run A stateless run sends a single request and returns the full response. No conversation history is persisted. This is the simplest way to call your agent: ```python theme={null} import os from dotenv import load_dotenv from langgraph_sdk.client import get_client load_dotenv() agent_id = "your-agent-id" api_key = os.getenv("LANGGRAPH_API_KEY") api_url = "https://.us.langgraph.app" client = get_client( url=api_url, api_key=api_key, headers={ "X-Auth-Scheme": "langsmith-api-key", }, ) result = await client.runs.wait( None, agent_id, input={ "messages": [ {"role": "user", "content": "What can you help me with?"} ] }, ) print(result) ``` ```ts theme={null} import "dotenv/config"; import { Client } from "@langchain/langgraph-sdk"; const agentId = "your-agent-id"; const apiKey = process.env.LANGGRAPH_API_KEY; const apiUrl = ".us.langgraph.app"; const client = new Client({ apiUrl, apiKey, defaultHeaders: { "X-Auth-Scheme": "langsmith-api-key", }, }); const result = await client.runs.wait( null, agentId, { input: { messages: [ { role: "user", content: "What can you help me with?" } ] } } ); console.log(result); ``` ```bash theme={null} curl --request POST \ --url ".us.langgraph.app/runs/wait" \ --header 'Content-Type: application/json' \ --header 'X-Api-Key: your-personal-access-token' \ --header 'X-Auth-Scheme: langsmith-api-key' \ --data '{ "assistant_id": "your-agent-id", "input": { "messages": [ { "role": "user", "content": "What can you help me with?" } ] } }' ``` ### Stateless streaming run To stream the response as it is generated rather than waiting for the full result, use the streaming endpoint: ```python theme={null} async for chunk in client.runs.stream( None, agent_id, input={ "messages": [ {"role": "user", "content": "What can you help me with?"} ] }, stream_mode="updates", ): if chunk.data and "run_id" not in chunk.data: print(chunk.data) ``` ```ts theme={null} const streamResponse = client.runs.stream( null, agentId, { input: { messages: [ { role: "user", content: "What can you help me with?" } ] }, streamMode: "updates" } ); for await (const chunk of streamResponse) { if (chunk.data && !("run_id" in chunk.data)) { console.log(chunk.data); } } ``` ```bash theme={null} curl --request POST \ --url ".us.langgraph.app/runs/stream" \ --header 'Content-Type: application/json' \ --header 'X-Api-Key: your-personal-access-token' \ --header 'X-Auth-Scheme: langsmith-api-key' \ --data '{ "assistant_id": "your-agent-id", "input": { "messages": [ { "role": "user", "content": "What can you help me with?" } ] }, "stream_mode": [ "updates" ] }' ``` ### Stateful run with a thread To maintain conversation history across multiple interactions, first create a thread and then run your agent on it. Each subsequent run on the same thread has access to the full message history: ```python theme={null} import os from dotenv import load_dotenv from langgraph_sdk.client import get_client load_dotenv() agent_id = "your-agent-id" api_key = os.getenv("LANGGRAPH_API_KEY") api_url = ".us.langgraph.app" client = get_client( url=api_url, api_key=api_key, headers={ "X-Auth-Scheme": "langsmith-api-key", }, ) thread = await client.threads.create() async for chunk in client.runs.stream( thread["thread_id"], agent_id, input={ "messages": [ {"role": "user", "content": "Hi, my name is Alice."} ] }, stream_mode="updates", ): if chunk.data and "run_id" not in chunk.data: print(chunk.data) async for chunk in client.runs.stream( thread["thread_id"], agent_id, input={ "messages": [ {"role": "user", "content": "What is my name?"} ] }, stream_mode="updates", ): if chunk.data and "run_id" not in chunk.data: print(chunk.data) ``` ```ts theme={null} import "dotenv/config"; import { Client } from "@langchain/langgraph-sdk"; const agentId = "your-agent-id"; const apiKey = process.env.LANGGRAPH_API_KEY; const apiUrl = ".us.langgraph.app"; const client = new Client({ apiUrl, apiKey, defaultHeaders: { "X-Auth-Scheme": "langsmith-api-key", }, }); const thread = await client.threads.create(); let streamResponse = client.runs.stream( thread["thread_id"], agentId, { input: { messages: [ { role: "user", content: "Hi, my name is Alice." } ] }, streamMode: "updates" } ); for await (const chunk of streamResponse) { if (chunk.data && !("run_id" in chunk.data)) { console.log(chunk.data); } } streamResponse = client.runs.stream( thread["thread_id"], agentId, { input: { messages: [ { role: "user", content: "What is my name?" } ] }, streamMode: "updates" } ); for await (const chunk of streamResponse) { if (chunk.data && !("run_id" in chunk.data)) { console.log(chunk.data); } } ``` First, create a thread: ```bash theme={null} curl --request POST \ --url ".us.langgraph.app/threads" \ --header 'Content-Type: application/json' \ --header 'X-Api-Key: your-personal-access-token' \ --header 'X-Auth-Scheme: langsmith-api-key' \ --data '{}' ``` Use the `thread_id` from the response to send messages on the thread: ```bash theme={null} curl --request POST \ --url ".us.langgraph.app/threads//runs/stream" \ --header 'Content-Type: application/json' \ --header 'X-Api-Key: your-personal-access-token' \ --header 'X-Auth-Scheme: langsmith-api-key' \ --data '{ "assistant_id": "your-agent-id", "input": { "messages": [ { "role": "user", "content": "Hi, my name is Alice." } ] }, "stream_mode": [ "updates" ] }' ``` Send a follow-up message on the same thread: ```bash theme={null} curl --request POST \ --url ".us.langgraph.app/threads//runs/stream" \ --header 'Content-Type: application/json' \ --header 'X-Api-Key: your-personal-access-token' \ --header 'X-Auth-Scheme: langsmith-api-key' \ --data '{ "assistant_id": "your-agent-id", "input": { "messages": [ { "role": "user", "content": "What is my name?" } ] }, "stream_mode": [ "updates" ] }' ``` ## REST API reference The table below summarizes the key endpoints. Replace `` with your agent's deployment URL. | Operation | Method | Endpoint | | ------------------------------------------------------------------------------------------------------------------------ | ------ | ------------------------------------------- | | [Get agent info](/langsmith/agent-server-api/assistants/get-assistant) | `GET` | `/assistants/` | | [Create a thread](/langsmith/agent-server-api/threads/create-thread) | `POST` | `/threads` | | [Run (wait for result)](https://docs.langchain.com/langsmith/agent-server-api/stateless-runs/create-run-wait-for-output) | `POST` | `/runs/wait` | | [Run (streaming)](/langsmith/agent-server-api/stateless-runs/create-run-stream-output) | `POST` | `/runs/stream` | | [Run on thread (wait)](/langsmith/agent-server-api/thread-runs/create-run-wait-for-output) | `POST` | `/threads//runs/wait` | | /langsmith/agent-server-api/thread-runs/create-run-stream-output | `POST` | `/threads//runs/stream` | All endpoints require the following headers: * `Content-Type: application/json` * `X-Api-Key:` your [Personal Access Token](/langsmith/create-account-api-key) * `X-Auth-Scheme: langsmith-api-key` For the full API specification, see the [Agent Server API reference](/langsmith/server-api-ref). *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-code.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Essentials Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-essentials Agent Builder's core features Agent Builder essentials are the core features that make up the foundation of your agents. They include tools, triggers, memory, sub-agents, and approvals. ## Tools Tools let your agents interact with your apps and services. Your agents can send emails, create calendar events, post messages, search the web, and more. Choose from built-in tools for Gmail, Slack, Google Calendar, GitHub, and many others. See [Supported tools](/langsmith/agent-builder-tools) for a complete list. ## Triggers Triggers define when your agent should start running. You can connect your agent to external tools or time-based schedules, letting it respond automatically to messages, emails, or recurring events. Here are some popular ways to trigger your agent: Activate your agent when messages are received in specific Slack channels. Trigger your agent when emails are received. Run your agent on a time-based schedule for recurring tasks. ## Threads Threads are conversations between you and your agent. Each thread contains messages, agent responses, and any actions the agent takes. To view threads, navigate to your agent in the [LangSmith UI](https://smith.langchain.com). The inbox shows all threads for that agent. Click on a thread to view the conversation. ### Read and unread status How threads are marked depends on whether the agent uses triggers: * **Chat agents (no trigger):** Responses mark the thread as **unread**. Viewing the thread marks it as read. * **Trigger-based agents:** Responses keep the thread as **read** by default. You can manually mark any thread as read or unread at any time. ## Skills Skills are a way to bundle capabilities and provide more specific information in situations where the context is not universally relevant. Using skills can help: * Save on token usage by only providing the context that is relevant to the current task. * Prevent the agent from having too much context in the system prompt, which can lead to hallucinations and incorrect responses. For more information, see [Skills](/oss/python/deepagents/skills). ## Memory and updates Agents remember important information from previous conversations and can update themselves to work better. * Memory: Agents remember relevant details from past interactions, so they can make better decisions in future conversations. * Self-updates: Agents can add new tools, remove ones they don't need, or adjust their instructions to improve how they work. * What stays the same: Agents can't change their name, description, or the triggers that start them. For more information, see [How we built Agent Builder's memory system](https://www.langchain.com/conceptual-guides/how-we-built-agent-builders-memory). ## Custom models Agent Builder supports custom models. You can connect any LLM API that supports the **OpenAI chat completions spec** or **Anthropic chat spec**. Common use cases include: * **LLM proxies**: Route requests through services like LiteLLM, Portkey, or your own proxy. * **Self-hosted models**:Connect to models running on your own infrastructure. * **Alternative providers**: Use any provider with a compatible API. To add a custom model: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to the agent you want to edit. 2. Click on the settings icon in the top right corner. 3. In the **Model** section, select **+ Add custom model**. 4. Enter the model ID, display name, base URL, and API key name and value. 5. Click **Save**. Custom models must be accessible through a public API endpoint. LangSmith cannot connect to models hosted on private networks, behind VPNs, or on machines that are not exposed to the internet. ## Sub-agents Build complex agents by breaking big tasks into smaller, specialized helpers. Think of sub-agents as a team of specialists—each one handles a specific part of the job while working together with your main agent. This approach makes it easier to build sophisticated systems. Instead of one agent trying to do everything, you can have specialized helpers that each excel at their part of the task. Here are some ways you might use sub-agents: * Split into sub-tasks: Have one agent fetch data, another summarize it, and a third format the results. * Specialized tools: Give different agents access to different tools based on what they need to do. * Independent work: Let sub-agents work on their own, then bring their results back to the main agent. ## Human-in-the-loop Stay in control of important decisions. You can set up your agent to pause and ask for your approval before taking certain actions. This ensures your agent handles most tasks automatically, while you retain oversight. ### Setting up approval steps When setting up your agent, choose the tool or action you want to review before it runs. Find the approval option for that tool and switch it on. When your agent reaches that step, it will pause and wait for your approval before continuing. ### What you can do when your agent pauses When your agent stops to ask for approval, you have three options: Give the green light and let your agent proceed with its plan. Modify the agent's message or parameters before allowing it to continue. Share feedback to help your agent learn and improve. ## Traces Traces are a series of steps that your agent takes to go from input to output. You can use [LangSmith](/langsmith/home) to visualize these execution steps. To view all traces for your agent: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to your agent's inbox. 2. Next to the agent name, click the **View Agent Traces** icon. To view a trace for a specific thread: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to your agent's inbox. 2. Right-click on the thread you want to trace and select **View trace**. For more information, see [LangSmith Observability](/langsmith/observability). ## Next steps * [Set up your workspace](/langsmith/agent-builder-setup) * [Connect apps and services](/langsmith/agent-builder-tools) * [Use remote servers for tools](/langsmith/agent-builder-remote-mcp-servers) * [Choose between workspace and private agents](/langsmith/agent-builder-manage-agent-settings) * [Call agents from your app](/langsmith/agent-builder-code) *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-essentials.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Manage agent settings Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-manage-agent-settings Manage your agents in Agent Builder. This page explains how to manage the settings for your agents in Agent Builder. ## Change the model To change the model for your agent: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to your agent's inbox. 2. Next to the agent name, click the **Edit Agent** icon. 3. In the top right corner, click the **Settings** icon. 4. Select the **Model** you want to use. 5. Enter the API key for the model. For information on how to add a custom model, see [Custom models](/langsmith/agent-builder-essentials#custom-models). ## Reconnect tool integrations To reconnect a tool integration to an agent: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to your agent's inbox. 2. Next to the agent name, click the **Edit Agent** icon. 3. In the top right corner, click the **Settings** icon. 4. In the **Connected Integrations** section, click the **Connect** button next to the tool you want to reconnect. ## Download agent files To download the files for your agent, click the **Settings** icon in the top right corner of the agent and select **Download ZIP**. This will export the agent configuration as a ZIP file. ## Change access to the agent Agents can either be private to the creator or shared within a LangSmith workspace. | Feature | Private agents | [Workspace agents](#workspace-scoped-agent-details) | | ------------------------ | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | **Ownership and access** | Only visible to creator | Visible to anyone within the same LangSmith workspace | | **OAuth authentication** | OAuth credentials are scoped to creator | OAuth credentials are scoped to each user; new users cloning workspace agents must re-authenticate with selected tools | | **Secrets** | Uses workspace-scoped LangSmith secrets | Uses workspace-scoped LangSmith secrets (same as private agents) | To change the agent visibility, click the **Visibility settings** icon in the top right corner of the agent and select either **Only me** or **Workspace**. ### Workspace-scoped agent details While workspace-scoped agents are shared, some details are public, while others are private: * **Threads are always user-scoped**, so even if an agent is workspace-scoped, the chat history created within that agent will always be private and only accessible to the specific user who created them. * **The system prompt, selected tools, and sub-agents will be public on workspace-scoped agents.** Users will not be able to modify these fields on the original workspace-scoped agent, but can make changes once they've cloned the agent. * **The trigger type on workspace-scoped agents is public** (for example, Slack message received), but the specific connection with the trigger (for example, the Slack channel, or Gmail address) is not shared. This way, users know what trigger to use when cloning an agent, but can't gain unauthorized access to any connections the original user has set up. ## Update memory Your agent can remember information from previous conversations and use it to make better decisions in future conversations. By default, your agent will require approval to update its memories folder. To disable this requirement for your agent: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to your agent's inbox. 2. Next to the agent name, click the **Edit Agent** icon. 3. In the top right corner, click the **Settings** icon. 4. In the **Memory** section, toggle **Require approval to update memories** to off. ## Use the agent programmatically You can use the [LangGraph SDK](/langsmith/reference) to connect to your agent through code. To view the code snippets needed to call your agent programmatically: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to your agent's inbox. 2. Next to the agent name, click the **Edit Agent** icon. 3. In the top right corner, click the **Settings** icon. 4. Click the **View code snippets** button. 5. Copy the pre-populated code snippets for your agent. For more information, see [Call agents from code](/langsmith/agent-builder-code). ## Pause agent To pause an agent, pause its trigger: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to your agent's inbox. 2. Next to the agent name, click the **Edit Agent** icon. 3. In the graph view, click the **Pause** button in the **Triggers** box. 4. Click **Save Changes**. To resume, click the **Resume triggers** button in the **Triggers** box. ## Delete agent To permanently delete an agent: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to your agent's inbox. 2. Next to the agent name, click the **Edit Agent** icon. 3. In the top right corner, click the **Settings** icon. 4. Click the **Delete Agent** button. 5. To confirm the deletion, click the **Delete** button. This action cannot be undone. It will permanently delete the agent, all threads linked to the agent, and unlink any attached triggers. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-manage-agent-settings.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # LangSmith Tool Server Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-mcp-framework The LangSmith Tool Server is a standalone MCP framework for building and deploying tools with built-in authentication and authorization. Use the Tool Server when you want to: * [Create custom tools](#create-a-custom-toolkit) that integrate with LangSmith's [Agent Auth](/langsmith/agent-auth) for OAuth authentication * [Build an MCP gateway](#use-as-an-mcp-gateway) for agents you're building yourself (outside of Agent Builder) If you're using [Agent Builder](/langsmith/agent-builder), you don't need to interact with the Tool Server directly. Agent Builder provides [built-in tools](/langsmith/agent-builder-tools) and supports [remote MCP servers](/langsmith/agent-builder-tools#using-remote-mcp-servers) without requiring Tool Server setup. However, you can configure the associated tool server instance as an MCP server, which will allow you to use your custom MCP servers in your agent. Download the [PyPi package](https://pypi.org/project/langsmith-tool-server/) to get started. ## Create a custom toolkit Install the LangSmith Tool Server and LangChain CLI: ```bash theme={null} pip install langsmith-tool-server pip install langchain-cli-v2 ``` Create a new toolkit: ```bash theme={null} langchain tools new my-toolkit cd my-toolkit ``` This creates a toolkit with the following structure: ``` my-toolkit/ ├── pyproject.toml ├── toolkit.toml └── my_toolkit/ ├── __init__.py ├── auth.py └── tools/ ├── __init__.py └── ... ``` Define your tools using the `@tool` decorator: ```python theme={null} from langsmith_tool_server import tool @tool def hello(name: str) -> str: """Greet someone by name.""" return f"Hello, {name}!" @tool def add(x: int, y: int) -> int: """Add two numbers.""" return x + y TOOLS = [hello, add] ``` Run the server: ```bash theme={null} langchain tools serve ``` Your tool server will start on `http://localhost:8000`. ## Call tools via MCP protocol Below is an example that lists available tools and calls the `add` tool: ```python theme={null} import asyncio import aiohttp async def mcp_request(url: str, method: str, params: dict = None): async with aiohttp.ClientSession() as session: payload = {"jsonrpc": "2.0", "method": method, "params": params or {}, "id": 1} async with session.post(f"{url}/mcp", json=payload) as response: return await response.json() async def main(): url = "http://localhost:8000" tools = await mcp_request(url, "tools/list") print(f"Tools: {tools}") result = await mcp_request(url, "tools/call", {"name": "add", "arguments": {"a": 5, "b": 3}}) print(f"Result: {result}") asyncio.run(main()) ``` ## Use as an MCP gateway The LangSmith Tool Server can act as an MCP gateway, aggregating tools from multiple MCP servers into a single endpoint. Configure MCP servers in your `toolkit.toml`: ```toml theme={null} [toolkit] name = "my-toolkit" tools = "./my_toolkit/__init__.py:TOOLS" [[mcp_servers]] name = "weather" transport = "streamable_http" url = "http://localhost:8001/mcp/" [[mcp_servers]] name = "math" transport = "stdio" command = "python" args = ["-m", "mcp_server_math"] ``` All tools from connected MCP servers are exposed through your server's `/mcp` endpoint. MCP tools are prefixed with their server name to avoid conflicts (e.g., `weather_get_forecast`, `math_add`). ## Authenticate ### OAuth for third-party APIs For tools that need to access third-party APIs (like Google, GitHub, Slack, etc.), you can use OAuth authentication with [Agent Auth](/langsmith/agent-auth). Before using OAuth in your tools, you'll need to configure an OAuth provider in your LangSmith workspace settings. See the [Agent Auth documentation](/langsmith/agent-auth) for setup instructions. Once configured, specify the `auth_provider` in your tool decorator: ```python theme={null} from langsmith_tool_server import tool, Context from google.oauth2.credentials import Credentials from googleapiclient.discovery import build @tool( auth_provider="google", scopes=["https://www.googleapis.com/auth/gmail.readonly"], integration="gmail" ) async def read_emails(context: Context, max_results: int = 10) -> str: """Read recent emails from Gmail.""" credentials = Credentials(token=context.token) service = build('gmail', 'v1', credentials=credentials) # ... Gmail API calls return f"Retrieved {max_results} emails" ``` Tools with `auth_provider` must: * Have `context: Context` as the first parameter * Specify at least one scope * Use `context.token` to make authenticated API calls ### Custom request authentication Custom authentication allows you to validate requests and integrate with your identity provider. Define an authentication handler in your `auth.py` file: ```python theme={null} from langsmith_tool_server import Auth auth = Auth() @auth.authenticate async def authenticate(authorization: str = None) -> dict: """Validate requests and return user identity.""" if not authorization or not authorization.startswith("Bearer "): raise auth.exceptions.HTTPException( status_code=401, detail="Unauthorized" ) token = authorization.replace("Bearer ", "") # Validate token with your identity provider user = await verify_token_with_idp(token) return {"identity": user.id} ``` The handler runs on every request and must return a dict with `identity` (and optionally `permissions`). *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-mcp-framework.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Pricing FAQ Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-pricing-faq View our [Pricing](https://www.langchain.com/pricing) page for more information on our pricing plans. ## What is an Agent Builder run? An Agent Builder Run is a complete invocation of an Agent Builder agent, initiated by the receipt of a message or event, whether triggered automatically or sent manually. An Agent Builder Run includes any message delivered to the agent through configured triggers (including third-party integrations or other connected services) as well as messages sent directly through the Agent Builder user interface (for example, via the chat interface). An Agent Builder Run is counted if the invocation succeeds or is interrupted. Resuming execution after a human-in-the-loop interruption constitutes a separate Agent Builder Run. An execution failure does not count as an Agent Builder Run. ## Are model costs included with Agent Builder pricing? No. Model usage is billed separately by your model provider. Agent Builder lets you choose the model you want (for example, Anthropic, OpenAI, Gemini, or another provider) and connect it using your provider API key. For more information on configuring models, see the [Agent Builder setup](/langsmith/agent-builder-setup#required-model-key) page. ## Are agent tools included with Agent Builder pricing? Agent Builder includes built-in tools and supports connecting third-party tools via a remote MCP server. Third-party tools typically require you to authenticate with your account, and any fees or usage charges are billed by the third-party provider. For more information on setting up tool keys, see the [Agent Builder setup](/langsmith/agent-builder-setup#optional-tool-keys) page. ## Are Agent Builder runs automatically traced in LangSmith, and do they count toward billing? Yes. Every Agent Builder run is automatically traced in LangSmith. These traces are attributed to the user's account and count toward usage-based billing under the customer's LangSmith plan. ## How do I disable Agent Builder? If you are on a Self-Hosted LangSmith instance, you can disable Agent Builder by setting the following to `false` in your `values.yaml`: ```yaml theme={null} backend: agentBootstrap: enabled: false config: agentBuilder: enabled: false agentBuilderToolServer: enabled: false agentBuilderTriggerServer: enabled: false ``` If you are on cloud LangSmith, [reach out to our Support team](https://support.langchain.com/) to disable Agent Builder. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-pricing-faq.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Quickstart Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-quickstart Build an agent from a template In this quickstart, you'll use the pre-defined **Email Assistant** [template](/langsmith/agent-builder-templates) that organizes and manages your inbox for you. * Select a different template. You'll interact with your agent through chat, just like texting a helpful assistant. ## Before you start You'll need: * A LangSmith account ([sign up here](https://smith.langchain.com/agents?skipOnboarding=true)). * A Gmail account. * A Google calendar. * An OpenAI or Anthropic API key (Step 1 will show you how to get one). ## 1. Get your model API key Your agent needs an API key to connect to an AI model. The AI model is what allows your agent to understand and respond to your requests. 1. Go to [platform.openai.com/api-keys](https://platform.openai.com/api-keys). 2. Click **Create new secret key**. 3. Give it a name like "Agent Builder". 4. Copy the key (it starts with `sk-`). 5. Save it somewhere safe, you'll need it in Step 2. 1. Go to [console.anthropic.com/settings/keys](https://console.anthropic.com/settings/keys). 2. Click **Create Key**. 3. Give it a name like "Agent Builder". 4. Copy the key (it starts with `sk-ant-`). 5. Save it somewhere safe, you'll need it in Step 2. Both services charge based on usage. ## 2. Add your API key to LangSmith Now you'll add your API key to LangSmith so your agents can use it: 1. Go to [smith.langchain.com](https://smith.langchain.com). 2. Click the **Settings** icon in the bottom left. Click the **Secrets** tab at the top. 1. Click **Add secret**. 2. For **Key**, enter: * `OPENAI_API_KEY` (if using OpenAI) * `ANTHROPIC_API_KEY` (if using Anthropic) 3. For **Value**, paste the API key you copied in Step 1. 4. Click **Save secret**. Your agent now has access to an AI model to understand and respond to your requests. Next, you'll create your agent. ## 3. Create your agent 1. In the [LangSmith UI](https://smith.langchain.com), click **Switch to Agent Builder** at the top of the left-hand navigation. 1. Select **Templates** in the left-hand navigation. 2. Select **Email Assistant** template. 3. Click **Use this template**. If you don't want to start with a template, you have two other options. From the **+ New Agent** page: * **Chat**: Use the chat interface to describe your agent, and it will help you create it step-by-step. * **Manually**: Select **Create manually instead** to build your agent without any pre-filled responses on the configuration page. Your agent will ask you to connect your Google accounts: 1. Click **Connect**. 2. Sign in with your Google account. 3. Review permissions and click **Allow**. 4. You'll be redirected back to LangSmith where your agent will be created. Your agent only accesses your accounts when working on tasks you give it. You can revoke access anytime in your Google account settings. ## 4. View the agent template At this point, you can review the template instructions for the email assistant. If needed, you can make adjustments to the instructions. If you made any changes, click **Save changes**. 1. In the right-hand panel of the configuration page, select the **Test Chat** tab. 2. Try out the email assistant in the chat interface, for example: > *Apply a "Review" label to emails that I receive, which require some kind of review from me* Your agent will start work and provide a **Continue** option for each step that requires your approval. Test chat output view with response including approvals for Gmail tool. Test chat output view with response including approvals for Gmail tool. 3. As you test out the agent, you can make edits to the instructions, or add tools that you may need. Click **Save changes** when you're happy with the results. ## Edit your agent You may want to update your agent's instructions or include more tools. You can directly chat with your agent to ask for updates, or you can: 1. From **My Agents** in the left-hand navigation, select the agent you want to edit. 2. Select **Edit Agent**. From the agent's edit page, you can: * Add tools with **+ Add tool** to connect more apps and services like Slack, GitHub, or Linear. * Add further helpers with **+ Add sub-agent** to break complex tasks into specialized sub-tasks. * Request pauses for reviews on existing tools. * Modify existing tools. * Explore features that can trigger your agent to start a task. ## Next steps Now that you've created your first agent, here's what to explore: Explore pre-built agents for common tasks Run your agent automatically with triggers (Slack, email, schedules) Add Slack, GitHub, Linear, and more Use sub-agents to break down big tasks *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-quickstart.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Remote MCP servers Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-remote-mcp-servers Connect Agent Builder to popular remote MCP servers You can connect Agent Builder to remote MCP servers to extend your agents with additional tools and integrations. This page covers how to add custom MCP servers and provides configuration details for popular remote servers. An [*MCP (Model Context Protocol) server*](https://modelcontextprotocol.io/docs/getting-started/intro) exposes tools that an agent can call at runtime. A remote MCP server: * Runs outside of LangSmith (usually over HTTPS). * Owns its own authentication and authorization. * Acts as a bridge between your agent and an external system. LangSmith Agent Builder doesn't execute these tools itself, it forwards requests to the MCP server and returns the results to the agent. ### How it works * Agent Builder discovers tools from remote MCP servers via the standard MCP protocol. * Headers configured in your workspace are automatically attached when fetching tools or calling them. Headers are key-value pairs sent with every HTTP request to your MCP server. They're commonly used for authentication (like API keys or bearer tokens), but can also provide configuration information, content types, or custom metadata. * Tools from remote servers are available alongside built-in tools in Agent Builder. **Runtime**: Agent Builder automatically connects to your MCP server and uses its tools. ```mermaid theme={null} sequenceDiagram participant Agent as Agent Builder participant MCP as Remote MCP Server Agent->>MCP: Discover available tools
(with configured headers) MCP-->>Agent: Return tool list Note over Agent,MCP: Later, when agent needs a tool... Agent->>MCP: Call tool
(with configured headers) MCP-->>Agent: Return result ``` The following sections show you how to connect a remote MCP server to Agent Builder: * [General configuration](#general-configuration): Step-by-step instructions for connecting any remote MCP server with authentication headers. Use this if you're familiar with MCP servers and want a quick reference. * [Example: Connecting a custom MCP server](#example-connecting-a-custom-mcp-server): A detailed walkthrough using a GitHub-based MCP server as an example. Use this if you want to see a complete end-to-end example with specific authentication details. ## Add a remote MCP server Configure remote MCP servers in your LangSmith [workspace](/langsmith/administration-overview#workspaces): In the [LangSmith UI](https://smith.langchain.com), select **Settings** in the lower left sidebar, then choose the **MCP Servers** tab. You can also add MCP servers by navigating to the **Agent Builder > Tools** tab and clicking the **+ Add service** button. Click **Add server** and enter: * **Name**: A descriptive name for the server * **URL**: The MCP server endpoint URL Select an authentication type based on the server's requirements: * **Headers**: Add key-value pairs sent with every request. The most common pattern is using an Authorization bearer token: * **Key**: `Authorization` * **Value**: `Bearer API_KEY` You can add multiple headers if your MCP server requires additional authentication or configuration parameters. Each header key-value pair is sent with every request to the server. * **OAuth 2.1 (Auto)**: Select this for servers that support OAuth via dynamic client registration. You'll be prompted to log in with your account for that service. * **OAuth 2.1 (Manual)**: Select this for servers that support OAuth, but require specifying the client ID/secret beforehand. OAuth providers used in this flow must have **PKCE** enabled. For specific authentication details, see the configuration details for each [supported server](#supported-servers). Click **Save server**. Agent Builder will automatically discover available tools from your MCP server and make them available in your agents. The configured headers are applied to both tool discovery requests and tool execution requests. ## Update your MCP server URL Changing the URL of a custom MCP server will break any agents that use tools from that server. Agent Builder stores tool references by MCP server URL. If you update the URL of a custom MCP server, existing agents will fail when attempting to call those tools because the stored URL no longer matches. To update an MCP server URL: 1. Update your MCP server URL in the workspace settings. 2. For each agent using tools from that server: * Remove the affected tools from the agent configuration. * Re-add the tools (they will now reference the new URL). 3. Test the agent to confirm tools work correctly. ## Example: Connect a custom MCP server Here's a practical example of connecting Agent Builder to a GitHub MCP server that requires authentication: The MCP server needs permission to access GitHub on your behalf. You’ll do this using a **GitHub Personal Access Token (PAT)**. 1. Go to **GitHub → Settings → Developer settings**. 2. Open **Personal access tokens**. 3. Create a **Fine-grained token** (recommended). Grant **read-only** permissions: * **Contents**: Read * **Issues**: Read * **Pull requests**: Read Once created, **copy the token**. You won’t be able to see it again. Treat this token like a password. You can rotate or revoke it at any time without changing your agent. Remote MCP servers typically authenticate using HTTP headers. For the GitHub MCP server, the required headers look like this: ```http theme={null} Authorization: Bearer ghp_xxxxxxxxxxxxxxxxxxxx Content-Type: application/json User-Agent: langsmith-agent-builder ``` * Authorization proves who you are. * The MCP server validates the token. * Every tool call from the agent includes these headers. Agent Builder will attach these headers automatically once configured. In the [LangSmith UI](https://smith.langchain.com): 1. Navigate to **Settings** > **Workspaces** > **Secrets**. 2. Click **Add secret**. 3. Name: `GITHUB_TOKEN` (or any descriptive name). 4. Value: Your authentication token. 5. Save the secret. In **Settings** > **MCP Servers**: 1. Click **Add server**. 2. Add a **Name** for the MCP server. 3. **URL**: Enter your MCP server URL (e.g., `https://mcp-github.example.com`) 4. Add authentication header: * Key: `Authorization` * Value: `Bearer {{GITHUB_TOKEN}}` 5. Save the configuration. The tools from your MCP server are now available in Agent Builder. When you create or edit an agent, you'll see these tools alongside the built-in tools. All requests to your MCP server will include the authentication header automatically. Once connected, the workflow for this example looks like this: 1. The agent decides it needs GitHub data. 2. It selects a tool exposed by the MCP server. 3. LangSmith forwards the request to the remote MCP server. 4. The server authenticates using your token. 5. GitHub data is fetched and returned. 6. The agent receives structured results and continues reasoning. Different MCP servers may use different authentication methods: * `Authorization: Bearer {{TOKEN}}` (most common) * `X-API-Key: {{API_KEY}}` * Custom headers specific to your implementation * Multiple headers for authentication Always check your MCP server's documentation for the correct authentication header format. ## Supported servers ### Arcade [Arcade](https://arcade.dev) provides a gateway for connecting to various tools and services. **Configuration details** | Setting | Value | | ------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | **URL** | Dynamic. Create an MCP gateway in your [Arcade dashboard](https://arcade.dev), select the tools you want, then copy the generated URL. | | **Auth type** | Headers or OAuth 2.1 (Auto). See below for specific details. | **Option 1: Headers authentication** Add the following headers: | Header | Value | | ---------------- | ----------------------- | | `Authorization` | `Bearer ARCADE_API_KEY` | | `Arcade-User-Id` | Your email address | **Option 2: OAuth authentication** 1. Select **OAuth 2.1 (Auto)** as the auth type when adding the server. 2. Log in with your Arcade account when prompted. To learn more about Arcade MCP integration, see the [Arcade documentation](https://docs.arcade.dev/en/resources/integrations). ### Parallel [Parallel](https://parallel.ai) provides search and task automation tools. **Configuration details** | Setting | Value | | ------------- | ------------------------------------ | | **URL** | `https://search-mcp.parallel.ai/mcp` | | **Auth type** | Headers | Add the following header: | Header | Value | | --------------- | ------------------------- | | `Authorization` | `Bearer PARALLEL_API_KEY` | For more information, see the [Parallel documentation for search MCP](https://docs.parallel.ai/integrations/mcp/search-mcp) and [task MCP](https://docs.parallel.ai/integrations/mcp/task-mcp). ### Notion [Notion](https://notion.com) provides tools for interacting with your Notion workspace. **Configuration details** | Setting | Value | | ------------- | ---------------------------- | | **URL** | `https://mcp.notion.com/mcp` | | **Auth type** | OAuth 2.1 (Auto) | 1. Select **OAuth 2.1 (Auto)** as the auth type when adding the server. 2. Log in with your Notion account when prompted. For more information, see the [Notion MCP documentation](https://developers.notion.com/docs/mcp). *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-remote-mcp-servers.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Manage Agent Builder Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-self-hosted [Agent Builder](/langsmith/agent-builder) allows users to create, deploy, and manage AI agents directly within LangSmith with no code. An agent created in Agent Builder is essentially an assistant on a LangSmith Deployment. This page explains how to manage Agent Builder on a [self-hosted LangSmith instance](/langsmith/self-hosted). Agent Builder is available on [LangSmith Self-Hosted v0.13](https://changelog.langchain.com/announcements/langsmith-self-hosted-v0-13) and later. Self-hosted is an add-on to the Enterprise plan. For more details, refer to [Pricing](https://www.langchain.com/pricing). [Contact our sales team](https://www.langchain.com/contact-sales) if you want to get a license key to trial LangSmith in your environment. ## Prerequisites Before enabling Agent Builder, you must complete the following setup steps: 1. Install the base LangSmith platform: * [Install on Kubernetes](/langsmith/kubernetes). * [Install on Docker](/langsmith/docker). 2. [Enable LangSmith Deployment](/langsmith/deploy-self-hosted-full-platform) (agent deployment capabilities). ## Components Agent Builder consists of the following components: * `agentBootstrap`: Job that deploys the LangSmith Deployment (agent) needed for Agent Builder. * `agentBuilder` * `toolServer`: Provides MCP tool execution for agents. * `triggerServer`: Handles webhooks and scheduled triggers. * `agent`: The main agent that will handle agent generation and where all the assistants will be created. ## Enable Agent Builder To enable Agent Builder, add the following to your `values.yaml`: ```yaml theme={null} backend: agentBootstrap: enabled: true config: agentBuilder: enabled: true encryptionKey: "" agentBuilderToolServer: enabled: true agentBuilderTriggerServer: enabled: true ``` ### Generate an encryption key Agent Builder requires a Fernet encryption key to securely store secrets. Generate one using Python: ```bash theme={null} python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" ``` You can store the encryption key in a predefined Kubernetes secret using the `agent_builder_encryption_key` parameter. See [Use an existing secret](/langsmith/self-host-using-an-existing-secret#parameters) for details. ## Enable OAuth tools and triggers (optional) To enable OAuth-based tools (like Gmail, Slack, GitHub), configure the `oauthProviderOrgId` and add provider IDs for each integration you want to enable. You can enable any combination of providers. ### Available providers | Provider | Tools enabled | Trigger enabled | Setup guide | | ----------------------- | ----------------------------------------------- | --------------- | ------------------------------------- | | `githubOAuthProvider` | GitHub | - | [See below](#github-oauth-provider) | | `googleOAuthProvider` | Gmail, Google Calendar, Google Sheets, BigQuery | Gmail | [See below](#google-oauth-provider) | | `linearOAuthProvider` | Linear | - | [See below](#linear-oauth-provider) | | `linkedinOAuthProvider` | LinkedIn | - | [See below](#linkedin-oauth-provider) | | `slackOAuthProvider` | Slack | Slack | [See below](#slack-oauth-provider) | ### General configuration Add the following to your `values.yaml`. Include only the providers you need. ```yaml theme={null} backend: agentBootstrap: enabled: true config: agentBuilder: # Organization ID where OAuth providers are configured oauthProviderOrgId: "" oauth: # Add provider IDs for integrations you want to enable, # Slack requires additional configuration slackOAuthProvider: "" slackSigningSecret: "" slackBotId: "" googleOAuthProvider: "" linkedinOAuthProvider: "" linearOAuthProvider: "" githubOAuthProvider: "" ``` The provider ID must be unique and cannot end with `-agent-builder` or `-oauth-provider`. ### Provider setup guides To enable GitHub OAuth for Agent Builder, you need to create a GitHub OAuth app and configure it with the required permissions. Go to [GitHub Settings > Developer settings > OAuth Apps](https://github.com/settings/developers) and click **New OAuth App**. Fill in the application details. You can name it whatever you like and leave the default checkbox settings. Give the app read/write permissions to **Pull Requests** and **Issues**. Set the callback URL, replacing `` with your LangSmith hostname and `` with your provider ID: ``` https:///host-oauth-callback/ ``` Click **Generate a new client secret** and copy both the **Client ID** (shown at the top of the app page) and the **Client Secret**. In LangSmith, go to **Settings > OAuth Providers** and add a new provider: * **Client ID**: from GitHub app * **Client Secret**: from GitHub app * **Authorization URL**: `https://github.com/login/oauth/authorize` * **Token URL**: `https://github.com/login/oauth/access_token` * **Provider ID**: Unique string, for example: `github` Add the following to your `values.yaml` and deploy: ```yaml theme={null} config: agentBuilder: oauthProviderOrgId: "" oauth: githubOAuthProvider: "" ``` After creating the app, you need to: 1. Authenticate the app to your GitHub account. 2. Go to **Settings > Applications > Installed GitHub Apps** and install the app on the repositories you want it to access. For private repositories, you must explicitly install the app on each repository you want Agent Builder to access. To enable Google OAuth for Agent Builder, you need to create an OAuth client in GCP and configure it with the required URLs and credentials. Create a new OAuth client app (Web application) in [Google Cloud Console](https://console.cloud.google.com/apis/credentials). Add the following URLs to your OAuth client, replacing `` with your LangSmith hostname and `` with the provider ID you'll use (e.g., `google`): **Authorized JavaScript origins:** * `https://` **Authorized redirect URIs:** * `https:///api-host/v2/auth/callback/` * `https:///host-oauth-callback/` Copy the **Client ID** and **Client Secret** from the GCP OAuth app. In LangSmith, go to **Settings > OAuth Providers** and add a new provider: * **Client ID**: Find in GCP * **Client Secret**: Find in GCP * **Authorization URL**: `https://accounts.google.com/o/oauth2/auth` * **Token URL**: `https://oauth2.googleapis.com/token` * **Provider ID**: Unique string, for example: `google` Add the LangSmith OAuth provider ID to your `values.yaml` and deploy: ```yaml theme={null} config: agentBuilder: oauthProviderOrgId: "" oauth: googleOAuthProvider: "" ``` To enable Linear OAuth for Agent Builder, you need to create a Linear OAuth app and configure it with the required credentials. Go to [Linear Settings > API > Applications](https://linear.app/settings/api/applications/new) and create a new OAuth application. Set the callback URL, replacing `` with your LangSmith hostname and `` with your provider ID: ``` https:///host-oauth-callback/ ``` After creating the app, copy the **Client ID** and **Client Secret**. In LangSmith, go to **Settings > OAuth Providers** and add a new provider: * **Client ID**: from Linear app * **Client Secret**: from Linear app * **Authorization URL**: `https://linear.app/oauth/authorize` * **Token URL**: `https://api.linear.app/oauth/token` * **Provider ID**: Unique string, for example: `linear` Add the following to your `values.yaml` and deploy: ```yaml theme={null} config: agentBuilder: oauthProviderOrgId: "" oauth: linearOAuthProvider: "" ``` To enable LinkedIn OAuth for Agent Builder, you need to create a LinkedIn OAuth app and configure it with the required credentials. Go to [linkedin.com/developers/apps](https://www.linkedin.com/developers/apps/) and create a new app. In your app settings, go to the **Auth** tab. Add the following redirect URI, replacing `` with your LangSmith hostname and `` with your provider ID: ``` https:///host-oauth-callback/ ``` Copy the **Client ID** and **Client Secret** from the Auth tab. In LangSmith, go to **Settings > OAuth Providers** and add a new provider: * **Client ID**: from LinkedIn app * **Client Secret**: from LinkedIn app * **Authorization URL**: `https://www.linkedin.com/oauth/v2/authorization` * **Token URL**: `https://www.linkedin.com/oauth/v2/accessToken` * **Provider ID**: Unique string, for example: `linkedin` Add the following to your `values.yaml` and deploy: ```yaml theme={null} config: agentBuilder: oauthProviderOrgId: "" oauth: linkedinOAuthProvider: "" ``` To enable Slack OAuth for Agent Builder, you need to create a Slack app and configure it with the required scopes, credentials, and event subscriptions. Go to [api.slack.com/apps](https://api.slack.com/apps) and click **Create New App**. In **OAuth & Permissions**, add the following scopes: * `channels:history` * `channels:read` * `chat:write` * `groups:history` * `groups:read` * `im:history` * `im:read` * `im:write` * `mpim:history` * `team:read` * `users:read` * `users:read.email` Copy the **Client ID**, **Client Secret**, and **Signing Secret** from the Slack app settings. In LangSmith, go to **Settings > OAuth Providers** and add a new provider: * **Client ID**: Find in Slack app * **Client Secret**: Find in Slack app * **Authorization URL**: `https://slack.com/oauth/v2/authorize` * **Token URL**: `https://slack.com/api/oauth.v2.access` * **Provider ID**: Unique string, for example: `slack` Add the following redirect URI to your Slack app under **OAuth & Permissions > Redirect URLs**, replacing `` with your LangSmith hostname and `` with your provider ID (e.g., `slack`): ``` https:///host-oauth-callback/ ``` 1. Get the bot token from **OAuth & Permissions** in your Slack app. 2. Run the following command: ```bash theme={null} curl -X POST https://slack.com/api/auth.test \ -H "Authorization: Bearer " ``` 3. Copy the `bot_id` from the response. Add the following to your `values.yaml` and deploy: ```yaml theme={null} config: agentBuilder: oauthProviderOrgId: "" oauth: slackOAuthProvider: "" slackSigningSecret: "" slackBotId: "" ``` 1. After deployment, go to **Event Subscriptions** in your Slack app and enable events. 2. Set the **Request URL** to: ``` https:///v1/triggers/webhooks/d809e66e-0000-4000-8000-000000000002 ``` 3. Add the following bot events: * `message.channels` * `message.groups` * `message.im` * `message.mpim` 1. Add the Slack bot to the channel you want it to read from. 2. When configuring the Slack tool or trigger in Agent Builder, provide the **channel ID** and **channel name**. ## Disable Agent Builder To disable Agent Builder, set the following to `false` in your `values.yaml`: ```yaml theme={null} config: agentBuilder: enabled: false ``` *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-self-hosted.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Workspace setup Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-setup Add required workspace secrets for models and tools used by Agent Builder. This page lists the workspace secrets you need to add before using Agent Builder. Add these in your LangSmith workspace settings under Secrets. Keep values scoped to your workspace and avoid placing credentials in prompts or code. ## Add workspace secrets In the [LangSmith UI](https://smith.langchain.com), ensure that you have an LLM API key set as a [workspace secret](/langsmith/administration-overview#workspace-secrets) (either Anthropic or OpenAI API key). 1. Navigate to **Settings** and then move to the **Secrets** tab. 2. Select **Add secret** and enter either `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` as the **name**, and your API key as the **value**. 3. Select **Save secret**. When adding workspace secrets in the LangSmith UI, make sure the secret keys match the environment variable names expected by your model provider. ## Secret types ### Required model key For Agent Builder to make API calls to LLMs, you need to set an OpenAI or Anthropic API key as a workspace secret. The agent graphs load this key from workspace secrets for inference. Agent Builder supports custom models per agent. See [Custom models](/langsmith/agent-builder-essentials#custom-models) for more information. ### Agent builder specific secrets Secrets prefixed with `AGENT_BUILDER_` are prioritized over workspace secrets within Agent Builder. This way, you can better track the usage of Agent Builder vs other parts of LangSmith which use the same secrets. If you have both `OPENAI_API_KEY` and `AGENT_BUILDER_OPENAI_API_KEY`, the `AGENT_BUILDER_OPENAI_API_KEY` secret will be used. ### Optional tool keys Add keys for any tools you enable. These are read from workspace secrets at runtime. * `EXA_API_KEY`: Required for Exa search tools (general web and LinkedIn profile search). * `TAVILY_API_KEY`: Required for Tavily web search. * `TWITTER_API_KEY` and `TWITTER_API_KEY_SECRET`: Required for Twitter/X read operations (app-only bearer). Posting/media upload is not enabled. ### MCP server configuration Agent Builder can pull tools from one or more remote [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers. Configure MCP servers and headers in your [workspace](/langsmith/administration-overview#workspaces) settings. Agent Builder automatically discovers tools and applies the configured headers when calling them. For more information, refer to the [Remote MCP servers](/langsmith/agent-builder-remote-mcp-servers) page. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-setup.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Integrate Slack with an agent Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-slack-app Connect the LangSmith Agent Builder to your Slack workspace to let your agents communicate with users in Slack. The LangSmith Agent Builder App for Slack integrates your agents with Slack for secure, context-aware communication inside your Slack workspace. After integrating, your agents will be able to: * Send direct messages. * Post to channels. * Read thread messages. * Reply in threads. * Read conversation history. The LangSmith Agent Builder App for Slack itself does not have any direct pricing. However, agent runs and traces are billed through the [LangSmith platform](https://smith.langchain.com) according to your organization's plan. For current pricing information, see the [LangSmith pricing page](https://www.langchain.com/pricing). ## How it works When a message is posted in your monitored Slack channel: 1. Slack sends an event to LangSmith. 2. The trigger activates your agent with the message content. 3. Your agent processes the message and uses Slack tools to respond. 4. The response appears in Slack (in the same thread if replying to a thread). Your agent receives the full thread context when responding to threaded messages, so it can provide contextually relevant responses. ## Prerequisites * An existing agent in Agent Builder (see [Quickstart](/langsmith/agent-builder-quickstart) to create one) * Admin access to a Slack workspace or permission to install apps ## Connect to Slack First, authorize LangSmith to access your Slack workspace and invite the bot to your channel. 1. In LangSmith, navigate to **Agent Builder**. 2. Select your agent from **My Agents**. 3. Click **Edit Agent**. 1. Scroll down to the **Triggers** section. 2. Click **+ Add trigger**. 3. Select **Slack - Message Received**. 1. Click **Connect** to authorize the Slack connection. 2. Sign in to your Slack workspace. 3. Review the permissions and click **Allow**. 4. You'll be redirected back to LangSmith. Agent Builder requires the following permissions to your Slack workspace: * **Send messages** - Send direct messages and post to channels * **Read messages** - Read channel history and thread messages * **View channels** - Access basic channel information * **View users** - Look up user information for messaging These permissions enable agents to communicate effectively within your Slack workspace. Before selecting a channel, invite the bot to the channel you want to use. In Slack, go to that channel and type: ```txt theme={null} /invite @LangSmith Agent Builder ``` 1. Back in LangSmith, choose the Slack channel you invited the bot to. 2. Click **Save**. Your agent will now be triggered whenever a message is posted in that channel. ## Add Slack tools Tools let your agent take actions. To respond in Slack, you need to add Slack tools. You can also ask your agent to add these tools itself! In the agent chat, try: "Add the Slack tools so you can respond to messages." 1. In the agent editor, scroll to the **Tools** section. 2. Click **+ Add tool**. 3. Search for "Slack" and add the tools you need: * **slack\_send\_channel\_message** - Post messages to a channel * **slack\_reply\_to\_message** - Reply in a thread * **slack\_write\_private\_message** - Send direct messages * **slack\_read\_channel\_history** - Read recent messages * **slack\_read\_thread\_messages** - Read thread replies If prompted, click **Connect** to authorize the Slack tools. This may use the same authorization from Step 1. Click **Save changes** to save your agent configuration. ## Configure agent behavior (optional) Your agent needs to know how to handle incoming Slack messages. You can update its instructions by prompting it directly. In the agent chat, try something like: ``` Update your instructions to handle the Slack Trigger and Slack Tools for bidirectional communication ``` Adjust the instructions based on your use case - for example, you might want the agent to only respond to certain types of questions, or to pull information from specific sources before replying. ## Test the integration In your Slack channel, send a message to test the agent: > *Hello, can you help me?* Your agent should respond in the channel. You can view the agent's activity in the **Feed** tab in Agent Builder. If your agent doesn't respond: * Verify the bot was invited to the channel * Check the **Feed** tab for any errors * Ensure the trigger is not paused (check the toggle in the Triggers section) ## Next steps Connect additional services to your agent Set up email, schedule, or webhook triggers Start from a pre-built agent template *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-slack-app.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Templates Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-templates Start faster with curated Agent Builder templates and customize tools, prompts, and triggers. Agent Builder includes [starter templates](https://www.langchain.com/templates) to help you create agents quickly. Templates include predefined instructions, [tools](/langsmith/agent-builder-tools), and [triggers](/langsmith/agent-builder-essentials#triggers) (if applicable) for common use cases. You can use templates as-is, or as a baseline to customize. If you're new to Agent Builder, start with the step-by-step [quickstart](/langsmith/agent-builder-quickstart) to build your first agent using a template. ## Features Templates are pre-configured agents designed for specific use cases. Each template includes the following components: ### Pre-configured tools Templates come with a curated set of [tools](/langsmith/agent-builder-essentials#tools) that enable the agent to perform specific actions. For example, an email assistant template includes tools for reading, sending, and organizing emails. Tools connect to external services through OAuth authentication, allowing your agent to interact with apps like Gmail, Slack, or Linear. For a complete list, refer to [Supported tools](/langsmith/agent-builder-tools). ### System instructions Each template includes a *system prompt* (also called *instructions*) that defines the agent's behavior, personality, and capabilities. The system prompt guides how the agent interprets user requests and uses its available tools. You can customize these instructions to match your specific needs. ### Triggers (optional) Some templates include [triggers](/langsmith/agent-builder-essentials#triggers) that allow agents to respond to external events automatically. For example, a Slack bot template might include a trigger that activates when someone mentions the agent in a channel. Triggers enable proactive agent behavior beyond chat-based interactions. ### Cloning and customization Templates serve as starting points that you clone to create your own agent. When you clone a template, you create an independent copy that you can customize without affecting the original. You can modify prompts, add or remove tools, attach different triggers, and switch models to tailor the agent to your requirements. ## Available templates A daily agent that scans your calendar and delivers a concise briefing with meeting details and important context. Automate email triage with an agent that flags important emails, drafts and sends replies, and schedules meetings. Automate recruiting with an agent that digests candidate requirements, adapts to feedback, and outputs a candidate list. An agent that tracks top AI discussions from X lists and Hacker News, and delivers a daily Slack message with important updates. For more information, see [Templates](https://www.langchain.com/templates). *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-templates.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Built-in tools Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-tools You can access a variety of tools in Agent Builder. Use built-in tools to give your agents access to email, calendars, chat, project management, code hosting, spreadsheets/BI, search, social, and general web utilities. Google, Slack, Linear, GitHub, and LinkedIn use OAuth. Exa, Tavily, Pylon, and Twitter/X use workspace secrets (API keys). Math and logic
  • Math operations
  • Generate random numbers
Analytics
  • Execute SQL queries
Search Deep Wiki
  • Read wiki structure and contents
  • Ask questions
Search our documentation PRs, issues, and content
  • List pull requests
  • Get pull request details
  • Create issues and pull requests
  • Comment on issues and pull requests
  • Read repository files and list directories
Read and send email
  • Read emails (optionally include body, filter with search)
  • Send email or reply to an existing message
  • Create draft emails
  • Mark messages as read
  • Get a conversation thread
  • Apply or create labels
  • List mailbox labels
Manage events
  • List events for a date
  • Get event details
  • Create new events
  • Update events
  • Delete events
Manage docs
  • Create new docs
  • Read docs
  • Append text
  • Replace text
Spreadsheets
  • Get spreadsheets
  • Create spreadsheets
  • Read ranges
  • Write ranges
  • Append rows
  • Clear ranges
Manage issues and teams
  • List teams and team members
  • List issues with filters
  • Get issue details
  • List labels
  • Create, update, or delete issues
Post to profile
  • Publish a post with optional image or link
Manage incidents
  • List alert group settings and get details
  • List incidents and get details
  • Get outlier incidents, past incidents, and related incidents
  • List services and get details
  • List teams, members, schedules, and users, and get details
  • List oncalls
  • Manage team members
  • Manage schedules
  • Manage event orchestration routers
Issue management
  • List issues
  • Get issue details
  • Update issues
  • Exa web search (optionally fetch page contents)
  • Exa LinkedIn profile search
  • Tavily web search
Send and read messages
  • Send a direct message to a user
  • Post a message to a channel
  • Reply in a thread
  • Read channel history
  • Read thread messages
Manage payments
  • Create and list customers, products, payments, and prices
  • Create, list, and finalize invoices
  • List, update, and delete subscriptions
  • Create and list coupons
  • Create list, and update disputes
  • Search and fetch Stripe resources
  • Search documentation
  • Read a tweet by ID
  • Read recent posts from a list
  • Read webpage text content
  • Extract image URLs and metadata
  • Notify user (for confirmations/updates)
You can also connect to remote MCP servers to give your agents access to additional tools. See [Remote MCP servers](/langsmith/agent-builder-remote-mcp-servers) for more information. ## Disconnect a tool To remove a tool from your agent: In the [LangSmith UI](https://smith.langchain.com), hover over **My Agents** in the left sidebar and click the settings icon. In the integrations section, locate the connected app you want to remove. Click **Disconnect** for that integration. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-tools.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Agent Builder webhooks Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-builder-webhooks Integrate agent publishing with external systems, CI/CD pipelines, or custom deployment workflows. When triggered, a webhook sends a complete package of your agent's configuration and files to the specified endpoint. **Security notes:** * Webhook URLs must use HTTPS. * Custom headers (e.g., API keys) are stored encrypted. * Publisher identity is included for audit trails. * Webhooks are only visible to agent owners. ## Set up a webhook 1. Navigate to **Settings > Agent Builder Webhooks**. 2. Click **Add Webhook**. 3. Configure: * **Name**: A descriptive name (e.g., "Publish Agent", "Deploy to Production"). * **URL**: Your HTTPS endpoint that will receive the webhook. * **Headers** (optional): Custom headers for authentication (stored encrypted). * **Form Schema** (optional): Define custom input fields users must fill when triggering. ## Trigger a webhook 1. Open your agent in the Agent Builder editor. 2. Click the **Settings** menu (gear icon). 3. Under **Webhooks**, click the webhook name. 4. Fill in any custom fields defined in the form schema. 5. Click **Run Webhook**. ## Webhook payload The webhook payload is a JSON object with the following fields: | Field | Description | | --------------------------------------------------- | ------------------------------------------------------------------ | | `action` | The name of the webhook. | | `input` | Values from custom form fields (empty object if no custom fields). | | `publisher` | User ID and email of the person triggering the webhook. | | `agent` | Agent name and description. | | [`tool_auth_requirements`](#tool-auth-requirements) | Authentication requirements for each tool the agent uses. | | [`files`](#zip-file-structure) | Base64-encoded ZIP containing all agent files. | | [`fields`](#custom-input-fields) | Custom input fields. | For example: ```json theme={null} { "action": "Webhook Name", "input": { "notes": "User-provided value", "environment": "prod", "dry_run": true }, "publisher": { "user_id": "uuid-of-publishing-user", "email": "user@example.com" }, "agent": { "name": "My Agent", "description": "Agent description text" }, "tool_auth_requirements": [ { "tool_name": "tavily_web_search", "auth_type": "api_key", "required_env_vars": ["TAVILY_API_KEY"] }, { "tool_name": "google_calendar", "auth_type": "oauth", "auth_provider": "google", "scopes": ["calendar.readonly"] } ], "files": { "type": "zip", "filename": "My_Agent.zip", "content_base64": "" }, "fields": [ { "name": "notes", "label": "Deployment Notes", "type": "textarea" } ] } ``` ### Tool auth requirements The `tool_auth_requirements` array describes authentication needed for each tool: | Auth Type | Fields | Description | | --------- | ------------------------- | ------------------------------------------------ | | `none` | - | Tool requires no authentication | | `api_key` | `required_env_vars` | Tool needs API key(s) in environment variables | | `oauth` | `auth_provider`, `scopes` | Tool requires OAuth tokens with specified scopes | Use this information to configure your deployment environment with the necessary credentials. ### ZIP file structure The `files.content_base64` field contains a ZIP archive with the following structure: ``` . ├── AGENTS.md # Agent system prompt and instructions ├── config.json # Agent metadata (name, description, visibility) ├── tools.json # Tool configurations and interrupt settings ├── skills/ # Optional skill definitions │ └── skill-name/ │ └── SKILL.md └── subagents/ # Optional subagent configurations └── research_worker/ ├── AGENTS.md └── tools.json ``` The `config.json` file and `tools.json` files are structured as follows: ```json theme={null} { "name": "My Agent", "description": "Agent description", "visibility_scope": "tenant", "triggers_paused": false } ``` ```json theme={null} { "tools": [ { "name": "tavily_web_search", "mcp_server_url": "http://localhost:8084", "mcp_server_name": "Agent Builder", "display_name": "tavily_web_search" } ], "interrupt_config": { "http://localhost:8084::tavily_web_search::Agent Builder": false } } ``` ### Custom input fields You can define custom input fields to collect information when the webhook is triggered. Supported field types are as follows: | Type | Description | | ---------- | --------------------------------- | | `string` | Single-line text input (default). | | `number` | Numeric input. | | `boolean` | Checkbox (true/false). | | `textarea` | Multi-line text input. | | `json` | JSON editor. | | `select` | Dropdown with predefined options. | For example: ```json theme={null} { "fields": [ { "name": "notes", "label": "Deployment Notes", "type": "textarea" }, { "name": "environment", "label": "Environment", "type": "select", "options": [ { "label": "Development", "value": "dev" }, { "label": "Staging", "value": "staging" }, { "label": "Production", "value": "prod" } ] }, { "name": "dry_run", "label": "Dry Run", "type": "boolean", "default": true } ] } ``` ## Example: Webhook server The following is an example webhook server in Python: ```python theme={null} from http.server import HTTPServer, BaseHTTPRequestHandler import json import base64 import zipfile import io class WebhookHandler(BaseHTTPRequestHandler): def do_POST(self): content_length = int(self.headers['Content-Length']) body = json.loads(self.rfile.read(content_length)) action = body.get("action") input_data = body.get("input", {}) publisher = body.get("publisher", {}) agent = body.get("agent", {}) tool_auth = body.get("tool_auth_requirements", []) files = body.get("files", {}) print(f"Webhook: {action}") print(f"Publisher: {publisher.get('email')}") print(f"Agent: {agent.get('name')}") print(f"Custom Input: {input_data}") # Extract ZIP contents if files.get("content_base64"): zip_bytes = base64.b64decode(files["content_base64"]) with zipfile.ZipFile(io.BytesIO(zip_bytes)) as zf: print(f"Files: {zf.namelist()}") self.send_response(200) self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(json.dumps({"status": "ok"}).encode()) HTTPServer(("", 8000), WebhookHandler).serve_forever() ``` *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-builder-webhooks.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Agent Server Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server LangSmith Deployment's **Agent Server** offers an API for creating and managing agent-based applications. It is built on the concept of [assistants](/langsmith/assistants), which are agents configured for specific tasks, and includes built-in [persistence](/oss/python/langgraph/persistence#memory-store) and a **task queue**. This versatile API supports a wide range of agentic application use cases, from background processing to real-time interactions. Use Agent Server to create and manage [assistants](/langsmith/assistants), [threads](/oss/python/langgraph/persistence#threads), [runs](/langsmith/assistants#execution), [cron jobs](/langsmith/cron-jobs), [webhooks](/langsmith/use-webhooks), and more. **API reference**
For detailed information on the API endpoints and data models, refer to the [Agent Server API reference](/langsmith/server-api-ref).
## Application structure To deploy an Agent Server application, you need to specify the graph(s) you want to deploy, as well as any relevant configuration settings, such as dependencies and environment variables. Read the [application structure](/langsmith/application-structure) guide to learn how to structure your LangGraph application for deployment. ## Parts of a deployment When you deploy Agent Server, you are deploying one or more [graphs](#graphs), a database for [persistence](/oss/python/langgraph/persistence), and a task queue. ### Graphs When you deploy a graph with Agent Server, you are deploying a "blueprint" for an [Assistant](/langsmith/assistants). An [Assistant](/langsmith/assistants) is a graph paired with specific configuration settings. You can create multiple assistants per graph, each with unique settings to accommodate different use cases that can be served by the same graph. Upon deployment, Agent Server will automatically create a default assistant for each graph using the graph's default configuration settings. We often think of a graph as implementing an [agent](/oss/python/langgraph/workflows-agents), but a graph does not necessarily need to implement an agent. For example, a graph could implement a simple chatbot that only supports back-and-forth conversation, without the ability to influence any application control flow. In reality, as applications get more complex, a graph will often implement a more complex flow that may use [multiple agents](/oss/python/langchain/multi-agent) working in tandem. ### Persistence and task queue Agent Server leverages a database for [persistence](/oss/python/langgraph/persistence) and a task queue. [PostgreSQL](https://www.postgresql.org/) is supported as a database for Agent Server and [Redis](https://redis.io/) as the task queue. If you're deploying using [LangSmith cloud](/langsmith/cloud), these components are managed for you. If you're deploying Agent Server on your [own infrastructure](/langsmith/self-hosted), you'll need to set up and manage these components yourself. For more information on how these components are set up and managed, review the [hosting options](/langsmith/platform-setup) guide. ### How to deploy Agent Server can be deployed using different methods depending on your infrastructure: * [Cloud](/langsmith/deploy-to-cloud): Deploy from GitHub repositories with fully managed infrastructure. * [Hybrid or self-hosted with control plane](/langsmith/deploy-with-control-plane): Build Docker images and deploy via the UI. * [Standalone servers](/langsmith/deploy-standalone-server): Deploy Agent Servers directly without the control plane. Cloud deployments are available on all LangSmith plans. Hybrid and self-hosted options require an Enterprise plan and license key. To acquire a license key, [contact our sales team](https://www.langchain.com/contact-sales). ## Runtime architecture The following description applies to the non-distributed runtime variant of LangSmith Deployment. ### Container architecture A typical deployment consists of two kinds of long-running containers, both built from the same Docker image (a base image with your project code installed on top): * **API servers** handle client requests (creating runs, reading thread state, streaming results) but do not execute agent code themselves. * **Queue workers** are the execution engine. They listen to the durable task queue, execute your graph code, and write checkpoints. Containers are \**stateless* but persistent. At least 1 queue worker must listen to the task queue at any time to ensure no runs are orphaned. The containers can serve many runs over their lifetime. API servers and queue workers are separate container pools and [scale independently](/langsmith/data-plane#autoscaling). ### Run execution lifecycle When you invoke a run, the request flows through several components: 1. A client sends a request to an API server, which creates a pending run in the durable task queue. 2. A queue worker picks up the run, acquires a lease on it, loads the appropriate graph, and begins execution. The queue enforces that at most 1 run can be executed for a given thread at one time. 3. As the graph executes, the worker writes checkpoints to the persistence layer (the frequency depends on the [durability mode](/oss/python/langgraph/durable-execution#durability-modes)) and broadcasts streaming events over the configured pubsub provider. 4. If the client opened a `/stream` connection, the API server subscribes to the pubsub channel and forwards events to the client via server-sent events in real time. 5. When execution completes, the worker updates the run status and releases its slot for the next run. Each worker handles up to [`N_JOBS_PER_WORKER`](/langsmith/env-var#n-jobs-per-worker) runs concurrently (default: 10), so a single worker container serves many runs in parallel. See [Configure Agent Server for scale](/langsmith/agent-server-scale) for tuning guidance. ### Graph loading and compilation How and when your graph is compiled depends on how you register it in your [application structure](/langsmith/application-structure): 1. **Compiled graph**: If you export an already-compiled graph (a `CompiledGraph` instance), it is loaded once at container startup and reused for every run. This is the most efficient path. 2. **Factory function**: If you export an agent factory function, the server invokes it each time it needs the graph. Factories receive the run's configuration, enabling per-run graph customization (for example, choosing different models or tools based on the assistant config). Keep factory functions lightweight for best performance. In both cases, the server automatically injects the checkpointer and memory store configured for that deployment at runtime. **You should not configure these in your graph code**, since the server needs to manage these for other operations. ## Learn more * [Application Structure](/langsmith/application-structure) guide explains how to structure your application for deployment. * The [API Reference](https://docs.langchain.com/langsmith/server-api-ref) provides detailed information on the API endpoints and data models. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-server.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # A2A JSON-RPC Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/a2a/a2a-json-rpc langsmith/agent-server-openapi.json post /a2a/{assistant_id} Communicate with an assistant using the Agent-to-Agent (A2A) Protocol over JSON-RPC 2.0. This endpoint accepts a JSON-RPC envelope and dispatches based on `method`. **Supported Methods:** - `message/send`: Send a message and wait for the final Task result. - `message/stream`: Send a message and receive Server-Sent Events (SSE) JSON-RPC responses. - `tasks/get`: Fetch the current state of a Task by ID. - `tasks/cancel`: Request cancellation (currently not supported; returns an error). **LangGraph Mapping:** - `message.contextId` maps to LangGraph `thread_id`. **Notes:** - Only `text` and `data` parts are supported; `file` parts are not. - If `message.contextId` is omitted, a new context is created. - Text parts require the assistant input schema to include a `messages` field. # Count Assistants Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/count-assistants langsmith/agent-server-openapi.json post /assistants/count Get the count of assistants matching the specified criteria. # Create Assistant Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/create-assistant langsmith/agent-server-openapi.json post /assistants Create an assistant. An initial version of the assistant will be created and the assistant is set to that version. To change versions, use the `POST /assistants/{assistant_id}/latest` endpoint. # Delete Assistant Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/delete-assistant langsmith/agent-server-openapi.json delete /assistants/{assistant_id} Delete an assistant by ID. All versions of the assistant will be deleted as well. # Get Assistant Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/get-assistant langsmith/agent-server-openapi.json get /assistants/{assistant_id} Get an assistant by ID. # Get Assistant Graph Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/get-assistant-graph langsmith/agent-server-openapi.json get /assistants/{assistant_id}/graph Get an assistant by ID. # Get Assistant Schemas Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/get-assistant-schemas langsmith/agent-server-openapi.json get /assistants/{assistant_id}/schemas Get an assistant by ID. # Get Assistant Subgraphs Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/get-assistant-subgraphs langsmith/agent-server-openapi.json get /assistants/{assistant_id}/subgraphs Get an assistant's subgraphs. # Get Assistant Subgraphs by Namespace Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/get-assistant-subgraphs-by-namespace langsmith/agent-server-openapi.json get /assistants/{assistant_id}/subgraphs/{namespace} Get an assistant's subgraphs filtered by namespace. # Get Assistant Versions Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/get-assistant-versions langsmith/agent-server-openapi.json post /assistants/{assistant_id}/versions Get all versions of an assistant. # Patch Assistant Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/patch-assistant langsmith/agent-server-openapi.json patch /assistants/{assistant_id} Update an assistant. # Search Assistants Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/search-assistants langsmith/agent-server-openapi.json post /assistants/search Search for assistants. This endpoint also functions as the endpoint to list all assistants. # Set Latest Assistant Version Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/assistants/set-latest-assistant-version langsmith/agent-server-openapi.json post /assistants/{assistant_id}/latest Set the latest version for an assistant. # Count Crons Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/crons-plus-tier/count-crons langsmith/agent-server-openapi.json post /runs/crons/count Get the count of crons matching the specified criteria. # Create Cron Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/crons-plus-tier/create-cron langsmith/agent-server-openapi.json post /runs/crons Create a cron to schedule runs on new threads. # Create Thread Cron Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/crons-plus-tier/create-thread-cron langsmith/agent-server-openapi.json post /threads/{thread_id}/runs/crons Create a cron to schedule runs on a thread. # Delete Cron Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/crons-plus-tier/delete-cron langsmith/agent-server-openapi.json delete /runs/crons/{cron_id} Delete a cron by ID. # Search Crons Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/crons-plus-tier/search-crons langsmith/agent-server-openapi.json post /runs/crons/search Search all active crons # Update Cron Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/crons-plus-tier/update-cron langsmith/agent-server-openapi.json patch /runs/crons/{cron_id} Update a cron job by ID. # MCP Get Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/mcp/mcp-get langsmith/agent-server-openapi.json get /mcp/ Implemented according to the Streamable HTTP Transport specification. # MCP Post Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/mcp/mcp-post langsmith/agent-server-openapi.json post /mcp/ Implemented according to the Streamable HTTP Transport specification. Sends a JSON-RPC 2.0 message to the server. - **Request**: Provide an object with `jsonrpc`, `id`, `method`, and optional `params`. - **Response**: Returns a JSON-RPC response or acknowledgment. **Notes:** - Stateless: Sessions are not persisted across requests. # Terminate Session Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/mcp/terminate-session langsmith/agent-server-openapi.json delete /mcp/ Implemented according to the Streamable HTTP Transport specification. Terminate an MCP session. The server implementation is stateless, so this is a no-op. # Create Background Run Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/stateless-runs/create-background-run langsmith/agent-server-openapi.json post /runs Create a run and return the run ID immediately. Don't wait for the final run output. # Create Run Batch Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/stateless-runs/create-run-batch langsmith/agent-server-openapi.json post /runs/batch Create a batch of runs and return immediately. # Create Run, Stream Output Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/stateless-runs/create-run-stream-output langsmith/agent-server-openapi.json post /runs/stream Create a run and stream the output. # Create Run, Wait for Output Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/stateless-runs/create-run-wait-for-output langsmith/agent-server-openapi.json post /runs/wait Create a run, wait for the final output and then return it. # Delete an item. Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/store/delete-an-item langsmith/agent-server-openapi.json delete /store/items # List namespaces with optional match conditions. Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/store/list-namespaces-with-optional-match-conditions langsmith/agent-server-openapi.json post /store/namespaces # Retrieve a single item. Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/store/retrieve-a-single-item langsmith/agent-server-openapi.json get /store/items # Search for items within a namespace prefix. Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/store/search-for-items-within-a-namespace-prefix langsmith/agent-server-openapi.json post /store/items/search # Store or update an item. Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/store/store-or-update-an-item langsmith/agent-server-openapi.json put /store/items # Health Check Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/system/health-check langsmith/agent-server-openapi.json get /ok Check the health status of the server. Optionally check database connectivity. # Server Information Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/system/server-information langsmith/agent-server-openapi.json get /info Get server version information, feature flags, and metadata. # System Metrics Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/system/system-metrics langsmith/agent-server-openapi.json get /metrics Get system metrics in Prometheus or JSON format for monitoring and observability. # Cancel Run Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/thread-runs/cancel-run langsmith/agent-server-openapi.json post /threads/{thread_id}/runs/{run_id}/cancel # Cancel Runs Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/thread-runs/cancel-runs langsmith/agent-server-openapi.json post /runs/cancel Cancel one or more runs. Can cancel runs by thread ID and run IDs, or by status filter. # Create Background Run Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/thread-runs/create-background-run langsmith/agent-server-openapi.json post /threads/{thread_id}/runs Create a run in existing thread, return the run ID immediately. Don't wait for the final run output. # Create Run, Stream Output Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/thread-runs/create-run-stream-output langsmith/agent-server-openapi.json post /threads/{thread_id}/runs/stream Create a run in existing thread. Stream the output. # Create Run, Wait for Output Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/thread-runs/create-run-wait-for-output langsmith/agent-server-openapi.json post /threads/{thread_id}/runs/wait Create a run in existing thread. Wait for the final output and then return it. # Delete Run Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/thread-runs/delete-run langsmith/agent-server-openapi.json delete /threads/{thread_id}/runs/{run_id} Delete a run by ID. # Get Run Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/thread-runs/get-run langsmith/agent-server-openapi.json get /threads/{thread_id}/runs/{run_id} Get a run by ID. # Join Run Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/thread-runs/join-run langsmith/agent-server-openapi.json get /threads/{thread_id}/runs/{run_id}/join Wait for a run to finish. # Join Run Stream Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/thread-runs/join-run-stream langsmith/agent-server-openapi.json get /threads/{thread_id}/runs/{run_id}/stream Join a run stream. This endpoint streams output in real-time from a run similar to the /threads/__THREAD_ID__/runs/stream endpoint. If the run has been created with `stream_resumable=true`, the stream can be resumed from the last seen event ID. # List Runs Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/thread-runs/list-runs langsmith/agent-server-openapi.json get /threads/{thread_id}/runs List runs for a thread. # Copy Thread Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/copy-thread langsmith/agent-server-openapi.json post /threads/{thread_id}/copy Create a new thread with a copy of the state and checkpoints from an existing thread. # Count Threads Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/count-threads langsmith/agent-server-openapi.json post /threads/count Get the count of threads matching the specified criteria. # Create Thread Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/create-thread langsmith/agent-server-openapi.json post /threads Create a thread. # Delete Thread Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/delete-thread langsmith/agent-server-openapi.json delete /threads/{thread_id} Delete a thread by ID. # Get Thread Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/get-thread langsmith/agent-server-openapi.json get /threads/{thread_id} Get a thread by ID. # Get Thread History Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/get-thread-history langsmith/agent-server-openapi.json get /threads/{thread_id}/history Get all past states for a thread. # Get Thread History Post Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/get-thread-history-post langsmith/agent-server-openapi.json post /threads/{thread_id}/history Get all past states for a thread. # Get Thread State Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/get-thread-state langsmith/agent-server-openapi.json get /threads/{thread_id}/state Get state for a thread. The latest state of the thread (i.e. latest checkpoint) is returned. # Get Thread State At Checkpoint Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/get-thread-state-at-checkpoint langsmith/agent-server-openapi.json get /threads/{thread_id}/state/{checkpoint_id} Get state for a thread at a specific checkpoint. # Get Thread State At Checkpoint Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/get-thread-state-at-checkpoint-1 langsmith/agent-server-openapi.json post /threads/{thread_id}/state/checkpoint Get state for a thread at a specific checkpoint. # Join Thread Stream Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/join-thread-stream langsmith/agent-server-openapi.json get /threads/{thread_id}/stream This endpoint streams output in real-time from a thread. The stream will include the output of each run executed sequentially on the thread and will remain open indefinitely. It is the responsibility of the calling client to close the connection. # Patch Thread Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/patch-thread langsmith/agent-server-openapi.json patch /threads/{thread_id} Update a thread. # Prune Threads Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/prune-threads langsmith/agent-server-openapi.json post /threads/prune Prune threads by ID. The 'delete' strategy removes threads entirely. The 'keep_latest' strategy prunes old checkpoints but keeps threads and their latest state (requires FF_USE_CORE_API=true). # Search Threads Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/search-threads langsmith/agent-server-openapi.json post /threads/search Search for threads. This endpoint also functions as the endpoint to list all threads. # Update Thread State Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-api/threads/update-thread-state langsmith/agent-server-openapi.json post /threads/{thread_id}/state Add state to a thread. # Agent Server changelog Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-changelog **Subscribe**: Our changelog includes an [RSS feed](https://docs.langchain.com/langsmith/agent-server-changelog/rss.xml) that can integrate with [Slack](https://slack.com/help/articles/218688467-Add-RSS-feeds-to-Slack), [email](https://zapier.com/apps/email/integrations/rss/1441/send-new-rss-feed-entries-via-email), Discord bots like [Readybot](https://readybot.io/) or [RSS Feeds to Discord Bot](https://rss.app/en/bots/rssfeeds-discord-bot), and other subscription tools. [Agent Server](/langsmith/agent-server) is an API platform for creating and managing agent-based applications. It provides built-in persistence, a task queue, and supports deploying, configuring, and running assistants (agentic workflows) at scale. This changelog documents all notable updates, features, and fixes to Agent Server releases. ## v0.7.46 * Structured error payloads in webhooks now include `error` and `message` fields, replacing the previous flat string format, which may affect systems parsing the `error` field. * Expanded store auth tests with namespace-rewriting to enhance namespace handling and cross-user isolation. ## v0.7.45 * Replaced null bytes with U+FFFD in all handling paths to prevent key collisions. ## v0.7.44 * Increase flexibility of database URI parser * Add additional validation on some payloads ## v0.7.40 * Fixed a regression in assistant creation by ensuring `metadata` and `config` are populated as empty objects `{}` instead of `null` when not provided. ## v0.7.39 * Ensured auth configuration is passed correctly in distributed runtime operations to improve executor functionality. * Added support for Red Hat UBI-9 based Docker images for enterprise customers using RHEL-based containers. * Added graceful shutdown handoff for distributed runtime, allowing in-flight runs to transfer to the next pod without using a retry attempt. ## v0.7.38 * Added `state_updated_at` field to threads for tracking meaningful state changes, allowing filtering and sorting based on these changes. * Added support for scheduling crons within the core system. * Ensured accurate display of the `https` protocol in agent cards using the x-forwarded-proto header for proper A2A client functionality. ## v0.7.37 * Added generic fallbacks for `acopy_thread`, `aprune`, and `adelete_for_runs` in the BYOC checkpointer adapter, simplifying implementation for custom checkpointers. ## v0.7.36 * Updated A2A protocol support to v1.0 RC, renamed JSON-RPC methods, added a ListTasks handler, and enhanced role, state, and part formats for improved integration and compliance. * Improved authentication filtering for `Crons.search()` and `Crons.count()` to prevent unauthorized thread information access. * Fixed gaps in BYOC checkpointer for copy, rollback, and namespace filtering operations, ensuring proper handling across different storage backends. ## v0.7.35 * Added an optional `context` parameter to MCP `tools/call` and A2A `message/send` and `message/stream` endpoints, enabling middleware to inject runtime context from headers. ## v0.7.33 * Enhanced the Redis fixture by removing custom checkpointer test skips, improving typed serialization, and adding missing Redis methods. * Resolved a stored XSS vulnerability in the handle\_ui endpoint by sanitizing message names in single-quoted HTML onload attributes. * Fixed an authorization bypass issue in `put_item` to ensure correct namespace rewrite by the auth handler. * Enforced assistant ownership checks during run creation, preventing execution on unowned assistants while ensuring system assistants remain accessible to all authenticated users. * Implemented AES encryption for checkpoint blobs and writes in the Go checkpointer when using LANGGRAPH\_AES\_KEY. * Implemented initial checkpointer gRPC servicer with all necessary methods and conversion helpers. ## v0.7.32 * Sanitized error messages in streams and A2A responses to protect sensitive information like database connection strings and internal hostnames. * Fixed a bug in `join_run_stream` to correctly handle multiple `stream_mode` parameters, ensuring proper parsing of stringified JSON lists. * Added build, test, and publish processes for Node.js 24 images, supporting the latest LTS version. * Enhanced custom checkpointer adapter with new capabilities and improved metadata enrichment for consistent API responses. * Added stricter version constraints for langgraph libraries in executor Docker images to prevent unintended upgrades. * Enhanced security by sanitizing SSE event and id fields to prevent CR/LF injection. * Fixed an issue causing cron-created runs to use default encryption contexts instead of properly propagating the specified ones. ## v0.7.31 * Corrected metadata reading functionality to ensure accurate data processing. ## v0.7.30 * Propagated cron metadata for more comprehensive scheduling information. * Merges cron metadata on `PATCH` requests to align with other endpoints by preserving existing data. ## v0.7.29 * Refined authentication semantics for cron creation to prevent privilege escalation and ensure independent filtering for crons, threads, and assistants. * Validated tar file entries to prevent directory traversal vulnerabilities in the cloudflared download process. * Added an IDs filter to the `SearchThreadsRequest` to streamline thread endpoint operations. * Updated the fallback mechanism to use a Python Postgres connection for thread state, fixing issues with worker completion checkpoints. * Introduced a feature-flagged initial version of the Redis queue implementation with ongoing updates. ## v0.7.28 * Internal maintenance and stability improvements for MCP and gRPC. ## v0.7.27 * Improved MCP tool input schemas by removing common message types for cleaner tool definitions. * Added name sanitization for MCP tools to ensure valid tool names. ## v0.7.26 * Added validation for system keys on ingress. ## v0.7.25 * Switched the Python queue worker to use core go `Runs.next()`. * Fixed a monitoring issue in the long query monitor ## v0.7.24 * Optimized Postgres connection handling to prevent hitting connection limits under high load and removed unnecessary error logs. * Switched to a new backend for runs management and streaming using gRPC. ## v0.7.23 * Corrected the unmarshaling process for the `input` field in `RunCommand` to ensure accurate data mapping and enable a previously gated JS test. * Ensured race condition handling for run streaming by fully subscribing before execution starts, with added support for the `FF_LOG_DROPPED_EVENTS` environment variable. ## v0.7.22 * Ensured `get_store()` works in custom routes, enabling Store access from user-defined Starlette endpoints. ## v0.7.21 * Support for PATCH /crons/ ## v0.7.19 * Custom encryption improvements for core API. ## v0.7.18 * Update thread streaming for core API usage. ## v0.7.17 * Instrumentation for OTEL now requires explicit opt-in with `LS_APM_OTEL_ENABLED=true` for improved control. ## v0.7.16 * Switched threads streaming to the new gRPC backend for improved performance. * Introduced replica tracing in DR for enhanced evaluation capabilities in Studio. ## v0.7.15 * Added support for pausing crons with a new `is_enabled` field, allowing only enabled crons to be executed. * Introduced gRPC server support for JSON encryption and decryption operations. ## v0.7.14 * Ensured selected system fields are excluded from custom encryption to prevent unnecessary encryption of non-sensitive data. * Introduced a custom checkpointer adapter with unit tests to validate implementation checks. ## v0.7.13 * Fixed a bug where the app state was not properly preserved through requests when a mount prefix was set. ## v0.7.11 * Added configuration to control which payload fields can be exposed to webhooks. * Updated all dependencies in the `/api/langgraph_api/js` group, including `@langchain/core`, `hono`, `@types/react`, and `prettier`, to the latest versions for improved performance and security. * Upgraded `hono` from version 4.11.4 to 4.11.7 to address multiple security vulnerabilities in the middleware. ## v0.7.10 * Increased the gRPC server startup timeout to 1 minute to prevent occasional connection timeouts with the core server. * Updated @langchain/langgraph from version 1.1.0 to 1.1.2, introducing mixed schema support for StateGraph and type bag patterns for GraphNode and ConditionalEdgeRouter utilities. ## v0.7.9 * A2A `messageId` is now mapped to LangChain message IDs for proper message tracking across protocols. ## v0.7.7 * Ensured preservation of custom configurable fields in checkpoint metadata during gRPC serialization. ## v0.7.5 * Enforced custom encryption for values, interrupts, and errors when setting a thread's status, resolving previous inconsistencies. * Added A2A validation checks in `message/stream` and `message/send` routes for `parts`, `role`, and `messageId` fields. * Added native A2A interrupt support: `input-required` state is now returned when graphs are interrupted. Use the new `command` parameter in `message/stream` and `message/send` requests to resume with a `Command` payload. * Mounted `.well-known/agent-card.json` under `/a2a/{assistant_id}/` for A2A agent discovery. * Added proper A2A error codes for task existence checks in `tasks/cancel`. ## v0.7.4 * Fixed a bug with Redis URL parsing for `ssl_cert_reqs` field, ensuring compatibility with redis-go. * Added a gRPC client for streaming runs, controlled by the `FF_USE_CORE_API` feature flag. ## v0.7.2 * Updated `@langchain/langgraph` to version 1.1.0, introducing type utilities for graph nodes and conditional edges for enhanced TypeScript ergonomics. ## v0.7.0 * Switched to using the Go assistants implementation by default for improved performance. * Added `LANGGRAPH_AES_JSON_KEYS` configuration to enable AES encryption for specified JSON fields using a key name allowlist. ## v0.6.39 * Added gRPC client support for `Threads.State()` to the Python `core-api`, improving thread ID and run counting operations. ## v0.6.36 * Validated the length of `$and` and `$or` in auth filters and optimized unnecessary root-level filters. ## v0.6.35 * Unified the error format by removing the `code` field and standardizing all errors to return JSON with a `detail` field. ## v0.6.34 * Small fixes for feature-flagged internal environments (unreleased). ## v0.6.33 * Small fixes for feature-flagged internal environments (unreleased). ## v0.6.32 * Small fixes for feature-flagged internal environments (unreleased). ## v0.6.31 * Properly respected the disable\_a2a setting to ensure accurate configuration handling. ## v0.6.29 * Fix minor bugs. ## v0.6.28 * Added support for `ParentCommand` to correctly propagate control to parent graphs, enhancing command handling and navigation. * Added a Python gRPC client for managing run operations, enhancing consistency between Go and Python implementations. ## v0.6.27 * Fixed a regression issue in handling empty thread metadata. ## v0.6.26 * Fixed the port configuration issue for the persistence gRPC server. ## v0.6.25 * Ran the core-api gRPC server in the executor tier to support loopback API calls in graphs and removed unnecessary configuration for disabling the server. ## v0.6.24 * Fixed the behavior of the liveness probe in the executor tier, addressing issues from version 0.6.23. ## v0.6.23 * Integrated gRPC server health check with `/ok` endpoint in liveness probe to ensure proper startup coordination. * Reverted the previous change to disable the checkpointer and added a condition to enable RemoteCheckpointer only during testing. * Suppressed `langgraph_auth_*` and `langgraph_request_id` fields in checkpoint metadata to prevent inclusion of transient user data. ## v0.6.22 * Resolved an error caused by missing encryption contexts when using blob-only custom encryption, ensuring proper function without errors. ## v0.6.21 * Introduced a Python gRPC client for run operations, including `Search`, `Get`, `Delete`, `Cancel`, `Stats`, and `Sweep`, with updated API implementation and a new unit test suite for enum mappings. ## v0.6.19 * Reproduced OSS implementations of `get_state` and `update_state` in the engine server and re-enabled `test_weather_subgraph`. ## v0.6.18 * Added functionality to enforce specific license claims for self-hosted Enterprise users, enabling remote disabling of the Agent Builder product. * Added a new Prune endpoint for better resource management. * Merged graph configuration with invoke configuration in Pregel, giving precedence to invoke settings. * Introduced the `include=ttl` query parameter to the GET /threads/ endpoint for optional TTL information retrieval without affecting standard read performance. * Introduced a `keep_latest` TTL strategy to preserve the latest state while pruning older checkpoints via the core API. ## v0.6.17 * Ensured ongoing runs are stopped when an agent is deleted to prevent lingering processes. ## v0.6.16 * Streamlined and consolidated run operations in the Go persistence layer, improving efficiency and consistency across packages. ## v0.6.15 * Improved the utility converting custom route docstrings to OpenAPI schema content by adding error handling when parsing docstrings, applicable for users with custom Starlette apps. ## v0.6.12 * Improved resolve\_embeddings to be more robust, enabling multiple calls without errors. * Updated `@langchain/langgraph` from version 1.0.4 to 1.0.7, adding support for resumableStreams on remote graphs and undeprecating toolsCondition. * Implemented `RemoteCheckpointer` to enable subgraph checkpointing, enhancing task execution reliability. ## v0.6.11 * Made the maximum number of retries configurable for enhanced customization. ## v0.6.10 * Ensured run cancellation only processes 'message' type Redis events, improving pubsub client reliability. * Added custom encryption for the Store API `value` field, allowing users to choose which keys to encrypt for enhanced security. * Enabled streaming for subgraph custom events by updating TeeStream to handle event types separately. ## v0.6.9 * Enforced stable JSON keys for custom encryption, removed model-type-specific custom JSON functions, and improved error handling for double-encryption scenarios. ## v0.6.8 * Added profiling feature to enhance performance analysis and monitoring. ## v0.6.7 * Logged server startup time for improved monitoring and diagnostics. ## v0.6.5 * Added a warning log that triggers during import time for improved visibility. ## v0.6.4 * Enhanced custom encryption by parallelizing metadata and config processes, added encryption for thread.config and some checkpoints, improved tests and schema consistency. * Ensured the Go server starts as `core-api` in the queue entrypoint for consistent runtime behavior. ## v0.6.2 * Resolved an issue that caused duplicate calls to middleware when `mount_prefix` was specified. ## v0.6.0 This minor version updates the streaming APIs `/join-stream` and `/stream` behavior with respect to the `last-event-id` parameter to align with the SSE spec. Previously, passing a last-event-id would return that message in addition to any following messages. Going forward, these APIs will only return new messages following the provided last-event-id. For example, with the following stream, previously passing a last-event-id of `2` would return the messages with ids `2` and `3`, but will now only return the message with id `3`: ```json theme={null} { "id": 1, "event": "message", "data": { "content": "Excluded" } }, { "id": 2, "event": "message", "data": { "content": "Passed last-event-id" } }, { "id": 3, "event": "message", "data": { "content": "Included" } } ``` This bump also includes some fixes, including a bug exposing unintended internal events in run streams. ## v0.5.42 * Modified the Go server to rely solely on the CLI `-service` flag for determining service mode, ignoring the globally set `FF_USE_CORE_API` for better deployment specificity. ## v0.5.41 Fixed an issue with cron jobs in hybrid mode by ensuring proper initialization of the ENTERPRISE\_SAAS global flag. ## v0.5.39 * Completed the implementation of custom encryptions for runs and crons, along with simplifying encryption processes. * Introduced support for streaming subgraph events in both `values` and `updates` stream modes. ## v0.5.38 * Implemented complete custom encryption for threads, ensuring all thread data is properly secured and encrypted. * Ensured Redis attempt flags are consistently expired to prevent stale data. * Added core authentication and support for OR/AND filters, enhancing security and flexibility. ## v0.5.37 Added a `name` parameter to the assistants count API for improved search flexibility. ## v0.5.36 * Introduced configurable webhook support, allowing users to customize submitted webhooks and headers. * Added an `/ok` endpoint at the root for easier health checks and simplified configuration. ## v0.5.34 Introduced custom encryption middleware, allowing users to define their own encryption methods for enhanced data protection. ## v0.5.33 Set Uvicorn's keep-alive timeout to 75 seconds to prevent occasional 502 errors and improve connection handling. ## v0.5.32 Introduced OpenTelemetry telemetry agent with support for New Relic integration. ## v0.5.31 Added Py-Spy profiling for improved analysis of deployment performance, with some limitations on coverage. ## v0.5.30 * Always configure loopback transport clients to enhance reliability. * Ensured authentication headers are passed for remote non-stream methods in JS. ## v0.5.28 * Introduced a faster, Rust-based implementation of uuid7 to improve performance, now used in langsmith and langchain-core. * Added support for `$or` and `$and` in PostgreSQL auth filters to enable complex logic in authentication checks. * Capped psycopg and psycopg-pool versions to prevent infinite waiting on startup. ## v0.5.27 * Ensured `runs.list` with filters returns only run fields, preventing incorrect status data from being included. * (JS) Updated `uuid` from version 10.0.0 to 13.0.0. and `exit-hook` from version 4.0.0 to 5.0.1. ## v0.5.26 Resolved issues with `store.put` when used without AsyncBatchedStore in the JavaScript environment. ## v0.5.25 * Introduced the ability to search assistants by their `name` using a new endpoint. * Casted store\_get return types to tuple in JavaScript to ensure type consistency. ## v0.5.24 * Added executor metrics for Datadog and enhanced core stream API metrics for better performance tracking. * Disabled Redis Go maintenance notifications to prevent startup errors with unsupported commands in Redis versions below 8. ## v0.5.20 Resolved an error in the executor service that occurred when handling large messages. ## v0.5.19 Upgraded built-in langchain-core to version 1.0.7 to address a prompt formatting vulnerability. ## v0.5.18 Introduced persistent cron threads with `on_run_completed: {keep,delete}` for enhanced cron management and retrieval options. ## v0.5.17 Enhanced task handling to support multiple interrupts, aligning with open-source functionality. ## v0.5.15 Added custom JSON unmarshalling for `Resume` and `Goto` commands to fix map-style null resume interpretation issues. ## v0.5.14 Ensured `pg make start` command functions correctly with core-api enabled. ## v0.5.13 Support `include` and `exclude` (plural form key for `includes` and `excludes`) since a doc incorrectly claimed support for that. Now the server accepts either. ## v0.5.11 * Ensured auth handlers are applied consistently when streaming threads, aligning with recent security practices. * Bumped `undici` dependency from version 6.21.3 to 7.16.0, introducing various performance improvements and bug fixes. * Updated `p-queue` from version 8.0.1 to 9.0.0, introducing new features and breaking changes, including the removal of the `throwOnTimeout` option. ## v0.5.10 Implemented healthcheck calls in the queue /ok handler to improve Kubernetes liveness and readiness probe compatibility. ## v0.5.9 * Resolved an issue causing an "unbound local error" for the `elapsed` variable during a SIGINT interruption. * Mapped the "interrupted" status to A2A's "input-required" status for better task status alignment. ## v0.5.8 * Ensured environment variables are passed as a dictionary when starting langgraph-ui for compatibility with `uvloop`. * Implemented CRUD operations for runs in Go, simplifying JSON merges and improving transaction readability, with PostgreSQL as a reference. ## v0.5.7 Replaced no-retry Redis client with a retry client to handle connection errors more effectively and reduced corresponding logging severity. ## v0.5.6 * Added pending time metrics to provide better insights into task waiting times. * Replaced `pb.Value` with `ChannelValue` to streamline code structure. ## v0.5.5 Made the Redis `health_check_interval` more frequent and configurable for better handling of idle connections. ## v0.5.4 Implemented `ormsgpack` with `OPT_REPLACE_SURROGATES` and updated for compatibility with the latest FastAPI release affecting custom authentication dependencies. ## v0.5.2 Added retry logic for PostgreSQL connections during startup to enhance deployment reliability and improved error logging for easier debugging. ## v0.5.1 * Resolved an issue where persistence was not functioning correctly with LangChain.js's createAgent feature. * Optimized assistants CRUD performance by improving database connection pooling and gRPC client reuse, reducing latency for large payloads. ## v0.5.0 This minor version now requires langgraph-checkpoint versions later than 3.0 to prevent a deserialization vulnerability in earlier versions of the langgraph-checkpoint library. The `langgraph-checkpoint` library is compatible with `langgraph` minor versions 0.4, 0.5, 0.6, and 1.0. This version removes default support for deserialization of payloads saved using the "json" type, which has never been the default. By default, objects are serialized using msgpack. Under certain uncommon situations, payloads were serialized using an older "json" mode. If those payloads contained custom python objects, those will no longer be deserializable unless you provide a `serde` config: ```json theme={null} { "checkpointer": { "serde": { "allowed_json_modules": [ ["my_agent", "my_file", "SomeType"], ] } } } ``` ## v0.4.47 * Validated and auto-corrected environment configuration types using TypeAdapter. * Added support for LangChain.js and LangGraph.js version 1.x, ensuring compatibility. * Updated hono library from version 4.9.7 to 4.10.3, addressing a CORS middleware security issue and enhancing JWT audience validation. * Introduced a modular benchmark framework, adding support for assistants and streams, with improvements to the existing ramp benchmark methodology. * Introduced a gRPC API for core threads CRUD operations, with updated Python and TypeScript clients. * Updated `hono` package from version 4.9.7 to 4.10.2, including security improvements for JWT audience validation. * Updated `hono` dependency from version 4.9.7 to 4.10.3 to fix a security issue and improve CORS middleware handling. * Introduced basic CRUD operations for threads, including create, get, patch, delete, search, count, and copy, with support for Go, gRPC server, and Python and TypeScript clients. ## v0.4.46 Added an option to enable message streaming from subgraph events, giving users more control over event notifications. ## v0.4.45 * Implemented support for authorization on custom routes, controlled by the `enable_custom_route_auth` flag. * Set default tracing to off for improved performance and simplified debugging. ## v0.4.44 Used Redis key prefix for license-related keys to prevent conflicts with existing setups. ## v0.4.43 Implemented a health check for Redis connections to prevent them from idling out. ## v0.4.40 * Prevented duplicate messages in resumable run and thread streams by addressing a race condition and adding tests to ensure consistent behavior. * Ensured that runs don't start until the pubsub subscription is confirmed to prevent message drops on startup. * Renamed platform from langgraph to improve clarity and branding. * Reset PostgreSQL connections after use to prevent lock holding and improved error reporting for transaction issues. ## v0.4.39 * Upgraded `hono` from version 4.7.6 to 4.9.7, addressing a security issue related to the `bodyLimit` middleware. * Allowed customization of the base authentication URL to enhance flexibility. * Pinned the 'ty' dependency to a stable version using 'uv' to prevent unexpected linting failures. ## v0.4.38 * Replaced `LANGSMITH_API_KEY` with `LANGSMITH_CONTROL_PLANE_API_KEY` to support hybrid deployments requiring license verification. * Introduced self-hosted log ingestion support, configurable via `SELF_HOSTED_LOGS_ENABLED` and `SELF_HOSTED_LOGS_ENDPOINT` environment variables. ## v0.4.37 Required create permissions for copying threads to ensure proper authorization. ## v0.4.36 * Improved error handling and added a delay to the sweep loop for smoother operation during Redis downtime or cancellation errors. * Updated the queue entrypoint to start the core-api gRPC server when `FF_USE_CORE_API` is enabled. * Introduced checks for invalid configurations in assistant endpoints to ensure consistency with other endpoints. ## v0.4.35 * Resolved a timezone issue in the core API, ensuring accurate time data retrieval. * Introduced a new `middleware_order` setting to apply authentication middleware before custom middleware, allowing finer control over protected route configurations. * Logged the Redis URL when errors occur during Redis client creation. * Improved Go engine/runtime context propagation to ensure consistent execution flow. * Removed the unnecessary `assistants.put` call from the executor entrypoint to streamline the process. ## v0.4.34 Blocked unauthorized users from updating thread TTL settings to enhance security. ## v0.4.33 * Improved error handling for Redis locks by logging `LockNotOwnedError` and extending initial pool migration lock timeout to 60 seconds. * Updated the BaseMessage schema to align with the latest langchain-core version and synchronized build dependencies for consistent local development. ## v0.4.32 * Added a GO persistence layer to the API image, enabling GRPC server operation with PostgreSQL support and enhancing configurability. * Set the status to error when a timeout occurs to improve error handling. ## v0.4.30 * Added support for context when using `stream_mode="events"` and included new tests for this functionality. * Added support for overriding the server port using `$LANGGRAPH_SERVER_PORT` and removed an unnecessary Dockerfile `ARG` for cleaner configuration. * Applied authorization filters to all table references in thread delete CTE to enhance security. * Introduced self-hosted metrics ingestion capability, allowing metrics to be sent to an OTLP collector every minute when the corresponding environment variables are set. * Ensured that the `set_latest` function properly updates the name and description of the version. ## v0.4.29 Ensured proper cleanup of redis pubsub connections in all scenarios. ## v0.4.28 * Added a format parameter to the queue metrics server for enhanced customization. * Corrected `MOUNT_PREFIX` environment variable usage in CLI for consistency with documentation and to prevent confusion. * Added a feature to log warnings when messages are dropped due to no subscribers, controllable via a feature flag. * Added support for Bookworm and Bullseye distributions in Node images. * Consolidated executor definitions by moving them from the `langgraph-go` repository, improving manageability and updating the checkpointer setup method for server migrations. * Ensured correct response headers are sent for a2a, improving compatibility and communication. * Consolidated PostgreSQL checkpoint implementation, added CI testing for the `/core` directory, fixed RemoteStore test errors, and enhanced the Store implementation with transactions. * Added PostgreSQL migrations to the queue server to prevent errors from graphs being added before migrations are performed. ## v0.4.27 Replaced `coredis` with `redis-py` to improve connection handling and reliability under high traffic loads. ## v0.4.24 * Added functionality to return full message history for A2A calls in accordance with the A2A spec. * Added a `LANGGRAPH_SERVER_HOST` environment variable to Dockerfiles to support custom host settings for dual stack mode. ## v0.4.23 Use a faster message codec for redis streaming. ## v0.4.22 Ported long-stream handling to the run stream, join, and cancel endpoints for improved stream management. ## v0.4.21 * Added A2A streaming functionality and enhanced testing with the A2A SDK. * Added Prometheus metrics to track language usage in graphs, middleware, and authentication for improved insights. * Fixed bugs in Open Source Software related to message conversion for chunks. * Removed await from pubsub subscribes to reduce flakiness in cluster tests and added retries in the shutdown suite to enhance API stability. ## v0.4.20 Optimized Pubsub initialization to prevent overhead and address subscription timing issues, ensuring smoother run execution. ## v0.4.19 Removed warnings from psycopg by addressing function checks introduced in version 3.2.10. ## v0.4.17 Filtered out logs with mount prefix to reduce noise in logging output. ## v0.4.16 * Added support for implicit thread creation in a2a to streamline operations. * Improved error serialization and emission in distributed runtime streams, enabling more comprehensive testing. ## v0.4.13 * Monitored queue status in the health endpoint to ensure correct behavior when PostgreSQL fails to initialize. * Addressed an issue with unequal swept ID lengths to improve log clarity. * Enhanced streaming outputs by avoiding re-serialization of DR payloads, using msgpack byte inspection for json-like parsing. ## v0.4.12 * Ensured metrics are returned even when experiencing database connection issues. * Optimized update streams to prevent unnecessary data transmission. * Upgraded `hono` from version 4.9.2 to 4.9.6 in the `storage_postgres/langgraph-api-server` for improved URL path parsing security. * Added retries and an in-memory cache for LangSmith access calls to improve resilience against single failures. ## v0.4.11 Added support for TTL (time-to-live) in thread updates. ## v0.4.10 In distributed runtime, update serde logic for final checkpoint -> thread setting. ## v0.4.9 * Added support for filtering search results by IDs in the search endpoint for more precise queries. * Included configurable headers for assistant endpoints to enhance request customization. * Implemented a simple A2A endpoint with support for agent card retrieval, task creation, and task management. ## v0.4.7 Stopped the inclusion of x-api-key to enhance security. ## v0.4.6 Fixed a race condition when joining streams, preventing duplicate start events. ## v0.4.5 * Ensured the checkpointer starts and stops correctly before and after the queue to improve shutdown and startup efficiency. * Resolved an issue where workers were being prematurely cancelled when the queue was cancelled. * Prevented queue termination by adding a fallback for cases when Redis fails to wake a worker. ## v0.4.4 * Set the custom auth thread\_id to None for stateless runs to prevent conflicts. * Improved Redis signaling in the Go runtime by adding a wakeup worker and Redis lock implementation, and updated sweep logic. ## v0.4.3 * Added stream mode to thread stream for improved data processing. * Added a durability parameter to runs for improved data persistence. ## v0.4.2 Ensured pubsub is initialized before creating a run to prevent errors from missing messages. ## v0.4.0 Minor version 0.4 comes with a number of improvements as well as some breaking changes. * Emitted attempt messages correctly within the thread stream. * Reduced cluster conflicts by using only the thread ID for hashing in cluster mapping, prioritizing efficiency with stream\_thread\_cache. * Introduced a stream endpoint for threads to track all outputs across sequentially executed runs. * Made the filter query builder in PostgreSQL more robust against malformed expressions and improved validation to prevent potential security risks. This minor version also includes a couple of breaking changes to improve the usability and security of the service: * In this minor version, we stop the practice of automatically including headers as configurable values in your runs. You can opt-in to specific patterns by setting **configurable\_headers** in your agent server config. * Run stream event IDs (for resumable streams) are now in the format of `ms-seq` instead of the previous format. We retain backwards compatibility for the old format, but we recommend using the new format for new code. ## v0.3.4 * Added custom Prometheus metrics for Redis/PG connection pools and switched the queue server to Uvicorn/Starlette for improved monitoring. * Restored Wolfi image build by correcting shell command formatting and added a Makefile target for testing with nginx. ## v0.3.3 * Added timeouts to specific Redis calls to prevent workers from being left active. * Updated the Golang runtime and added pytest skips for unsupported functionalities, including initial support for passing store to node and message streaming. * Introduced a reverse proxy setup for serving combined Python and Node.js graphs, with nginx handling server routing, to facilitate a Postgres/Redis backend for the Node.js API server. ## v0.3.1 Added a statement timeout to the pool to prevent long-running queries. ## v0.3.0 * Set a default 15-minute statement timeout and implemented monitoring for long-running queries to ensure system efficiency. * Stop propagating run configurable values to the thread configuration, because this can cause issues on subsequent runs if you are specifying a checkpoint\_id. This is a **slight breaking change** in behavior, since the thread value will no longer automatically reflect the unioned configuration of the most recent run. We believe this behavior is more intuitive, however. * Enhanced compatibility with older worker versions by handling event data in channel names within ops.py. ## v0.2.137 Fixed an unbound local error and improved logging for thread interruptions or errors, along with type updates. ## v0.2.136 * Added enhanced logging to aid in debugging metaview issues. * Upgraded executor and runtime to the latest version for improved performance and stability. ## v0.2.135 Ensured async coroutines are properly awaited to prevent potential runtime errors. ## v0.2.134 Enhanced search functionality to improve performance by allowing users to select specific columns for query results. ## v0.2.133 * Added count endpoints for crons, threads, and assistants to enhance data tracking (#1132). * Improved SSH functionality for better reliability and stability. * Updated @langchain/langgraph-api to version 0.0.59 to fix an invalid state schema issue. ## v0.2.132 * Added Go language images to enhance project compatibility and functionality. * Printed internal PIDs for JS workers to facilitate process inspection via SIGUSR1 signal. * Resolved a `run_pkey` error that occurred when attempting to insert duplicate runs. * Added `ty run` command and switched to using uuid7 for generating run IDs. * Implemented the initial Golang runtime to expand language support. ## v0.2.131 Added support for `object agent spec` with descriptions in JS. ## v0.2.130 * Added a feature flag (FF\_RICH\_THREADS=false) to disable thread updates on run creation, reducing lock contention and simplifying thread status handling. * Utilized existing connections for `aput` and `apwrite` operations to improve performance. * Improved error handling for decoding issues to enhance data processing reliability. * Excluded headers from logs to improve security while maintaining runtime functionality. * Fixed an error that prevented mapping slots to a single node. * Added debug logs to track node execution in JS deployments for improved issue diagnosis. * Changed the default multitask strategy to enqueue, improving throughput by eliminating the need to fetch inflight runs during new run insertions. * Optimized database operations for `Runs.next` and `Runs.sweep` to reduce redundant queries and improve efficiency. * Improved run creation speed by skipping unnecessary inflight runs queries. ## v0.2.129 * Stopped passing internal LGP fields to context to prevent breaking type checks. * Exposed content-location headers to ensure correct resumability behavior in the API. ## v0.2.128 Ensured synchronized updates between `configurable` and `context` in assistants, preventing setup errors and supporting smoother version transitions. ## v0.2.127 Excluded unrequested stream modes from the resumable stream to optimize functionality. ## v0.2.126 * Made access logger headers configurable to enhance logging flexibility. * Debounced the Runs.stats function to reduce the frequency of expensive calls and improve performance. * Introduced debouncing for sweepers to enhance performance and efficiency (#1147). * Acquired a lock for TTL sweeping to prevent database spamming during scale-out operations. ## v0.2.125 Updated tracing context replicas to use the new format, ensuring compatibility. ## v0.2.123 Added an entrypoint to the queue replica for improved deployment management. ## v0.2.122 Utilized persisted interrupt status in `join` to ensure correct handling of user's interrupt state after completion. ## v0.2.121 * Consolidated events to a single channel to prevent race conditions and optimize startup performance. * Ensured custom lifespans are invoked on queue workers for proper setup, and added tests. ## v0.2.120 * Restored the original streaming behavior of runs, ensuring consistent inclusion of interrupt events based on `stream_mode` settings. * Optimized `Runs.next` query to reduce average execution time from \~14.43ms to \~2.42ms, improving performance. * Added support for stream mode "tasks" and "checkpoints", normalized the UI namespace, and upgraded `@langchain/langgraph-api` for enhanced functionality. ## v0.2.117 Added a composite index on threads for faster searches with owner-based authentication and updated the default sort order to `updated_at` for improved query performance. ## v0.2.116 Reduced the default number of history checkpoints from 10 to 1 to optimize performance. ## v0.2.115 Optimized cache re-use to enhance application performance and efficiency. ## v0.2.113 Improved thread search pagination by updating response headers with `X-Pagination-Total` and `X-Pagination-Next` for better navigation. ## v0.2.112 * Ensured sync logging methods are awaited and added a linter to prevent future occurrences. * Fixed an issue where JavaScript tasks were not being populated correctly for JS graphs. ## v0.2.111 Fixed JS graph streaming failure by starting the heartbeat as soon as the connection opens. ## v0.2.110 Added interrupts as default values for join operations while preserving stream behavior. ## v0.2.109 Fixed an issue where config schema was missing when `config_type` was not set, ensuring more reliable configurations. ## v0.2.108 Prepared for LangGraph v0.6 compatibility with new context API support and bug fixes. ## v0.2.107 * Implemented caching for authentication processes to enhance performance and efficiency. * Optimized database performance by merging count and select queries. ## v0.2.106 Made log streams resumable, enhancing reliability and improving user experience when reconnecting. ## v0.2.105 Added a heapdump endpoint to save memory heap information to a file. ## v0.2.103 Used the correct metadata endpoint to resolve issues with data retrieval. ## v0.2.102 * Captured interrupt events in the wait method to preserve previous behavior from langgraph 0.5.0. * Added support for SDK structlog in the JavaScript environment for enhanced logging capabilities. ## v0.2.101 Corrected the metadata endpoint for self-hosted deployments. ## v0.2.99 * Improved license check by adding an in-memory cache and handling Redis connection errors more effectively. * Reloaded assistants to preserve manually created ones while discarding those removed from the configuration file. * Reverted changes to ensure the UI namespace for gen UI is a valid JavaScript property name. * Ensured that the UI namespace for generated UI is a valid JavaScript property name, improving API compliance. * Enhanced error handling to return a 422 status code for unprocessable entity requests. ## v0.2.98 Added context to langgraph nodes to improve log filtering and trace visibility. ## v0.2.97 * Improved interoperability with the ckpt ingestion worker on the main loop to prevent task scheduling issues. * Delayed queue worker startup until after migrations are completed to prevent premature execution. * Enhanced thread state error handling by adding specific metadata and improved response codes for better clarity when state updates fail during creation. * Exposed the interrupt ID when retrieving the thread state to improve API transparency. ## v0.2.96 Added a fallback mechanism for configurable header patterns to handle exclude/include settings more effectively. ## v0.2.95 * Avoided setting the future if it is already done to prevent redundant operations. * Resolved compatibility errors in CI by switching from `typing.TypedDict` to `typing_extensions.TypedDict` for Python versions below 3.12. ## v0.2.94 * Improved performance by omitting pending sends for langgraph versions 0.5 and above. * Improved server startup logs to provide clearer warnings when the DD\_API\_KEY environment variable is set. ## v0.2.93 Removed the GIN index for run metadata to improve performance. ## v0.2.92 Enabled copying functionality for blobs and checkpoints, improving data management flexibility. ## v0.2.91 Reduced writes to the `checkpoint_blobs` table by inlining small values (null, numeric, str, etc.). This means we don't need to store extra values for channels that haven't been updated. ## v0.2.90 Improve checkpoint writes via node-local background queueing. ## v0.2.89 Decoupled checkpoint writing from thread/run state by removing foreign keys and updated logger to prevent timeout-related failures. ## v0.2.88 Removed the foreign key constraint for `thread` in the `run` table to simplify database schema. ## v0.2.87 Added more detailed logs for Redis worker signaling to improve debugging. ## v0.2.86 Honored tool descriptions in the `/mcp` endpoint to align with expected functionality. ## v0.2.85 Added support for the `on_disconnect` field to `runs/wait` and included disconnect logs for better debugging. ## v0.2.84 Removed unnecessary status updates to streamline thread handling and updated version to 0.2.84. ## v0.2.83 * Reduced the default time-to-live for resumable streams to 2 minutes. * Enhanced data submission logic to send data to both Beacon and LangSmith instance based on license configuration. * Enabled submission of self-hosted data to a LangSmith instance when the endpoint is configured. ## v0.2.82 Addressed a race condition in background runs by implementing a lock using join, ensuring reliable execution across CTEs. ## v0.2.81 Optimized run streams by reducing initial wait time to improve responsiveness for older or non-existent runs. ## v0.2.80 Corrected parameter passing in the `logger.ainfo()` API call to resolve a TypeError. ## v0.2.79 * Fixed a JsonDecodeError in checkpointing with remote graph by correcting JSON serialization to handle trailing slashes properly. * Introduced a configuration flag to disable webhooks globally across all routes. ## v0.2.78 * Added timeout retries to webhook calls to improve reliability. * Added HTTP request metrics, including a request count and latency histogram, for enhanced monitoring capabilities. ## v0.2.77 * Added HTTP metrics to improve performance monitoring. * Changed the Redis cache delimiter to reduce conflicts with subgraph message names and updated caching behavior. ## v0.2.76 Updated Redis cache delimiter to prevent conflicts with subgraph messages. ## v0.2.74 Scheduled webhooks in an isolated loop to ensure thread-safe operations and prevent errors with PYTHONASYNCIODEBUG=1. ## v0.2.73 * Fixed an infinite frame loop issue and removed the dict\_parser due to structlog's unexpected behavior. * Throw a 409 error on deadlock occurrence during run cancellations to handle lock conflicts gracefully. ## v0.2.72 * Ensured compatibility with future langgraph versions. * Implemented a 409 response status to handle deadlock issues during cancellation. ## v0.2.71 Improved logging for better clarity and detail regarding log types. ## v0.2.70 Improved error handling to better distinguish and log TimeoutErrors caused by users from internal run timeouts. ## v0.2.69 Added sorting and pagination to the crons API and updated schema definitions for improved accuracy. ## v0.2.66 Fixed a 404 error when creating multiple runs with the same thread\_id using `on_not_exist="create"`. ## v0.2.65 * Ensured that only fields from `assistant_versions` are returned when necessary. * Ensured consistent data types for in-memory and PostgreSQL users, improving internal authentication handling. ## v0.2.64 Added descriptions to version entries for better clarity. ## v0.2.62 * Improved user handling for custom authentication in the JS Studio. * Added Prometheus-format run statistics to the metrics endpoint for better monitoring. * Added run statistics in Prometheus format to the metrics endpoint. ## v0.2.61 Set a maximum idle time for Redis connections to prevent unnecessary open connections. ## v0.2.60 * Enhanced error logging to include traceback details for dictionary operations. * Added a `/metrics` endpoint to expose queue worker metrics for monitoring. ## v0.2.57 * Removed CancelledError from retriable exceptions to allow local interrupts while maintaining retriability for workers. * Introduced middleware to gracefully shut down the server after completing in-flight requests upon receiving a SIGINT. * Reduced metadata stored in checkpoint to only include necessary information. * Improved error handling in join runs to return error details when present. ## v0.2.56 Improved application stability by adding a handler for SIGTERM signals. ## v0.2.55 * Improved the handling of cancellations in the queue entrypoint. * Improved cancellation handling in the queue entry point. ## v0.2.54 * Enhanced error message for LuaLock timeout during license validation. * Fixed the \$contains filter in custom auth by requiring an explicit ::text cast and updated tests accordingly. * Ensured project and tenant IDs are formatted as UUIDs for consistency. ## v0.2.53 * Resolved a timing issue to ensure the queue starts only after the graph is registered. * Improved performance by setting thread and run status in a single query and enhanced error handling during checkpoint writes. * Reduced the default background grace period to 3 minutes. ## v0.2.52 * Now logging expected graphs when one is omitted to improve traceability. * Implemented a time-to-live (TTL) feature for resumable streams. * Improved query efficiency and consistency by adding a unique index and optimizing row locking. ## v0.2.51 * Handled `CancelledError` by marking tasks as ready to retry, improving error management in worker processes. * Added LG API version and request ID to metadata and logs for better tracking. * Added LG API version and request ID to metadata and logs to improve traceability. * Improved database performance by creating indexes concurrently. * Ensured postgres write is committed only after the Redis running marker is set to prevent race conditions. * Enhanced query efficiency and reliability by adding a unique index on thread\_id/running, optimizing row locks, and ensuring deterministic run selection. * Resolved a race condition by ensuring Postgres updates only occur after the Redis running marker is set. ## v0.2.46 Introduced a new connection for each operation while preserving transaction characteristics in Threads state `update()` and `bulk()` commands. ## v0.2.45 * Enhanced streaming feature by incorporating tracing contexts. * Removed an unnecessary query from the Crons.search function. * Resolved connection reuse issue when scheduling next run for multiple cron jobs. * Removed an unnecessary query in the Crons.search function to improve efficiency. * Resolved an issue with scheduling the next cron run by improving connection reuse. ## v0.2.44 * Enhanced the worker logic to exit the pipeline before continuing when the Redis message limit is reached. * Introduced a ceiling for Redis message size with an option to skip messages larger than 128 MB for improved performance. * Ensured the pipeline always closes properly to prevent resource leaks. ## v0.2.43 * Improved performance by omitting logs in metadata calls and ensuring output schema compliance in value streaming. * Ensured the connection is properly closed after use. * Aligned output format to strictly adhere to the specified schema. * Stopped sending internal logs in metadata requests to improve privacy. ## v0.2.42 * Added timestamps to track the start and end of a request's run. * Added tracer information to the configuration settings. * Added support for streaming with tracing contexts. ## v0.2.41 Added locking mechanism to prevent errors in pipelined executions. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-server-changelog.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Distributed tracing with Agent Server Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-distributed-tracing Unify traces when calling your deployed Agent Server from another service using RemoteGraph or the SDK. When you call a deployed [Agent Server](/langsmith/agent-server) from another service, you can propagate trace context so that the entire request appears as a single unified trace in LangSmith. This uses LangSmith's [distributed tracing](/langsmith/distributed-tracing) capabilities, which propagate context via HTTP headers. ## How it works Distributed tracing links runs across services using context propagation headers: 1. The **client** infers the trace context from the current run and sends it as HTTP headers. 2. The **server** reads the headers and adds them to the run's config and metadata as `langsmith-trace` and `langsmith-project` configurable values. You can choose to use these to set the tracing context for a given run when your agent is used. The headers used are: * `langsmith-trace`: Contains the trace's dotted order. * `baggage`: Specifies the LangSmith project and other optional tags and metadata. To opt-in to distributed tracing, both client and server need to opt in. ## Configure the server To accept distributed trace context, your graph must read the trace headers from the config and set the tracing context. The headers are passed through the `configurable` field as `langsmith-trace` and `langsmith-project`. ```python theme={null} import contextlib import langsmith as ls from langgraph.graph import StateGraph, MessagesState # Define your graph builder = StateGraph(MessagesState) # ... add nodes and edges ... my_graph = builder.compile() @contextlib.contextmanager async def graph(config): configurable = config.get("configurable", {}) parent_trace = configurable.get("langsmith-trace") parent_project = configurable.get("langsmith-project") # If you want to also include metadata and tags from the client metadata = configurable.get("langsmith-metadata") tags = configurable.get("langsmith-tags") with ls.tracing_context(parent=parent_trace, project_name=parent_project, metadata=metadata, tags=tags): yield my_graph ``` Export this `graph` function in your `langgraph.json`: ```json theme={null} { "graphs": { "agent": "./src/agent.py:graph" } } ``` ## Connect from the client Set `distributed_tracing=True` when initializing [`RemoteGraph`](https://reference.langchain.com/python/langsmith/deployment/remote_graph/). This automatically propagates trace headers on all requests. ```python theme={null} from langgraph.graph import StateGraph from langgraph.pregel.remote import RemoteGraph remote_graph = RemoteGraph( "agent", url="", distributed_tracing=True, # Enable trace propagation ) def subgraph_node(query: str): # Trace context is automatically propagated return remote_graph.invoke({ "messages": [{"role": "user", "content": query}] })['messages'][-1]['content'] # The RemoteGraph is called in the context of some on going work. # This could be a parent LangGraph agent, code traced with `@ls.traceable`, # or any other instrumented code. graph = ( StateGraph(str) .add_node(subgraph_node) .add_edge("__start__", "subgraph_node") .compile() ) # The remote graph's execution will appear as a child of this trace result = graph.invoke("What's the weather in SF?") ``` If you're using the [LangGraph SDK](/langsmith/reference) directly, propagate trace headers manually using `run_tree.to_headers()`: ```python theme={null} from langgraph_sdk import get_client import langsmith as ls client = get_client(url="") with ls.trace("call_remote_agent", inputs={"query": query}) as rt: headers = rt.to_headers() async for chunk in client.runs.stream( thread_id=None, assistant_id="agent", input={"messages": [{"role": "user", "content": query}]}, stream_mode="values", headers=headers, # Pass trace headers ): pass return chunk result = await call_remote_agent("What's the weather in SF?") ``` ## Related * [Distributed tracing](/langsmith/distributed-tracing): General distributed tracing concepts and patterns * [RemoteGraph](/langsmith/use-remote-graph): Full guide to interacting with deployments using RemoteGraph *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-server-distributed-tracing.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Configure LangSmith Agent Server for scale Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/agent-server-scale The default configuration for LangSmith Agent Server is designed to handle substantial read and write load across a variety of different workloads. By following the best practices outlined below, you can tune your Agent Server to perform optimally for your specific workload. This page describes scaling considerations for the Agent Server and provides examples to help configure your deployment. If you're not yet familiar with how API servers and queue workers operate at the container level, read the [runtime architecture](/langsmith/agent-server#runtime-architecture) overview first. For some example self-hosted configurations, refer to the [Example Agent Server configurations for scale](#example-self-hosted-agent-server-configurations) section. ## Scaling for write load Write load is primarily driven by the following factors: * Creation of new [runs](/langsmith/background-run) * Creation of new checkpoints during run execution * Writing to long term memory * Creation of new [threads](/langsmith/use-threads) * Creation of new [assistants](/langsmith/assistants) * Deletion of runs, checkpoints, threads, assistants and cron jobs The following components are primarily responsible for handling write load: * API server: Handles initial request and persistence of data to the database. * Queue worker: Handles the execution of runs. * Redis: Handles the storage of ephemeral data about on-going runs. * Postgres: Handles the storage of all data, including run, thread, assistant, cron job, checkpointing and long term memory. ### Best practices for scaling the write path #### Change `N_JOBS_PER_WORKER` based on assistant characteristics The default value of [`N_JOBS_PER_WORKER`](/langsmith/env-var#n-jobs-per-worker) is 10. You can change this value to scale the maximum number of runs that can be executed at a time by a single queue worker based on the characteristics of your assistant. Some general guidelines for changing `N_JOBS_PER_WORKER`: * If your assistant is CPU bounded, the default value of 10 is likely sufficient. You might lower `N_JOBS_PER_WORKER` if you notice excessive CPU usage on queue workers or delays in run execution. * If your assistant is IO bounded, increase `N_JOBS_PER_WORKER` to handle more concurrent runs per worker. There is no upper limit to `N_JOBS_PER_WORKER`. However, queue workers are greedy when fetching new runs, which means they will try to pick up as many runs as they have available jobs and begin executing them immediately. Setting `N_JOBS_PER_WORKER` too high in environments with bursty traffic can lead to uneven worker utilization and increased run execution times. #### Avoid synchronous blocking operations Avoid synchronous blocking operations in your code and prefer asynchronous operations. Long synchronous operations can block the main event loop, causing longer request and run execution times and potential timeouts. For example, consider an application that needs to sleep for 1 second. Instead of using synchronous code like this: ```python theme={null} import time def my_function(): time.sleep(1) ``` Prefer asynchronous code like this: ```python theme={null} import asyncio async def my_function(): await asyncio.sleep(1) ``` If an assistant requires synchronous blocking operations, set [`BG_JOB_ISOLATED_LOOPS`](/langsmith/env-var#bg-job-isolated-loops) to `True` to execute each run in a separate event loop. #### Minimize redundant checkpointing Minimize redundant checkpointing by setting [`durability`](/oss/python/langgraph/durable-execution#durability-modes) to the minimum value necessary to ensure your data is durable. The default durability mode is `"async"`, meaning checkpoints are written after each step asynchronously. If an assistant needs to persist only the final state of the run, `durability` can be set to `"exit"`, storing only the final state of the run. This can be set when creating the run: ```python theme={null} from langgraph_sdk import get_client client = get_client(url=) thread = await client.threads.create() run = await client.runs.create( thread_id=thread["thread_id"], assistant_id="agent", durability="exit" ) ``` #### Self-hosted These settings are only required for [self-hosted](/langsmith/self-hosted) deployments. By default, [cloud](/langsmith/cloud) deployments already have these best practices enabled. ##### Enable the use of queue workers
By default, the API server manages the queue and does not use queue workers. You can enable the use of queue workers by setting the `queue.enabled` configuration to `true`. ```yaml theme={null} queue: enabled: true ``` This will allow the API server to offload the queue management to the queue workers, significantly reducing the load on the API server and allowing it to focus on handling requests. ##### Support a number of jobs equal to expected throughput The more runs you execute in parallel, the more jobs you will need to handle the load. There are two main parameters to scale the available jobs: * `number_of_queue_workers`: The number of queue workers provisioned. * `N_JOBS_PER_WORKER`: The number of runs that a single queue work can execute at a time. Defaults to 10. You can calculate the available jobs with the following equation: ``` available_jobs = number_of_queue_workers * `N_JOBS_PER_WORKER` ``` Throughput is then the number of runs that can be executed per second by the available jobs: ``` throughput_per_second = available_jobs / average_run_execution_time_seconds ``` Therefore, the minimum number of queue workers you should provision to support your expected steady state throughput is: ``` number_of_queue_workers = throughput_per_second * average_run_execution_time_seconds / `N_JOBS_PER_WORKER` ``` ##### Configure autoscaling for bursty workloads Autoscaling is disabled by default, but should be configured for bursty workloads. Using the same calculations as the [previous section](#support-a-number-of-jobs-equal-to-expected-throughput), you can determine the maximum number of queue workers you should allow the autoscaler to scale to based on maximum expected throughput. ## Scaling for read load Read load is primarily driven by the following factors: * Getting the results of a [run](/langsmith/background-run) * Getting the state of a [thread](/langsmith/use-threads) * Searching for [runs](/langsmith/background-run), [threads](/langsmith/use-threads), [cron jobs](/langsmith/cron-jobs) and [assistants](/langsmith/assistants) * Retrieving checkpoints and long term memory The following components are primarily responsible for handling read load: * API server: Handles the request and direct retrieval of data from the database. * Postgres: Handles the storage of all data, including run, thread, assistant, cron job, checkpointing and long term memory. * Redis: Handles the storage of ephemeral data about on-going runs, including streaming messages from queue workers to api servers. ### Best practices for scaling the read path #### Use filtering to reduce the number of resources returned per request [Agent Server](/langsmith/agent-server) provides a search API for each resource type. These APIs implement pagination by default and offer many filtering options. Use filtering to reduce the number of resources returned per request and improve performance. #### Set a TTLs to automatically delete old data Set a [TTL on threads](/langsmith/configure-ttl) to automatically clean up old data. Runs and checkpoints are automatically deleted when the associated thread is deleted. #### Avoid polling and use /join to monitor the state of a run Avoid polling the state of a run by using the `/join` API endpoint. This method returns the final state of the run once the run is complete. If you need to monitor the output of a run in real-time, use the `/stream` API endpoint. This method streams the run output including the final state of the run. #### Self-hosted These settings are only required for [self-hosted](/langsmith/self-hosted) deployments. By default, [cloud](/langsmith/cloud) deployments already have these best practices enabled. ##### Configure autoscaling for bursty workloads Autoscaling is disabled by default, but should be configured for bursty workloads. You can determine the maximum number of api servers you should allow the autoscaler to scale to based on maximum expected throughput. The default for [cloud](/langsmith/cloud) deployments is a maximum of 10 API servers. ## Example self-hosted Agent Server configurations The exact optimal configuration depends on your application complexity, request patterns, and data requirements. Use the following examples in combination with the information in the previous sections and your specific usage to update your deployment configuration as needed. If you have any questions, contact support via [support.langchain.com](https://support.langchain.com). The following table provides an overview comparing different LangSmith Agent Server configurations for various load patterns (read requests per second / write requests per second) and standard assistant characteristics (average run execution time of 1 second, moderate CPU and memory usage): | | **[Low / low](#low-reads-low-writes)** | **[Low / high](#low-reads-high-writes)** | **[High / low](#high-reads-low-writes)** | [Medium / medium](#medium-reads-medium-writes) | [High / high](#high-reads-high-writes) | | :--------------------------------------------- | :------------------------------------- | :--------------------------------------- | :--------------------------------------- | :--------------------------------------------- | :------------------------------------- | | Write requests per second | 5 | 5 | 500 | 50 | 500 | | Read requests per second | 5 | 500 | 5 | 50 | 500 | | **API servers**
(1 CPU, 2Gi per server) | 1 (default) | 6 | 10 | 3 | 15 | | **Queue workers**
(1 CPU, 2Gi per worker) | 1 (default) | 10 | 1 (default) | 5 | 10 | | **`N_JOBS_PER_WORKER`** | 10 (default) | 50 | 10 | 10 | 50 | | **Redis resources** | 2 Gi (default) | 2 Gi (default) | 2 Gi (default) | 2 Gi (default) | 2 Gi (default) | | **Postgres resources** | 2 CPU
8 Gi (default) | 4 CPU
16 Gi memory | 4 CPU
16 Gi | 4 CPU
16 Gi memory | 8 CPU
32 Gi memory | The following sample configurations enable each of these setups. Load levels are defined as: * Low means approximately 5 requests per second * Medium means approximately 50 requests per second * High means approximately 500 requests per second ### Low reads, low writes
The default [LangSmith Deployment](/langsmith/deployments) configuration will handle this load. No custom resource configuration is needed here. ### Low reads, high writes You have a high volume of write requests (500 per second) being processed by your deployment, but relatively few read requests (5 per second). For this, we recommend a configuration like this: ```yaml theme={null} # Example configuration for low reads, high writes (5 read/500 write requests per second) api: replicas: 6 resources: requests: cpu: "1" memory: "2Gi" limits: cpu: "2" memory: "4Gi" queue: replicas: 10 resources: requests: cpu: "1" memory: "2Gi" limits: cpu: "2" memory: "4Gi" config: numberOfJobsPerWorker: 50 redis: resources: requests: memory: "2Gi" limits: memory: "2Gi" postgres: resources: requests: cpu: "4" memory: "16Gi" limits: cpu: "8" memory: "32Gi" ``` ### High reads, low writes You have a high volume of read requests (500 per second) but relatively few write requests (5 per second). For this, we recommend a configuration like this: ```yaml theme={null} # Example configuration for high reads, low writes (500 read/5 write requests per second) api: replicas: 10 resources: requests: cpu: "1" memory: "2Gi" limits: cpu: "2" memory: "4Gi" queue: replicas: 1 # Default, minimal write load resources: requests: cpu: "1" memory: "2Gi" limits: cpu: "2" memory: "4Gi" redis: resources: requests: memory: "2Gi" limits: memory: "2Gi" postgres: resources: requests: cpu: "4" memory: "16Gi" limits: cpu: "8" memory: "32Gi" # Consider read replicas for high read scenarios readReplicas: 2 ``` ### Medium reads, medium writes This is a balanced configuration that should handle moderate read and write loads (50 read/50 write requests per second). For this, we recommend a configuration like this: ```yaml theme={null} # Example configuration for medium reads, medium writes (50 read/50 write requests per second) api: replicas: 3 resources: requests: cpu: "1" memory: "2Gi" limits: cpu: "2" memory: "4Gi" queue: replicas: 5 resources: requests: cpu: "1" memory: "2Gi" limits: cpu: "2" memory: "4Gi" redis: resources: requests: memory: "2Gi" limits: memory: "2Gi" postgres: resources: requests: cpu: "4" memory: "16Gi" limits: cpu: "8" memory: "32Gi" ``` ### High reads, high writes You have high volumes of both read and write requests (500 read/500 write requests per second). For this, we recommend a configuration like this: ```yaml theme={null} # Example configuration for high reads, high writes (500 read/500 write requests per second) api: replicas: 15 resources: requests: cpu: "1" memory: "2Gi" limits: cpu: "2" memory: "4Gi" queue: replicas: 10 resources: requests: cpu: "1" memory: "2Gi" limits: cpu: "2" memory: "4Gi" config: numberOfJobsPerWorker: 50 redis: resources: requests: memory: "2Gi" limits: memory: "2Gi" postgres: resources: requests: cpu: "8" memory: "32Gi" limits: cpu: "16" memory: "64Gi" ``` ### Autoscaling If your deployment experiences bursty traffic, you can enable autoscaling to scale the number of API servers and queue workers to handle the load. Here is a sample configuration for autoscaling for high reads and high writes: ```yaml theme={null} api: autoscaling: enabled: true minReplicas: 15 maxReplicas: 25 queue: autoscaling: enabled: true minReplicas: 10 maxReplicas: 20 ``` Ensure that your deployment environment has sufficient resources to scale to the recommended size. Monitor your applications and infrastructure to ensure optimal performance. Consider implementing monitoring and alerting to track resource usage and application performance. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/agent-server-scale.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Alerts in LangSmith Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/alerts **Self-hosted Version Requirement** Access to alerts requires Helm chart version **0.10.3** or later. ## Overview Effective observability in LLM applications requires proactive detection of failures, performance degradations, and regressions. LangSmith's alerts feature helps identify critical issues such as: * API rate limit violations from model providers * Latency increases for your application * Application changes that affect feedback scores reflecting end-user experience Alerts in LangSmith are project-scoped, requiring separate configuration for each monitored project. ## Configuring an alert ### Step 1: Navigate to create alert First navigate to the Tracing project that you would like to configure alerts for. Click the Alerts icon on the top right hand corner of the page to view existing alerts for that project and set up a new alert. ### Step 2: Select metric type
Alert metrics
LangSmith offers threshold-based alerting on three core metrics: | Metric Type | Description | Use Case | | ------------------ | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Errored Runs** | Track runs with an error status | Monitors for failures in an application. | | **Feedback Score** | Measures the average feedback score | Track [feedback from end users](/langsmith/attach-user-feedback) or [online evaluation results](/langsmith/online-evaluations-llm-as-judge) to alert on regressions. | | **Latency** | Measures average run execution time | Tracks the latency of your application to alert on spikes and performance bottlenecks. | Additionally, for **Errored Runs** and **Run Latency**, you can define filters to narrow down the runs that trigger alerts. For example, you might create an error alert filter for all `llm` runs tagged with `support_agent` that encounter a `RateLimitExceeded` error.
Alert Metrics
### Step 2: Define alert conditions Alert conditions consist of several components: * **Aggregation Method**: Average, Percentage, or Count * **Comparison Operator**: `>=`, `<=`, or exceeds threshold * **Threshold Value**: Numerical value triggering the alert * **Aggregation Window**: Time period for metric calculation (currently choose between 5 or 15 minutes) * **Feedback Key** (Feedback Score alerts only): Specific feedback metric to monitor
Alert Condition Configuration
**Example:** The configuration shown above would generate an alert when more than 5% of runs within the past 5 minutes result in errors. You can preview alert behavior over a historical time window to understand how many datapoints—and which ones—would have triggered an alert at a chosen threshold (indicated in red). For example, setting an average latency threshold of 60 seconds for a project lets you visualize potential alerts, as shown in the image below.
Alert Metrics
### Step 3: Configure notification channel LangSmith supports the following notification channels: 1. [PagerDuty integration](/langsmith/alerts-pagerduty) 2. [Webhook notifications](/langsmith/alerts-webhook) Select the appropriate channel to ensure notifications reach the responsible team members. ## Best practices * Adjust sensitivity based on application criticality * Start with broader thresholds and refine based on observed patterns * Ensure alert routing reaches appropriate on-call personnel *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/alerts.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Configure webhook notifications for LangSmith alerts Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/alerts-webhook ## Overview This guide details the process for setting up webhook notifications for [LangSmith alerts](/langsmith/alerts). Before proceeding, make sure you have followed the steps leading up to the notification step of creating the alert by following [this guide](./alerts). Webhooks enable integration with custom services and third-party platforms by sending HTTP POST requests when alert conditions are triggered. Use webhooks to forward alert data to ticketing systems, chat applications, or custom monitoring solutions. ## Prerequisites * An endpoint that can receive HTTP POST requests * Appropriate authentication credentials for your receiving service (if required) ## Integration configuration ### Step 1: Prepare your receiving endpoint Before configuring the webhook in LangSmith, ensure your receiving endpoint: * Accepts HTTP POST requests * Can process JSON payloads * Is accessible from external services * Has appropriate authentication mechanisms (if required) Additionally, if on a custom deployment of LangSmith, make sure there are no firewall settings blocking egress traffic from LangSmith services. ### Step 2: Configure webhook parameters Webhook Setup In the notification section of your alert complete the webhook configuration with the following parameters: **Required Fields** * **URL**: The complete URL of your receiving endpoint * Example: `https://api.example.com/incident-webhook` **Optional Fields** * **Headers**: JSON Key-value pairs sent with the webhook request * Common headers include: * `Authorization`: For authentication tokens * `Content-Type`: Usually set to `application/json` (default) * `X-Source`: To identify the source as LangSmith * If no headers, then simply use `{}` * **Request Body Template**: Customize the JSON payload sent to your endpoint * Default: LangSmith sends the payload defined and the following additional key-value pairs appended to the payload: * `project_name`: Name of the triggered alert * `alert_rule_id`: A UUID to identify the LangSmith alert. This can be used as a de-duplication key in the webhook service. * `alert_rule_name`: The name of the alert rule. * `alert_rule_type`: The type of alert (as of 04/01/2025 all alerts are of type `threshold`). * `alert_rule_attribute`: The attribute associated with the alert rule - `error_count`, `feedback_score` or `latency`. * `triggered_metric_value`: The value of the metric at the time the threshold was triggered. * `triggered_threshold`: The threshold that triggered the alert. * `timestamp`: The timestamp that triggered the alert. ### Step 3: Test the webhook Click **Send Test Alert** to send the webhook notification to ensure the notification works as intended. ## Troubleshooting If webhook notifications aren't being delivered: * Verify the webhook URL is correct and accessible * Ensure any authentication headers are properly formatted * Check that your receiving endpoint accepts POST requests * Examine your endpoint's logs for received but rejected requests * Verify your custom payload template is valid JSON format ## Security considerations * Use HTTPS for your webhook endpoints * Implement authentication for your webhook endpoint * Consider adding a shared secret in your headers to verify webhook sources * Validate incoming webhook requests before processing them ## Sending alerts to Slack using a webhook Here is an example for configuring LangSmith alerts to send notifications to Slack channels using the [`chat.postMessage`](https://api.slack.com/methods/chat.postMessage) API. ### Prerequisites * Access to a Slack workspace * A LangSmith project to set up alerts * Permissions to create Slack applications ### Step 1: Create a Slack app 1. Visit the [Slack API Applications page](https://api.slack.com/apps) 2. Click **Create New App** 3. Select **From scratch** 4. Provide an **App Name** (e.g., "LangSmith Alerts") 5. Select the workspace where you want to install the app 6. Click **Create App** ### Step 2: Configure bot permissions 1. In the left sidebar of your Slack app configuration, click **OAuth & Permissions** 2. Scroll down to **Bot Token Scopes** under **Scopes** and click **Add an OAuth Scope** 3. Add the following scopes: * `chat:write` (Send messages as the app) * `chat:write.public` (Send messages to channels the app isn't in) * `channels:read` (View basic channel information) ### Step 3: Install the app to your workspace 1. Scroll up to the top of the **OAuth & Permissions** page 2. Click **Install to Workspace** 3. Review the permissions and click **Allow** 4. Copy the **Bot User OAuth Token** that appears (begins with `xoxb-`) ### Step 4: Add the bot to a Slack channel Add the bot to the specific channel you want to receive alerts in. You can add a bot to a Slack channel by mentioning it in the message field (e.g., `@botname`). You also need the channel ID to configure the webhook alert in LangSmith. You can find the channel ID by opening channel details > About ### Step 5: Configure the webhook alert in LangSmith 1. In LangSmith, navigate to your project 2. Select **Alerts → Create Alert** 3. Define your alert metrics and conditions 4. In the notification section, select **Webhook** 5. Configure the webhook with the following settings: **Webhook URL** ```json theme={null} https://slack.com/api/chat.postMessage ``` **Headers** Replace `xoxb-your-token-here` with your Bot's User OAuth Token ```json theme={null} { "Content-Type": "application/json", "Authorization": "Bearer xoxb-your-token-here" } ``` **Request Body Template** It is required to fill in the `{channel_id}` from the value found in Step 4.

The remaining fields: `alert_name`, `project_name` and `project_url` optionally add additional context to the alert message. You can find your `project_url` in the browser's URL bar. Copy the portion up to but not including any query parameters.
```json theme={null} { "channel": "{channel_id}", "text": "{alert_name} triggered for {project_name}", "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": "🚨{alert_name} has been triggered" } }, { "type": "section", "text": { "type": "mrkdwn", "text": "Please check the following link for more information:" } }, { "type": "section", "text": { "type": "mrkdwn", "text": "<{project-url}|View in LangSmith>" } } ] } ``` 6. Click **Save** to activate the webhook configuration ### Step 6: Test the integration 1. In the LangSmith alert configuration, click **Test Alert** 2. Check your specified Slack channel for the test notification 3. Verify that the message contains the expected alert information ### (Optional) Step 7: Link to the alert preview in the request body After creating an alert, you can optionally link to its preview in the webhook's request body. Alert Preview Pane To configure this: 1. Save your alert 2. Find your saved alert in the alerts table and click it 3. Copy the displayed URL 4. Click "Edit Alert" 5. Replace the existing project URL with the copied alert preview URL ## Additional resources * [LangSmith Alerts Documentation](/langsmith/alerts) * [Slack chat.postMessage API Documentation](https://api.slack.com/methods/chat.postMessage) * [Slack Block Kit Builder](https://app.slack.com/block-kit-builder/) *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/alerts-webhook.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Analyze an experiment Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/analyze-an-experiment This page describes some of the essential tasks for working with [*experiments*](/langsmith/evaluation-concepts#experiment) in LangSmith: * **[Analyze a single experiment](#analyze-a-single-experiment)**: View and interpret experiment results, customize columns, filter data, and compare runs. * [Set a baseline in the Experiments view](#set-a-baseline-in-the-experiments-view): Set a baseline for a dataset that you want to outperform. * **[Download experiment results as a CSV](#download-experiment-results-as-a-csv)**: Export your experiment data for external analysis and sharing. * **[Rename an experiment](#how-to-rename-an-experiment)**: Update experiment names in both the Playground and Experiments view. ## Analyze a single experiment After running an experiment, you can use LangSmith's experiment view to analyze the results and draw insights about your experiment's performance. ### Open the experiment view To open the experiment view, select the relevant [*dataset*](/langsmith/evaluation-concepts#datasets) from the **Dataset & Experiments** page and then select the experiment you want to view. Open experiment view ### View experiment results #### Customize columns By default, the experiment view shows the input, output, and reference output for each [example](/langsmith/evaluation-concepts#examples) in the dataset, feedback scores from evaluations and experiment metrics like cost, token counts, latency and status. You can customize the columns using the **Display** button to make it easier to interpret experiment results: * **Break out fields from inputs, outputs, and reference outputs** into their own columns. This is especially helpful if you have long inputs/outputs/reference outputs and want to surface important fields. * **Hide and reorder columns** to create focused views for analysis. * **Control decimal precision on feedback scores**. By default, LangSmith surfaces numerical feedback scores with a decimal precision of 2, but you can customize this setting to be up to 6 decimals. * **Set the Heat Map threshold** to high, middle, and low for numeric feedback scores in your experiment, which affects the threshold at which score chips render as red or green: Column heatmap configuration You can set default configurations for an entire dataset or temporarily save settings just for yourself. #### Sort and filter To sort or filter feedback scores, you can use the actions in the column headers. Sort and filter #### Table views Depending on the view most useful for your analysis, you can change the formatting of the table by toggling between a compact view, a full, view, and a diff view. * The **Compact** view shows each run as a one-line row, for ease of comparing scores at a glance. * The **Full** view shows the full output for each run for digging into the details of individual runs. * The **Diff** view shows the text difference between the reference output and the output for each run. Diff view #### View the traces Hover over any of the output cells, and click on the trace icon to view the trace for that run. This will open up a trace in the side panel. To view the entire tracing project, click on the **View Project** button in the top right of the header. View trace #### View evaluator runs For evaluator scores, you can view the source run by hovering over the evaluator score cell and clicking on the arrow icon. This will open up a trace in the side panel. If you're running a [LLM-as-a-judge evaluator](/langsmith/llm-as-judge), you can view the prompt used for the evaluator in this run. If your experiment has [repetitions](/langsmith/evaluation-concepts#repetitions), you can click on the aggregate average score to find links to all of the individual runs. View evaluator runs ### Group results by metadata You can add metadata to examples to categorize and organize them. For example, if you're evaluating factual accuracy on a question answering dataset, the metadata might include which subject area each question belongs to. Metadata can be added either [via the UI](/langsmith/manage-datasets-in-application#edit-example-metadata) or [via the SDK](/langsmith/manage-datasets-programmatically#update-single-example). To analyze results by metadata, use the **Group by** dropdown in the top right corner of the experiment view and select your desired metadata key. This displays average feedback scores, latency, total tokens, and cost for each metadata group. You will only be able to group by example metadata on experiments created after February 20th, 2025. Any experiments before that date can still be grouped by metadata, but only if the metadata is on the experiment traces themselves. ### Repetitions If you've run your experiment with [*repetitions*](/langsmith/evaluation-concepts#repetitions), there will be arrows in the output results column so you can view outputs in the table. To view each run from the repetition, hover over the output cell and click the expanded view. When you run an experiment with repetitions, LangSmith displays the average for each feedback score in the table. Click on the feedback score to view the feedback scores from individual runs, or to view the standard deviation across repetitions. Repetitions ### Compare to another experiment In the top right of the experiment view, you can select another experiment to compare to. This will open up a comparison view, where you can see how the two experiments compare. To learn more about the comparison view, see [how to compare experiment results](/langsmith/compare-experiment-results). ## Set a baseline in the Experiments view While you may run dozens of tests, you typically have a specific benchmark you are trying to outperform. Setting a *baseline* anchors your results against this reference point, which allows you to identify improvements or regressions in a crowded experiment list. By designating a baseline, you can: * Highlight a reference: Explicitly mark your best-performing run so it remains visible at the top of the **Experiments** view as you iterate. * See instant diffs: View performance deltas across all experiments automatically, which means you don't necessarily need to perform manual side-by-side selection. * Accelerate assessment: Quickly determine if new iterations meet or exceed your current performance standards. The experiments view with an experiment marked as the baseline at the top of the table. Scores show against the baseline on the rows of other experiments. The experiments view with an experiment marked as the baseline at the top of the table. Scores show against the baseline on the rows of other experiments. To set a baseline for a dataset: 1. In the [LangSmith UI](https://smith.langchain.com), navigate to the **Datasets & Experiments** option in the left menu. 2. Select the dataset that you want to work with from the table. 3. In the **Experiments** view, hover over experiments to find the **Set as baseline** button. Click to select your baseline experiment. Your baseline experiment will pin to the top of the table and have the **Baseline** tag next to its name. Once an experiment is set as a baseline, the table will display scores against the baseline on each experiment for each column. When you are selecting multiple experiments for comparison, the baseline experiment will be the default source experiment to be compared to. ## Download experiment results as a CSV LangSmith lets you download experiment results as a CSV file, which allows you to analyze and share your results. To download as a CSV, click the download icon at the top of the experiment view. The icon is directly to the left of the [Compact toggle](/langsmith/compare-experiment-results#adjust-the-table-display). Download CSV There is a 5,000 row download limit for experiment results. ## Rename an experiment Experiment names must be unique per workspace. You can rename an experiment in the LangSmith UI in: * The [Playground](#renaming-an-experiment-in-the-playground). When running experiments in the Playground, a default name with the format `pg::prompt-name::model::uuid` (eg. `pg::gpt-4.1-mini::897ee630`) is automatically assigned. You can rename an experiment immediately after running it by editing its name in the Playground table header. Edit name in playground * The [Experiments view](#renaming-an-experiment-in-the-experiments-view). When viewing results in the experiments view, you can rename an experiment by using the pencil icon beside the experiment name. Edit name in experiments view *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/analyze-an-experiment.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Custom instrumentation Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/annotate-code If you've decided you no longer want to trace your runs, you can remove the `LANGSMITH_TRACING` environment variable. Note that this does not affect the `RunTree` objects or API users, as these are meant to be low-level and not affected by the tracing toggle. There are several ways to log traces to LangSmith. If you are using LangChain (either Python or JS/TS), you can skip this section and go directly to the [LangChain-specific instructions](/langsmith/trace-with-langchain). ## Use `@traceable` / `traceable` LangSmith makes it easy to log traces with minimal changes to your existing code with the `@traceable` decorator in Python and `traceable` function in TypeScript. The `LANGSMITH_TRACING` environment variable must be set to `'true'` in order for traces to be logged to LangSmith, even when using `@traceable` or `traceable`. This allows you to toggle tracing on and off without changing your code. Additionally, you will need to set the `LANGSMITH_API_KEY` environment variable to your API key (see [Setup](/) for more information). By default, the traces will be logged to a project named `default`. To log traces to a different project, see [this section](/langsmith/log-traces-to-project). The `@traceable` decorator is a simple way to log traces from the LangSmith Python SDK. Simply decorate any function with `@traceable`. Note that when wrapping a sync function with `traceable`, (e.g. `formatPrompt` in the example below), you should use the `await` keyword when calling it to ensure the trace is logged correctly. ```python Python theme={null} from langsmith import traceable from openai import Client openai = Client() @traceable def format_prompt(subject): return [ { "role": "system", "content": "You are a helpful assistant.", }, { "role": "user", "content": f"What's a good name for a store that sells {subject}?" } ] @traceable(run_type="llm") def invoke_llm(messages): return openai.chat.completions.create( messages=messages, model="gpt-4.1-mini", temperature=0 ) @traceable def parse_output(response): return response.choices[0].message.content @traceable def run_pipeline(): messages = format_prompt("colorful socks") response = invoke_llm(messages) return parse_output(response) run_pipeline() ``` ```typescript TypeScript theme={null} import { traceable } from "langsmith/traceable"; import OpenAI from "openai"; const openai = new OpenAI(); const formatPrompt = traceable((subject: string) => { return [ { role: "system" as const, content: "You are a helpful assistant.", }, { role: "user" as const, content: `What's a good name for a store that sells ${subject}?`, }, ]; },{ name: "formatPrompt" }); const invokeLLM = traceable( async ({ messages }: { messages: { role: string; content: string }[] }) => { return openai.chat.completions.create({ model: "gpt-4.1-mini", messages: messages, temperature: 0, }); }, { run_type: "llm", name: "invokeLLM" } ); const parseOutput = traceable( (response: any) => { return response.choices[0].message.content; }, { name: "parseOutput" } ); const runPipeline = traceable( async () => { const messages = await formatPrompt("colorful socks"); const response = await invokeLLM({ messages }); return parseOutput(response); }, { name: "runPipeline" } ); await runPipeline(); ``` Annotate code trace ## Use the `trace` context manager (Python only) In Python, you can use the `trace` context manager to log traces to LangSmith. This is useful in situations where: 1. You want to log traces for a specific block of code. 2. You want control over the inputs, outputs, and other attributes of the trace. 3. It is not feasible to use a decorator or wrapper. 4. Any or all of the above. The context manager integrates seamlessly with the `traceable` decorator and `wrap_openai` wrapper, so you can use them together in the same application. ```python theme={null} import openai import langsmith as ls from langsmith.wrappers import wrap_openai client = wrap_openai(openai.Client()) @ls.traceable(run_type="tool", name="Retrieve Context") def my_tool(question: str) -> str: return "During this morning's meeting, we solved all world conflict." def chat_pipeline(question: str): context = my_tool(question) messages = [ { "role": "system", "content": "You are a helpful assistant. Please respond to the user's request only based on the given context." }, { "role": "user", "content": f"Question: {question}\nContext: {context}"} ] chat_completion = client.chat.completions.create( model="gpt-4.1-mini", messages=messages ) return chat_completion.choices[0].message.content app_inputs = {"input": "Can you summarize this morning's meetings?"} with ls.trace("Chat Pipeline", "chain", project_name="my_test", inputs=app_inputs) as rt: output = chat_pipeline("Can you summarize this morning's meetings?") rt.end(outputs={"output": output}) ``` ## Use the `RunTree` API Another, more explicit way to log traces to LangSmith is via the `RunTree` API. This API allows you more control over your tracing - you can manually create runs and children runs to assemble your trace. You still need to set your `LANGSMITH_API_KEY`, but `LANGSMITH_TRACING` is not necessary for this method. This method is not recommended, as it's easier to make mistakes in propagating trace context. ```python Python theme={null} import openai from langsmith.run_trees import RunTree # This can be a user input to your app question = "Can you summarize this morning's meetings?" # Create a top-level run pipeline = RunTree( name="Chat Pipeline", run_type="chain", inputs={"question": question} ) pipeline.post() # This can be retrieved in a retrieval step context = "During this morning's meeting, we solved all world conflict." messages = [ { "role": "system", "content": "You are a helpful assistant. Please respond to the user's request only based on the given context." }, { "role": "user", "content": f"Question: {question}\nContext: {context}"} ] # Create a child run child_llm_run = pipeline.create_child( name="OpenAI Call", run_type="llm", inputs={"messages": messages}, ) child_llm_run.post() # Generate a completion client = openai.Client() chat_completion = client.chat.completions.create( model="gpt-4.1-mini", messages=messages ) # End the runs and log them child_llm_run.end(outputs=chat_completion) child_llm_run.patch() pipeline.end(outputs={"answer": chat_completion.choices[0].message.content}) pipeline.patch() ``` ```typescript TypeScript theme={null} import OpenAI from "openai"; import { RunTree } from "langsmith"; // This can be a user input to your app const question = "Can you summarize this morning's meetings?"; const pipeline = new RunTree({ name: "Chat Pipeline", run_type: "chain", inputs: { question } }); await pipeline.postRun(); // This can be retrieved in a retrieval step const context = "During this morning's meeting, we solved all world conflict."; const messages = [ { role: "system", content: "You are a helpful assistant. Please respond to the user's request only based on the given context." }, { role: "user", content: `Question: ${question}Context: ${context}` } ]; // Create a child run const childRun = await pipeline.createChild({ name: "OpenAI Call", run_type: "llm", inputs: { messages }, }); await childRun.postRun(); // Generate a completion const client = new OpenAI(); const chatCompletion = await client.chat.completions.create({ model: "gpt-4.1-mini", messages: messages, }); // End the runs and log them childRun.end(chatCompletion); await childRun.patchRun(); pipeline.end({ outputs: { answer: chatCompletion.choices[0].message.content } }); await pipeline.patchRun(); ``` ## Example usage You can extend the utilities above to conveniently trace any code. Below are some example extensions: Trace any public method in a class: ```python theme={null} from typing import Any, Callable, Type, TypeVar T = TypeVar("T") def traceable_cls(cls: Type[T]) -> Type[T]: """Instrument all public methods in a class.""" def wrap_method(name: str, method: Any) -> Any: if callable(method) and not name.startswith("__"): return traceable(name=f"{cls.__name__}.{name}")(method) return method # Handle __dict__ case for name in dir(cls): if not name.startswith("_"): try: method = getattr(cls, name) setattr(cls, name, wrap_method(name, method)) except AttributeError: # Skip attributes that can't be set (e.g., some descriptors) pass # Handle __slots__ case if hasattr(cls, "__slots__"): for slot in cls.__slots__: # type: ignore[attr-defined] if not slot.startswith("__"): try: method = getattr(cls, slot) setattr(cls, slot, wrap_method(slot, method)) except AttributeError: # Skip slots that don't have a value yet pass return cls @traceable_cls class MyClass: def __init__(self, some_val: int): self.some_val = some_val def combine(self, other_val: int): return self.some_val + other_val # See trace: https://smith.langchain.com/public/882f9ecf-5057-426a-ae98-0edf84fdcaf9/r MyClass(13).combine(29) ``` ## Ensure all traces are submitted before exiting LangSmith's tracing is done in a background thread to avoid obstructing your production application. This means that your process may end before all traces are successfully posted to LangSmith. Here are some options for ensuring all traces are submitted before exiting your application. ### Using the LangSmith SDK If you are using the LangSmith SDK standalone, you can use the `flush` method before exit: ```python Python theme={null} from langsmith import Client client = Client() @traceable(client=client) async def my_traced_func(): # Your code here... pass try: await my_traced_func() finally: await client.flush() ``` ```typescript TypeScript theme={null} import { Client } from "langsmith"; const langsmithClient = new Client({}); const myTracedFunc = traceable(async () => { // Your code here... },{ client: langsmithClient }); try { await myTracedFunc(); } finally { await langsmithClient.flush(); } ``` ### Using LangChain If you are using LangChain, please refer to our [LangChain tracing guide](/langsmith/trace-with-langchain#ensure-all-traces-are-submitted-before-exiting). If you prefer a video tutorial, check out the [Tracing Basics video](https://academy.langchain.com/pages/intro-to-langsmith-preview) from the Introduction to LangSmith Course. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/annotate-code.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Annotate traces and runs inline Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/annotate-traces-inline LangSmith allows you to manually annotate traces with feedback within the application. This can be useful for adding context to a trace, such as a user's comment or a note about a specific issue. You can annotate a trace either inline or by sending the trace to an annotation queue, which allows you to closely inspect and log feedbacks to runs one at a time. Feedback tags are associated with your [workspace](/langsmith/administration-overview#workspaces). **You can attach user feedback to ANY intermediate run (span) of the trace, not just the root span.** This is useful for critiquing specific parts of the LLM application, such as the retrieval step or generation step of the RAG pipeline. To annotate a trace inline, click on the `Annotate` in the upper right corner of trace view for any particular run that is part of the trace. Annotate trace inline This will open up a pane that allows you to choose from feedback tags associated with your workspace and add a score for particular tags. You can also add a standalone comment. Follow [this guide](./set-up-feedback-criteria) to set up feedback tags for your workspace. You can also set up new feedback criteria from within the pane itself. Annotation sidebar You can use the labeled keyboard shortcuts to streamline the annotation process. *** [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/annotate-traces-inline.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose). [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers. # Use annotation queues Source: https://langchain-5e9cc07a-preview-srimpr-1771619406-31dcf4f.mintlify.app/langsmith/annotation-queues *Annotation queues* provide a streamlined, directed view for human annotators to attach feedback to specific [runs](/langsmith/observability-concepts#runs). While you can always annotate [traces](/langsmith/observability-concepts#traces) inline, annotation queues provide a way to group runs together, prescribe rubrics, and track reviewer progress. LangSmith supports two queue styles: * [**Single-run annotation queues**](#single-run-annotation-queues) present one run at a time and let reviewers submit any rubric feedback you configure. * [**Pairwise annotation queues (PAQs)**](#pairwise-annotation-queues) present two runs side-by-side so reviewers can quickly decide which output is better (or if they are equivalent) against the rubric items you define. For a demonstration of using annotation queues, watch the [Getting started with annotation queues](#video-guide) video guide. ## Single-run annotation queues Single-run queues present one run at a time and let reviewers submit any rubric feedback you configure. They can be created directly from the **Annotation queues** section in the [LangSmith UI](https://smith.langchain.com/). ### Create a single-run queue 1. Navigate to **Annotation queues** in the left navigation. 2. Click **+ New annotation queue** in the top-right corner. Create Annotation Queue form with Basic Details, Annotation Rubric, and Feedback sections. #### Basic details 1. Fill in the **Name** and **Description** of the queue. 2. Optionally assign a **default dataset** to streamline exporting reviewed runs into a dataset in your LangSmith [workspace](/langsmith/administration-overview#workspaces). #### Annotation rubric 1. Draft some high-level instructions for your annotators, which will be shown in the sidebar on every run. 2. Click **+ Desired Feedback** to add feedback keys to your annotation queue. Annotators will be presented with these feedback keys on each run. 3. Add a description for each, as well as a short description of each category, if the feedback is categorical. Annotation queue rubric form with instructions and desired feedback entered. For example, with the descriptions in the previous screenshot, reviewers will see the **Annotation Rubric** details in the right-hand pane of the UI. The rendered rubric for reviewers from the example instructions. #### Collaborator settings When there are multiple annotators for a run: * **Number of reviewers per run**: This determines the number of reviewers that must mark a run as **Done** for it to be removed from the queue. If you check **All workspace members review each run**, then a run will remain in the queue until all [workspace](/langsmith/administration-overview#workspaces) members have marked their review as **Done**. * Reviewers cannot view the feedback left by other reviewers. * Comments on runs are visible to all reviewers. * **Enable reservations on runs**: When a reviewer views a run, the run is reserved for that reviewer for the specified **Reservation length**. If there are multiple reviewers per run as specified above, the run can be reserved by multiple reviewers (up to the number of reviewers per run) at the same time. We recommend enabling reservations. This will prevent multiple annotators from reviewing the same run at the same time. If a reviewer has viewed a run and then leaves the run without marking it **Done**, the reservation will expire after the specified **Reservation length**. The run is then released back into the queue and can be reserved by another reviewer. Clicking **Requeue** for a run's annotation will only move the current run to the end of the current user's queue; it won't affect the queue order of any other user. It will also release the reservation that the current user has on that run. Because of these settings, the number of runs visible to each reviewer can differ from the total queue size. You can revisit the pencil icon in **Annotation queues** to update any settings later. ### Assign runs to a single-run queue There are several ways to populate a single-run queue with work items: * **From a trace view**: Click **Add to Annotation Queue** in the top-right corner of any [trace](/langsmith/observability-concepts#traces) view. You can add any intermediate [run](/langsmith/observability-concepts#runs), but not the root span. Trace view with the Add to Annotation Queue button highlighted at the top of the screen. * **From the runs table**: Select multiple runs, then click **Add to Annotation Queue** at the bottom of the page. View of the runs table with runs selected. Add to Annotation Queue button at the bottom of the page. * **Automation rules**: [Set up a rule](/langsmith/rules) to automatically assign runs that match a filter (for example, errors or low user scores) into a queue. * **Datasets & experiments**: Select one or more [experiments](/langsmith/evaluation-concepts#experiment) within a dataset and click ** Annotate**. Choose an existing queue or create a new one, then confirm the (single-run) queue option. Selected experiments with the Annotate button at the bottom of the page. ### Review a single-run queue 1. Navigate to the **Annotation Queues** section through the left-hand navigation bar. 2. Click on the queue you want to review. This will take you to a focused, cyclical view of the runs in the queue that require review. 3. You can attach a comment, attach a score for a particular [feedback](/langsmith/observability-concepts#feedback) criteria, add the run to a dataset or mark the run as reviewed. You can also remove the run from the queue for all users, despite any current reservations or settings for the queue, by clicking the **Trash** icon next to **View run**. The keyboard shortcuts that are next to each option can help streamline the review process. View or a run with the Annotate side panel. Keyboard shortcuts visible for options. ## Pairwise annotation queues Pairwise annotation queues (PAQs) present two runs side-by-side so reviewers can quickly decide which output is better (or if they are equivalent) against the rubric items you define. They are designed for fast A/B comparisons between two experiments (often a baseline vs. a candidate model) and must be created from the **Datasets & Experiments** pages. ### Create a pairwise queue 1. Navigate to **Datasets & Experiments**, open a dataset, and select **exactly two experiments** you want to compare. 2. Click **Annotate**. In the popover, choose **Add to Pairwise Annotation Queue**. (The button is disabled until exactly two experiments are selected.) Popover showing the "Add to Pairwise Annotation Queue" card highlighted after two experiments are selected. 3. Decide whether to send the experiments to an existing pairwise queue or create a new one. 4. Provide the queue details: * **Basic details** (name and description) * **Instructions & rubrics** tailored to pairwise scoring * **Collaborator settings** (reviewer count, reservations, reservation length) 5. Submit the form to create the queue. LangSmith immediately pairs runs from the two experiments and populates the queue. Key differences for PAQs: * **Experiments**: You must provide two experiment sessions up front. LangSmith automatically pairs their runs in chronological order and populates the queue during creation. * **Rubric**: Pairwise rubric items only require a feedback key and (optionally) a description. Annotators decide whether Run A, Run B, or both are better for each rubric item. * **Dataset**: Pairwise queues do not use a default dataset, because comparisons span two experiments. * **Reservations & reviewers**: The same collaborator controls apply. Reservations help prevent two people from judging the same comparison simultaneously. ### Add more comparisons to a pairwise queue If you need to add more comparisons later, return to **Datasets & Experiments**, select the two experiments again, and choose **Add to Pairwise Annotation Queue** to append new pairs. Selecting two experiments and creating a PAQ automatically pairs the runs. When augmenting an existing PAQ, LangSmith preserves historical comparisons and appends new pairs to the queue. ### Review a pairwise queue 1. From **Annotation queues**, select the pairwise queue you want to review. 2. Each queue item displays Run A on the left and Run B on the right, along with your rubric. 3. For every rubric item: * Choose **A is better**, **B is better**, or **Equal**. The UI records binary feedback on both runs behind the scenes. * Use hotkeys `A`, `B`, or `E` to lock in your choice. 4. Once you finish all rubric items, press **Done** (or `Enter` on the final rubric item) to advance to the next comparison. 5. Optional actions: * Leave comments tied to either run. * Requeue the comparison if you need to revisit it later. * Open the full trace view for deeper debugging. Reservations, reviewer thresholds, and comments behave identically to those in single-run queues, enabling teams to use different queue types without modifying their existing workflow. Pairwise review screen showing runs side-by-side with the feedback pane containing A/B/Equal buttons and keyboard shortcuts. Consider routing runs that already have user feedback (e.g., thumbs-down) into a single-run queue for triage and a pairwise queue for head-to-head comparisons against a stronger baseline. This helps you identify regressions quickly. To learn more about how to capture user feedback from your LLM application, follow the guide on [attaching user feedback](/langsmith/attach-user-feedback). ## Video guide