{"id":30798506,"url":"https://github.com/permitio/langchain-permit","last_synced_at":"2025-09-05T18:12:18.382Z","repository":{"id":276863117,"uuid":"930190723","full_name":"permitio/langchain-permit","owner":"permitio","description":"A langchain integration to support fine-grained permissions for AI agents using Permit.io fine-grained authorization service.","archived":false,"fork":false,"pushed_at":"2025-03-24T22:29:21.000Z","size":261,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-08-29T15:26:14.902Z","etag":null,"topics":["example"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/permitio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-10T08:23:55.000Z","updated_at":"2025-08-14T16:52:59.000Z","dependencies_parsed_at":"2025-02-10T21:32:28.574Z","dependency_job_id":"33a42c53-18a8-440e-83e1-1122524b5708","html_url":"https://github.com/permitio/langchain-permit","commit_stats":null,"previous_names":["permitio/langchain-permit"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/permitio/langchain-permit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Flangchain-permit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Flangchain-permit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Flangchain-permit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Flangchain-permit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/permitio","download_url":"https://codeload.github.com/permitio/langchain-permit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Flangchain-permit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273797718,"owners_count":25170124,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-05T02:00:09.113Z","response_time":402,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["example"],"created_at":"2025-09-05T18:12:14.141Z","updated_at":"2025-09-05T18:12:18.367Z","avatar_url":"https://github.com/permitio.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LangChain Permit Integration\n\nCombine [LangChain](https://github.com/hwchase17/langchain) and [Permit.io](https://permit.io/) to add robust access control and permission logic to your LLM applications. This package offers:\n\n- **LangChain Tools** for JWT validation and direct permission checks\n- **LangChain Retrievers** that automatically filter or retrieve only the documents your user is allowed to see (Self Query + Ensemble)\n- Simple examples and demos to showcase usage\n\nWith this integration, you can:\n\n- Validate user tokens and ensure only authorized requests get access\n- Filter query results and documents by Permit’s policy logic (RBAC, ABAC, ReBAC)\n- Seamlessly embed Permit checks in a RAG pipeline or a chain/agent-based workflow\n\n---\n\n## Features\n\n1. **JWT Validation Tool**  \n   Validate JSON Web Tokens against a JWKs endpoint or direct JWKs JSON.\n\n2. **Permissions Check Tool**  \n   Check user / resource / action with Permit’s PDP at runtime.\n\n3. **PermitSelfQueryRetriever**  \n   A self-querying retriever that uses an LLM to parse a user’s natural language query, obtains the permitted resource IDs from Permit, and filters the vector store accordingly.\n\n4. **PermitEnsembleRetriever**  \n   Combines multiple underlying retrievers (like BM25 + vector) and then calls Permit to filter out unauthorized results.\n\n---\n\n## Installation\n\n```bash\npip install langchain-permit\n```\n\nYou’ll also need the [Permit](https://docs.permit.io/sdk/python/quickstart-python/) package if not already installed:\n\n```bash\npip install permit\n```\n\n## Environment Variables\n\n```bash\nPERMIT_API_KEY=your_api_key\nPERMIT_PDP_URL=http://localhost:7766   # or your real PDP\nJWKS_URL=http://localhost:3458/.well-known/jwks.json  # For JWT validation\nOPENAI_API_KEY=sk-...                 # If using OpenAI embeddings or chat models\n```\n\nFor usage, you’ll want to confirm your PDP is running, or you have Permit.io set up to match your policy configuration (resource types, roles, etc.). See [Permit Docs](https://docs.permit.io/concepts/pdp/overview/) for more on setting up the PDP container and writing policy rules.\n\n## Basic Usage Examples\n\n### JWT Validation Tool\n\nThe `LangchainJWTValidationTool` allows you to validate JSON Web Tokens (JWTs) using a JSON Web Key Set (JWKS) provided via a URL or direct JSON. It integrates with LangChain as a tool but also provides public methods (`validate` and `get_claims`) for standalone usage.\n\n#### Features\n\n- Validates JWTs with signature verification using a JWKS.\n- Extracts JWT claims without signature verification.\n- Supports both LangChain tool interface and direct method calls.\n- Allows session-based usage with a stored token or dynamic token passing.\n\n#### Installation\n\nEnsure you have the required dependencies:\n\n```bash\npip install langchain-permit requests pyjwt\n```\n\n### Usage\n\n1. **Initialize the Tool**: Provide a JWKS source (either a URL or JSON). Optionally, provide a token for session-based use.\n2. **Validate a Token**: Use the `validate` method to check the token’s validity with signature verification.\n3. **Extract Claims**: Use the `get_claims` method to extract claims without verifying the signature.\n\n#### Example 1: Using a JWKS URL with a Stored Token\n\n```python\nfrom langchain_permit.tools import LangchainJWTValidationTool\n\n# Initialize with a JWKS URL and a token\ntool = LangchainJWTValidationTool(\n    jwks_url=\"http://localhost:3458/.well-known/jwks.json\",\n    token=\"eyJhbGciOiJSUzI1NiIsImtpZCI6InRhb2ZpcS1pZCJ9.eyJzdWIiOiIxMjMifQ.SignatureHere\"\n)\n\n# Validate the stored token\ntry:\n    validated_claims = tool.validate()\n    print(\"Validated claims:\", validated_claims)\nexcept ValueError as e:\n    print(\"Validation error:\", e)\n\n# Extract claims from the stored token\ntry:\n    claims = tool.get_claims()\n    print(\"Extracted claims:\", claims)\nexcept ValueError as e:\n    print(\"Claims extraction error:\", e)\n```\n\n#### Example 2: Using a JWKS JSON File with a Dynamic Token\n\n```python\nfrom langchain_permit.tools import LangchainJWTValidationTool\nimport json\n\n# Load JWKS from a file\nwith open(\"jwks.json\", \"r\") as f:\n    jwks_data = json.load(f)\n\n# Initialize with JWKS JSON (no stored token)\ntool = LangchainJWTValidationTool(jwks_json=jwks_data)\n\n# Validate a token dynamically\ntry:\n    validated_claims = tool.validate(\"eyJhbGciOiJSUzI1NiIsImtpZCI6InRhb2ZpcS1pZCJ9.eyJzdWIiOiIxMjMifQ.SignatureHere\")\n    print(\"Validated claims:\", validated_claims)\nexcept ValueError as e:\n    print(\"Validation error:\", e)\n\n# Extract claims dynamically\ntry:\n    claims = tool.get_claims(\"eyJhbGciOiJSUzI1NiIsImtpZCI6InRhb2ZpcS1pZCJ9.eyJzdWIiOiIxMjMifQ.SignatureHere\")\n    print(\"Extracted claims:\", claims)\nexcept ValueError as e:\n    print(\"Claims extraction error:\", e)\n```\n\n### Notes\n\n- **JWKS Requirement**: You must provide either a `jwks_url` or `jwks_json` when initializing the tool. The JWKS must contain a key matching the token's `kid` for `validate` to work.\n- **Token Flexibility**: The `token` parameter is optional during initialization. If not provided, you must pass a token to `validate` or `get_claims`.\n- **Validation vs. Claims Extraction**: `validate` verifies the token's signature, while `get_claims` extracts claims without verification (use with trusted tokens only).\n- **Error Handling**: Always wrap calls in `try-except` blocks to handle `ValueError` exceptions (e.g., invalid token, unreachable JWKS URL).\n\n### Permission Check Tool\n\n```python\nfrom permit import Permit\nfrom langchain_permit.tools import LangchainPermissionsCheckTool\n\npermit_client = Permit(\n    token=\"permit_api_key_here\",\n    pdp=\"http://localhost:7766\" # or your real deployment url\n)\n\npermissions_checker = LangchainPermissionsCheckTool(\n    name=\"permission_check\",\n    permit=permit_client,\n)\n\n# In an async context:\n# result = await permissions_checker._arun(\n#     user={\"key\": \"user123\"},\n#     action=\"read\",\n#     resource={\"type\": \"Document\", \"key\": \"doc123\", \"tenant\": \"default\"}\n# )\n# print(\"Permission check result:\", result)\n```\n\nCheck out `examples/demo_permissions_check.py` for a runnable demonstration.\n\n### PermitSelfQueryRetriever\n\nA custom retriever that:\n\n1. Fetches permitted document IDs from Permit.\n2. Uses an LLM to parse your user’s query into a structured filter (Self Query).\n3. Applies that ID-based filter to the vector store search.\n\n```python\nfrom langchain_openai import OpenAIEmbeddings\nfrom langchain_community.vectorstores import FAISS\nfrom langchain_permit.retrievers import PermitSelfQueryRetriever\n\n# Suppose we have some documents\ndocs = [...]\nembeddings = OpenAIEmbeddings()\nvectorstore = FAISS.from_documents(docs, embeddings)\n\nretriever = PermitSelfQueryRetriever(\n    api_key=\"...\",\n    pdp_url=\"...\",\n    user={\"key\": \"user_123\"},\n    resource_type=\"my_resource\",\n    action=\"view\",\n    llm=embeddings,                # or ChatOpenAI, for actual LLM-based query parsing\n    vectorstore=vectorstore,\n    enable_limit=False,\n)\n\nquery = \"Which docs talk about cats?\"\ndocs = retriever.get_relevant_documents(query)\nfor doc in docs:\n    print(doc.metadata.get(\"id\"), doc.page_content)\n```\n\nSee a complete script at `examples/demo_self_query.py`.\n\n### PermitEnsembleRetriever\n\nThis retriever leverages EnsembleRetriever from LangChain, merging multiple child retrievers, and then uses Permit to filter out any unauthorized docs.\n\n```python\nimport os\nimport asyncio\nfrom langchain_core.documents import Document\nfrom langchain_community.vectorstores import FAISS\nfrom langchain_openai import OpenAIEmbeddings\nfrom langchain_permit.retrievers import PermitEnsembleRetriever\n\nasync def main():\n    # Sample documents\n    texts = [\n        (\"doc_a\", \"Cats are wonderful creatures...\"),\n        (\"doc_b\", \"Dogs are quite loyal...\"),\n    ]\n    docs = [Document(page_content=txt, metadata={\"id\": idx}) for (idx, txt) in texts]\n\n    # Vector store\n    embeddings = OpenAIEmbeddings()\n    vectorstore = FAISS.from_documents(docs, embedding=embeddings)\n    vector_retriever = vectorstore.as_retriever(search_kwargs={\"k\": 2})\n\n    # Ensemble with just one child retriever for simplicity\n    ensemble_retriever = PermitEnsembleRetriever(\n        api_key=os.getenv(\"PERMIT_API_KEY\", \"\"),\n        pdp_url=os.getenv(\"PERMIT_PDP_URL\"),\n        user=\"user_abc\",\n        action=\"view\",\n        resource_type=\"my_resource\",\n        retrievers=[vector_retriever],  # Or pass multiple retrievers\n    )\n\n    query = \"tell me about cats\"\n    results = await ensemble_retriever._aget_relevant_documents(query, run_manager=None)\n\n    for i, doc in enumerate(results, start=1):\n        print(f\"{i}. {doc.metadata.get('id')}: {doc.page_content}\")\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\nCheck out examples/demo_ensemble.py for a more complete version.\n\n## Requirements\n\n1. Python 3.8+\n2. [Permit.io](https://app.permit.io/) Account\n3. [LangChain](https://python.langchain.com/docs/introduction/)\n\n## License\n\nThis project is MIT Licensed. See [Permit.io Docs](https://docs.permit.io/) for terms related to the Permit PDP and hosted services.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpermitio%2Flangchain-permit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpermitio%2Flangchain-permit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpermitio%2Flangchain-permit/lists"}