Skip to main content
LangSmith의 API는 API 키를 통한 프로그래밍 방식 접근을 지원하며, 사용자 전용 엔드포인트에 명시된 몇 가지 예외를 제외하고 UI에서 사용할 수 있는 모든 작업을 수행할 수 있습니다.
이 내용을 학습하기 전에 다음 문서를 읽어보시는 것이 도움이 될 수 있습니다:
곧 해제될 몇 가지 제한 사항이 있습니다:
  • LangSmith SDK는 아직 이러한 조직 관리 작업을 지원하지 않습니다.
  • Organization Admin 권한이 있는 조직 범위 서비스 키를 이러한 작업에 사용할 수 있습니다.
대상으로 지정할 워크스페이스를 X-Tenant-Id 헤더로 지정하세요. 헤더가 없는 경우, 작업은 API 키가 조직 범위가 아닌 경우 처음 생성된 워크스페이스를 기본값으로 사용합니다.조직 범위 API 키로 워크스페이스 범위 리소스에 접근할 때 X-Tenant-Id를 지정하지 않으면, 요청이 403 Forbidden으로 실패합니다.
자주 사용되는 엔드포인트와 사용 사례가 아래에 나열되어 있습니다. 사용 가능한 전체 엔드포인트 목록은 API 문서를 참조하세요. 모든 요청에는 X-Organization-Id 헤더가 있어야 하며, 특정 워크스페이스에 범위가 지정된 요청에는 X-Tenant-Id 헤더가 있어야 합니다.

워크스페이스

사용자 관리

RBAC

멤버십 관리

이러한 작업의 역할 ID를 가져오려면 RBAC 아래의 역할 목록 조회를 사용해야 합니다. 아래의 [조직|워크스페이스] 멤버 목록 조회 엔드포인트 응답의 "id" 값을 이러한 작업에서 identity_id로 사용해야 합니다. 조직 수준: 워크스페이스 수준:
다음 매개변수는 생략해야 합니다: read_only (더 이상 사용되지 않음), passwordfull_name (기본 인증만 해당)

API 키

보안 설정

이 맥락에서 “공유 리소스”는 공개 프롬프트, 공유 실행, 공유 데이터셋을 의미합니다.
이러한 설정을 업데이트하면 조직의 모든 리소스에 영향을 미칩니다.
워크스페이스의 설정 > 공유 탭에서 이러한 설정을 업데이트하거나 API를 통해 업데이트할 수 있습니다:
  • 조직 공유 설정 업데이트
    • 조직의 모든 공유 리소스를 공유 해제하려면 unshare_all을 사용하고, 향후 리소스 공유를 방지하려면 disable_public_sharing을 사용하세요

사용자 전용 엔드포인트

이러한 엔드포인트는 사용자 범위이며 로그인한 사용자의 JWT가 필요하므로 UI를 통해서만 실행해야 합니다.
  • /api-key/current 엔드포인트: 사용자의 PAT와 관련된 엔드포인트입니다
  • /sso/email-verification/send (Cloud 전용): 이 엔드포인트는 SAML SSO와 관련이 있습니다

샘플 코드

아래 샘플 코드는 조직 관리와 관련된 몇 가지 일반적인 워크플로를 설명합니다. 코드에서 <replace_me>가 있는 곳마다 필요한 값으로 교체해야 합니다.
import os
import requests

def main():
    api_key = os.environ["LANGSMITH_API_KEY"]
    # LANGSMITH_ORGANIZATION_ID는 SDK의 표준 환경 변수가 아니며, 이 예제에서만 사용됩니다
    organization_id = os.environ["LANGSMITH_ORGANIZATION_ID"]
    base_url = os.environ.get("LANGSMITH_ENDPOINT")  # 또는 "https://api.smith.langchain.com". 자체 호스팅 설치 또는 EU 지역에 맞게 적절히 업데이트하세요
    headers = {
        "Content-Type": "application/json",
        "X-API-Key": api_key,
        "X-Organization-Id": organization_id,
    }
    session = requests.Session()
    session.headers.update(headers)
    workspaces_path = f"{base_url}/api/v1/workspaces"
    orgs_path = f"{base_url}/api/v1/orgs/current"
    api_keys_path = f"{base_url}/api/v1/api-key"

    # 워크스페이스 생성
    workspace_res = session.post(workspaces_path, json={"display_name": "My Workspace"})
    workspace_res.raise_for_status()
    workspace = workspace_res.json()
    workspace_id = workspace["id"]
    new_workspace_headers = {
        "X-Tenant-Id": workspace_id,
    }

    # 역할 가져오기 - 조직 및 워크스페이스 역할 모두 포함
    roles_res = session.get(f"{orgs_path}/roles")
    roles_res.raise_for_status()
    roles = roles_res.json()
    # 시스템 조직 역할은 'Organization Admin', 'Organization User'입니다
    # 시스템 워크스페이스 역할은 'Admin', 'Editor', 'Viewer'입니다
    org_roles_by_name = {role["display_name"]: role for role in roles if role["access_scope"] == "organization"}
    ws_roles_by_name = {role["display_name"]: role for role in roles if role["access_scope"] == "workspace"}

    # 조직 및 새 워크스페이스에 Editor로 사용자 초대
    # workspace_role_id는 RBAC가 활성화된 경우에만 허용됩니다 (엔터프라이즈 기능).
    new_user_email = "<replace_me>"
    new_user_res = session.post(
        f"{orgs_path}/members",
        json={
            "email": new_user_email,
            "role_id": org_roles_by_name["Organization User"]["id"],
            "workspace_ids": [workspace_id],
            "workspace_role_id": ws_roles_by_name["Editor"]["id"],
        },
    )
    new_user_res.raise_for_status()

    # 이미 조직에 있는 사용자를 Viewer로 새 워크스페이스에 추가
    # workspace_role_id는 RBAC가 활성화된 경우에만 허용됩니다 (엔터프라이즈 기능).
    existing_user_email = "<replace_me>"
    org_members_res = session.get(f"{orgs_path}/members")
    org_members_res.raise_for_status()
    org_members = org_members_res.json()
    existing_org_member = next(
        (member for member in org_members["members"] if member["email"] == existing_user_email), None
    )
    existing_user_res = session.post(
        f"{workspaces_path}/current/members",
        json={
            "user_id": existing_org_member["user_id"],
            "workspace_ids": [workspace_id],
            "workspace_role_id": ws_roles_by_name["Viewer"]["id"],
        },
        headers=new_workspace_headers,
    )
    existing_user_res.raise_for_status()

    # 워크스페이스의 모든 멤버 목록 조회
    members_res = session.get(f"{workspaces_path}/current/members", headers=new_workspace_headers)
    members_res.raise_for_status()
    members = members_res.json()
    workspace_member = next(
        (member for member in members["members"] if member["email"] == existing_user_email), None
    )

    # 사용자의 워크스페이스 역할을 Admin으로 업데이트 (엔터프라이즈 전용)
    existing_user_id = workspace_member["id"]
    update_res = session.patch(
        f"{workspaces_path}/current/members/{existing_user_id}",
        json={"role_id": ws_roles_by_name["Admin"]["id"]},
        headers=new_workspace_headers,
    )
    update_res.raise_for_status()

    # 사용자의 조직 역할을 Organization Admin으로 업데이트
    update_res = session.patch(
        f"{orgs_path}/members/{existing_org_member['id']}",
        json={"role_id": org_roles_by_name["Organization Admin"]["id"]},
    )
    update_res.raise_for_status()

    # 새 서비스 키 생성
    api_key_res = session.post(
        api_keys_path,
        json={"description": "my key"},
        headers=new_workspace_headers,
    )
    api_key_res.raise_for_status()
    api_key_json = api_key_res.json()
    api_key = api_key_json["key"]

if __name__ == "__main__":
    main()

Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
I