Generally Available

Attribute-Based
Access Control

Fine-grained access control for LangSmith runs, traces, prompts, and datasets — based on resource tags. Policies layer on top of RBAC: deny always wins, allow can grant access even without RBAC permissions.

Helm ≥ 0.11.28App ≥ 0.12.1Self-HostedCloudallowdeny
01

RBAC + ABAC: The Two-Layer Model

LangSmith enforces access in two sequential layers. RBAC controls workspace membership and coarse role-based permissions. ABAC then evaluates resource tags to provide fine-grained scoping — restricting or expanding what each role can actually see.

Organization
Your LangSmith Org
Org Admin
Workspace
ML Workspace
EditorViewer
chatbot-dev
env:devteam:ml
chatbot-prod
env:prodteam:ml
Workspace
Data Workspace
EditorViewer
customer-evals
sensitivity:piiteam:data
benchmark-suite
env:stagingteam:data
Workspace
Platform Workspace
EditorViewer
infra-agents
access:internalteam:ops
incident-bot
access:sensitiveteam:ops
👤
User
Layer 1 — RBAC
Workspace Membership
Is the user a member of this workspace? Does their role grant the required permission (e.g. runs:read)?
Not a member → DENY immediately
Member with role → proceed to ABAC
Layer 2 — ABAC
Tag Policy Evaluation
For the user's role, do any access policies match this resource's tags? deny always wins over allow.
deny policy matches → DENY
allow policy matches → ALLOW
allow exists, none match → DENY
no ABAC policies for role → RBAC fallback
📦
Resource
Access SimulatorPick a user + resource to trace the evaluation
Active policies for this scenario
ALLOWEditorenv = devallow-dev-env
ALLOWEditorenv = stagingallow-staging-env
DENYALL rolessensitivity = piideny-pii-data
Select a user
Select a resource
← Select a user and a resource above to trace the access decision
02

Enable ABAC

ABAC requires Helm chart 0.11.28+ and application version 0.12.1+. Enable it before creating policies — choose per-organization SQL or cluster-wide Helm values.

Self-Hosted Enablement
Requires Helm chart 0.11.28+ and application version 0.12.1+. Enable ABAC before creating policies — choose per-org or cluster-wide activation.
UPDATE organizations
  SET config = config || '{"can_use_abac": true}'
  WHERE id = '<organization_id>'
  AND NOT is_personal;
Cloud: ABAC is generally available for cloud deployments — no additional configuration required. Policies apply to runs, traces, prompts, and datasets automatically once enabled in your workspace settings.
03

Policy Builder

Compose an ABAC access policy interactively. Load a quick example or build from scratch — the JSON panel updates live and can be exported as a ready-to-run Python script.

Quick-Load Examples
Policy Metadata

✓ Allow policies can grant access even without RBAC permissions

Condition Groups — OR logic between groups
Group 1projectAND within group
Role IDs

Get role IDs via the LangSmith API — GET /api/v1/workspaces/<workspace-id>/roles

Ready to POST
{
  "name": "<policy-name>",
  "effect": "allow",
  "condition_groups": [
    {
      "permission": "projects:read",
      "resource_type": "project",
      "conditions": [
        {
          "attribute_name": "resource_tag_key",
          "attribute_key": "<tag-key>",
          "operator": "equals",
          "attribute_value": "<tag-value>"
        }
      ]
    }
  ]
}
Operator Reference
OperatorBehaviorExample
equalsExact match (case-sensitive)Environment = prod
not_equalsExclude exact matchEnvironment != prod
equals_ignore_caseCase-insensitive matchteam = BACKEND
not_equals_ignore_caseExclude ignoring caseaccess ≠ SENSITIVE
matchesGlob: * any string, ? one charApp = chatbot-*
not_matchesNegated globEnv NOT LIKE *prod*
*_if_existsMatches or tag key absentClient = Acme (or untagged)

deny > allow > RBAC fallback
Multiple groups → OR logic
Conditions in group → AND logic

04

Code Examples

Ready-to-run Python scripts covering common ABAC patterns. Set LANGSMITH_API_KEY to an org admin key before running. For self-hosted, also set LANGCHAIN_ENDPOINT.

Prerequisites: set LANGSMITH_API_KEY to an org admin key. For self-hosted deployments, also set LANGCHAIN_ENDPOINT to your LangSmith API base URL (e.g. https://langsmith.yourdomain.com/api).
Example 1ALLOW
Example 1 — Allow Only (Runs)
Create a custom role with no RBAC runs permissions. Access to runs is determined purely by ABAC Allow Policies. Grants access to runs in projects tagged Environment=dev or Environment=staging.
#!/usr/bin/env python3
"""
ABAC-only role: Allow reading runs for Environment=dev or staging.
No RBAC runs permissions — access controlled entirely by ABAC.
"""
import os, requests
from datetime import datetime

API_BASE_URL = os.environ.get("LANGCHAIN_ENDPOINT", "https://api.smith.langchain.com")
API_KEY = os.environ["LANGSMITH_API_KEY"]

headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
session = requests.Session()
session.headers.update(headers)

# Create a custom role with minimal permissions (no runs:read RBAC).
# projects:read allows the role to browse the project list in the UI.
role_payload = {
    "display_name": f"abac_allow_only_{datetime.now().strftime('%H%M%S')}",
    "description": "ABAC-only runs access — no RBAC runs permissions",
    "permissions": ["projects:read", "workspaces:read"]
}
role_res = session.post(
    f"{API_BASE_URL}/api/v1/orgs/current/roles",
    json=role_payload
)
role_res.raise_for_status()
role = role_res.json()
print(f"Created role: {role['display_name']} ({role['id']})")

# Each condition_group is OR-ed — access granted if ANY group matches
policy_payload = {
    "name": f"allow_env_dev_staging_{datetime.now().strftime('%H%M%S')}",
    "description": "Allow runs access for Environment=dev or staging only",
    "effect": "allow",
    "condition_groups": [
        {
            "permission": "runs:read",
            "resource_type": "project",
            "conditions": [{
                "attribute_name": "resource_tag_key",
                "attribute_key": "Environment",
                "operator": "equals",
                "attribute_value": "dev"
            }]
        },
        {
            "permission": "runs:read",
            "resource_type": "project",
            "conditions": [{
                "attribute_name": "resource_tag_key",
                "attribute_key": "Environment",
                "operator": "equals",
                "attribute_value": "staging"
            }]
        }
    ],
    "role_ids": [role["id"]]
}

is_cloud = any(d in API_BASE_URL for d in [
    "smith.langchain.com", "smith.langchain.dev", "api.smith.langchain.com"
])
url = (f"{API_BASE_URL}/v1/platform/orgs/current/access-policies"
       if is_cloud
       else f"{API_BASE_URL}/api/v1/platform/orgs/current/access-policies")

resp = session.post(url, json=policy_payload)
resp.raise_for_status()
print(f"Created policy: {resp.json()}")