auth0-ai-langchain 0.2.0__py3-none-any.whl → 1.0.0b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of auth0-ai-langchain might be problematic. Click here for more details.

@@ -1,115 +0,0 @@
1
- from typing import Optional, List, Callable, Union, Awaitable, TypedDict
2
- from abc import ABC, abstractmethod
3
- from langgraph.graph import StateGraph
4
- from langchain_core.messages import AIMessage, ToolMessage
5
- from auth0_ai.authorizers.types import AuthorizerParams
6
- from auth0_ai.authorizers.ciba_authorizer import AuthorizeResponse
7
-
8
- class Auth0State(TypedDict):
9
- error: str
10
-
11
- class BaseState(TypedDict):
12
- task_id: str
13
- messages: List[Union[AIMessage, ToolMessage]]
14
- auth0: Optional[Auth0State] = None
15
-
16
- class SchedulerParams:
17
- def __init__(
18
- self,
19
- user_id: str,
20
- thread_id: str,
21
- ciba_graph_id: str,
22
- ciba_response: AuthorizeResponse,
23
- tool_id: Optional[str] = None,
24
- on_resume_invoke: str = "",
25
- ):
26
- self.user_id = user_id
27
- self.thread_id = thread_id
28
- self.tool_id = tool_id
29
- self.on_resume_invoke = on_resume_invoke
30
- self.ciba_graph_id = ciba_graph_id
31
- self.ciba_response = ciba_response
32
-
33
- class CIBAOptions():
34
- """
35
- The CIBA options.
36
-
37
- Attributes:
38
- binding_message (Union[str, Callable[..., Awaitable[str]]]): A human-readable string to display to the user, or a function that resolves it.
39
- scope (Optional[str]): Space-separated list of OIDC and custom API scopes.
40
- on_approve_go_to (Optional[str]): A node name to redirect the flow after user approval.
41
- on_reject_go_to (Optional[str]): A node name to redirect the flow after user rejection.
42
- audience (Optional[str]): Unique identifier of the audience for an issued token.
43
- request_expiry (Optional[int]): To configure a custom expiry time in seconds for CIBA request, pass a number between 1 and 300.
44
- """
45
- def __init__(
46
- self,
47
- binding_message: Union[str, Callable[..., Awaitable[str]]],
48
- scope: Optional[str] = None,
49
- on_approve_go_to: Optional[str] = None,
50
- on_reject_go_to: Optional[str] = None,
51
- audience: Optional[str] = None,
52
- request_expiry: Optional[int] = None,
53
- ):
54
- self.binding_message = binding_message
55
- self.scope = scope
56
- self.on_approve_go_to = on_approve_go_to
57
- self.on_reject_go_to = on_reject_go_to
58
- self.audience = audience
59
- self.request_expiry = request_expiry
60
-
61
- class ProtectedTool():
62
- def __init__(self, tool_name: str, options: CIBAOptions):
63
- self.tool_name = tool_name
64
- self.options = options
65
-
66
- class CIBAGraphOptionsConfig:
67
- def __init__(self, on_resume_invoke: str, scheduler: Union[str, Callable[[SchedulerParams], Awaitable[None]]]):
68
- self.on_resume_invoke = on_resume_invoke
69
- self.scheduler = scheduler
70
-
71
- class CIBAGraphOptions():
72
- """
73
- The base CIBA options.
74
-
75
- Attributes:
76
- config (CIBAGraphOptionsConfig): Configuration options.
77
- scope (Optional[str]): Space-separated list of OIDC and custom API scopes.
78
- on_approve_go_to (Optional[str]): A node name to redirect the flow after user approval.
79
- on_reject_go_to (Optional[str]): A node name to redirect the flow after user rejection.
80
- audience (Optional[str]): Unique identifier of the audience for an issued token.
81
- request_expiry (Optional[int]): To configure a custom expiry time in seconds for CIBA request, pass a number between 1 and 300.
82
- """
83
- def __init__(
84
- self,
85
- config: CIBAGraphOptionsConfig,
86
- scope: Optional[str] = None,
87
- on_approve_go_to: Optional[str] = None,
88
- on_reject_go_to: Optional[str] = None,
89
- audience: Optional[str] = None,
90
- request_expiry: Optional[int] = None,
91
-
92
- ):
93
- self.config = config
94
- self.scope = scope
95
- self.on_approve_go_to = on_approve_go_to
96
- self.on_reject_go_to = on_reject_go_to
97
- self.audience = audience
98
- self.request_expiry = request_expiry
99
-
100
- class ICIBAGraph(ABC):
101
- @abstractmethod
102
- def get_tools(self) -> List[ProtectedTool]:
103
- pass
104
-
105
- @abstractmethod
106
- def get_graph(self) -> StateGraph:
107
- pass
108
-
109
- @abstractmethod
110
- def get_authorizer_params(self) -> Optional[AuthorizerParams]:
111
- pass
112
-
113
- @abstractmethod
114
- def get_options(self) -> Optional[CIBAGraphOptions]:
115
- pass
@@ -1,17 +0,0 @@
1
- from typing import Optional, List
2
- from .types import ProtectedTool, BaseState
3
-
4
- def get_tool_definition(state: BaseState, tools: List[ProtectedTool]) -> Optional[dict]:
5
- message = state["messages"][-1]
6
-
7
- if not hasattr(message, "tool_calls") or not message.tool_calls:
8
- return None
9
-
10
- tool_calls = message.tool_calls
11
- tool = tool_calls[-1]
12
- metadata = next((t for t in tools if t.tool_name == tool["name"]), None)
13
-
14
- if not metadata:
15
- return None
16
-
17
- return {"metadata": metadata, "tool": tool, "message": message}
@@ -1,105 +0,0 @@
1
- import os
2
- from typing import Awaitable, Callable, Optional, TypedDict, Union
3
-
4
- from auth0_ai.authorizers.ciba_authorizer import (
5
- AuthorizeResponse,
6
- CIBAAuthorizer,
7
- CibaAuthorizerCheckResponse,
8
- )
9
- from auth0_ai.credentials import Credentials
10
- from auth0_ai.token_response import TokenResponse
11
- from langgraph.graph import END, START, StateGraph
12
- from langgraph_sdk import get_client
13
- from langgraph_sdk.schema import Command
14
-
15
- from auth0_ai_langchain.ciba.types import Auth0Graphs
16
-
17
-
18
- class State(TypedDict):
19
- ciba_response: AuthorizeResponse
20
- on_resume_invoke: str
21
- thread_id: str
22
- user_id: str
23
-
24
- # Internal
25
- task_id: str
26
- tool_id: str
27
- status: CibaAuthorizerCheckResponse
28
- token_response: Optional[TokenResponse]
29
-
30
-
31
- def ciba_poller_graph(on_stop_scheduler: Union[str, Callable[[State], Awaitable[None]]]):
32
- """
33
- A LangGraph graph to monitor the status of a CIBA transaction.
34
-
35
- Attributes:
36
- on_stop_scheduler (Union[str, Callable[[State], Awaitable[None]]]): A graph name to redirect the flow, or a function to execute when the CIBA transaction expires.
37
- """
38
- async def check_status(state: State):
39
- try:
40
- res = await CIBAAuthorizer.check(state["ciba_response"]["auth_req_id"])
41
- state["token_response"] = res.get("token")
42
- state["status"] = res.get("status")
43
- except Exception as e:
44
- print(f"Error in check_status: {e}")
45
- return state
46
-
47
- async def stop_scheduler(state: State):
48
- try:
49
- if isinstance(on_stop_scheduler, str):
50
- langgraph = get_client(url=os.getenv(
51
- "LANGGRAPH_API_URL", "http://localhost:54367"))
52
- await langgraph.crons.create_for_thread(state.thread_id, Auth0Graphs.CIBA_POLLER.value)
53
- elif callable(on_stop_scheduler):
54
- await on_stop_scheduler(state)
55
- except Exception as e:
56
- print(f"Error in stop_scheduler: {e}")
57
- return state
58
-
59
- async def resume_agent(state: State):
60
- langgraph = get_client(url=os.getenv(
61
- "LANGGRAPH_API_URL", "http://localhost:54367"))
62
- _credentials: Credentials = None
63
-
64
- try:
65
- if state["status"] == CibaAuthorizerCheckResponse.APPROVED:
66
- _credentials = {
67
- "access_token": {
68
- "type": state["token_response"].get("token_type", "Bearer"),
69
- "value": state["token_response"].get("access_token"),
70
- }
71
- }
72
-
73
- await langgraph.runs.wait(
74
- state["thread_id"],
75
- state["on_resume_invoke"],
76
- config={
77
- # this is only for this run / thread_id
78
- "configurable": {"_credentials": _credentials}
79
- },
80
- command=Command(resume={"status": state["status"]})
81
- )
82
- except Exception as e:
83
- print(f"Error in resume_agent: {e}")
84
-
85
- return state
86
-
87
- async def should_continue(state: State):
88
- status = state.get("status")
89
- if status == CibaAuthorizerCheckResponse.PENDING:
90
- return END
91
- elif status == CibaAuthorizerCheckResponse.EXPIRED:
92
- return "stop_scheduler"
93
- elif status in [CibaAuthorizerCheckResponse.APPROVED, CibaAuthorizerCheckResponse.REJECTED]:
94
- return "resume_agent"
95
- return END
96
-
97
- state_graph = StateGraph(State)
98
- state_graph.add_node("check_status", check_status)
99
- state_graph.add_node("stop_scheduler", stop_scheduler)
100
- state_graph.add_node("resume_agent", resume_agent)
101
- state_graph.add_edge(START, "check_status")
102
- state_graph.add_edge("resume_agent", "stop_scheduler")
103
- state_graph.add_conditional_edges("check_status", should_continue)
104
-
105
- return state_graph
@@ -1,8 +0,0 @@
1
- from enum import Enum
2
-
3
- class Auth0Nodes(Enum):
4
- AUTH0_CIBA_HITL = "AUTH0_CIBA_HITL"
5
- AUTH0_CIBA = "AUTH0_CIBA"
6
-
7
- class Auth0Graphs(Enum):
8
- CIBA_POLLER = "AUTH0_CIBA_POLLER"
@@ -1,3 +0,0 @@
1
- from auth0_ai.authorizers.fga_authorizer import FGAAuthorizer, FGAAuthorizerOptions
2
-
3
- __all__ = ["FGAAuthorizer", "FGAAuthorizerOptions"]
@@ -1,221 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: auth0-ai-langchain
3
- Version: 0.2.0
4
- Summary: This package is an SDK for building secure AI-powered applications using Auth0, Okta FGA and LangChain.
5
- License: Apache-2.0
6
- Author: Auth0
7
- Author-email: support@auth0.com
8
- Requires-Python: >=3.11,<4.0
9
- Classifier: License :: OSI Approved :: Apache Software License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.11
12
- Classifier: Programming Language :: Python :: 3.12
13
- Classifier: Programming Language :: Python :: 3.13
14
- Requires-Dist: auth0-ai (>=0.2.0,<0.3.0)
15
- Requires-Dist: langchain (>=0.3.20,<0.4.0)
16
- Requires-Dist: langchain-core (>=0.3.43,<0.4.0)
17
- Requires-Dist: langgraph (>=0.3.25,<0.4.0)
18
- Requires-Dist: langgraph-sdk (>=0.1.55,<0.2.0)
19
- Requires-Dist: openfga-sdk (>=0.9.0,<0.10.0)
20
- Project-URL: Homepage, https://auth0.com
21
- Description-Content-Type: text/markdown
22
-
23
- # Auth0 AI for LangChain
24
-
25
- `auth0-ai-langchain` is an SDK for building secure AI-powered applications using [Auth0](https://www.auth0.ai/), [Okta FGA](https://docs.fga.dev/) and [LangChain](https://python.langchain.com/docs/tutorials/).
26
-
27
- ![Release](https://img.shields.io/pypi/v/auth0-ai-langchain) ![Downloads](https://img.shields.io/pypi/dw/auth0-ai-langchain) [![License](https://img.shields.io/:license-APACHE%202.0-blue.svg?style=flat)](https://opensource.org/license/apache-2-0)
28
-
29
- ## Installation
30
-
31
- > ⚠️ **WARNING**: `auth0-ai-langchain` is currently under development and it is not intended to be used in production, and therefore has no official support.
32
-
33
- ```bash
34
- pip install auth0-ai-langchain
35
- ```
36
-
37
- ## Authorization for Tools
38
-
39
- The `FGAAuthorizer` can leverage Okta FGA to authorize tools executions. The `FGAAuthorizer.create` function can be used to create an authorizer that checks permissions before executing the tool.
40
-
41
- Full example of [Authorization for Tools](https://github.com/auth0-lab/auth0-ai-python/tree/main/examples/authorization-for-tools/langchain-examples).
42
-
43
- 1. Create an instance of FGA Authorizer:
44
-
45
- ```python
46
- from auth0_ai_langchain.fga.fga_authorizer import FGAAuthorizer, FGAAuthorizerOptions
47
-
48
- fga = FGAAuthorizer.create()
49
- ```
50
-
51
- **Note**: Here, you can configure and specify your FGA credentials. By `default`, they are read from environment variables:
52
-
53
- ```sh
54
- FGA_STORE_ID="<fga-store-id>"
55
- FGA_CLIENT_ID="<fga-client-id>"
56
- FGA_CLIENT_SECRET="<fga-client-secret>"
57
- ```
58
-
59
- 2. Define the FGA query (`build_query`) and, optionally, the `on_unauthorized` handler:
60
-
61
- ```python
62
- from langchain_core.runnables import ensure_config
63
-
64
- async def build_fga_query(tool_input):
65
- user_id = ensure_config().get("configurable",{}).get("user_id")
66
- return {
67
- "user": f"user:{user_id}",
68
- "object": f"asset:{tool_input["ticker"]}",
69
- "relation": "can_buy",
70
- "context": {"current_time": datetime.now(timezone.utc).isoformat()}
71
- }
72
-
73
- def on_unauthorized(tool_input):
74
- return f"The user is not allowed to buy {tool_input["qty"]} shares of {tool_input["ticker"]}."
75
-
76
- use_fga = fga(FGAAuthorizerOptions(
77
- build_query=build_fga_query,
78
- on_unauthorized=on_unauthorized,
79
- ))
80
- ```
81
-
82
- **Note**: The parameters given to the `build_query` and `on_unauthorized` functions are the same as those provided to the tool function.
83
-
84
- 3. Wrap the tool:
85
-
86
- ```python
87
- from langchain_core.tools import StructuredTool
88
-
89
- async def buy_tool_function(ticker: str, qty: int) -> str:
90
- # TODO: implement buy operation
91
- return f"Purchased {qty} shares of {ticker}"
92
-
93
- func=use_fga(buy_tool_function)
94
-
95
- buy_tool = StructuredTool(
96
- func=func,
97
- coroutine=func,
98
- name="buy",
99
- description="Use this function to buy stocks",
100
- )
101
- ```
102
-
103
- ## Calling APIs On User's Behalf
104
-
105
- The `Auth0AI.with_federated_connection` function exchanges user's refresh token taken from the runnable configuration (`config.configurable._credentials.refresh_token`) for a Federated Connection API token.
106
-
107
- Full Example of [Calling APIs On User's Behalf](https://github.com/auth0-lab/auth0-ai-python/tree/main/examples/calling-apis/langchain-examples).
108
-
109
- 1. Define a tool with the proper authorizer:
110
-
111
- ```python
112
- from auth0_ai_langchain.auth0_ai import Auth0AI
113
- from auth0_ai_langchain.federated_connections import get_access_token_for_connection
114
- from langchain_core.tools import StructuredTool
115
-
116
- auth0_ai = Auth0AI()
117
-
118
- with_google_calendar_access = auth0_ai.with_federated_connection(
119
- connection="google-oauth2",
120
- scopes=["https://www.googleapis.com/auth/calendar.freebusy"]
121
- )
122
-
123
- def tool_function(date: datetime):
124
- access_token = get_access_token_for_connection()
125
- # Call Google API
126
-
127
- check_calendar_tool = with_google_calendar_access(
128
- StructuredTool(
129
- name="check_user_calendar",
130
- description="Use this function to check if the user is available on a certain date and time",
131
- func=tool_function,
132
- # ...
133
- )
134
- )
135
- ```
136
-
137
- 2. Add a node to your graph for your tools:
138
-
139
- ```python
140
- workflow = (
141
- StateGraph(State)
142
- .add_node(
143
- "tools",
144
- ToolNode(
145
- [
146
- check_calendar_tool,
147
- # ...
148
- ],
149
- # The error handler should be disabled to allow interruptions to be triggered from within tools.
150
- handle_tool_errors=False
151
- )
152
- )
153
- # ...
154
- )
155
- ```
156
-
157
- 3. Handle interruptions properly. If the tool does not have access to user's Google Calendar, it will throw an interruption.
158
-
159
- ## RAG with FGA
160
-
161
- The `FGARetriever` can be used to filter documents based on access control checks defined in Okta FGA. This retriever performs batch checks on retrieved documents, returning only the ones that pass the specified access criteria.
162
-
163
- Full Example of [RAG Application](https://github.com/auth0-lab/auth0-ai-python/tree/main/examples/authorization-for-rag/langchain-examples).
164
-
165
- Create a retriever instance using the `FGARetriever` class.
166
-
167
- ```python
168
- from langchain.vectorstores import VectorStoreIndex
169
- from langchain.schema import Document
170
- from auth0_ai_langchain import FGARetriever
171
- from openfga_sdk.client.models import ClientCheckRequest
172
- from openfga_sdk import ClientConfiguration
173
- from openfga_sdk.credentials import CredentialConfiguration, Credentials
174
-
175
- # Define some docs:
176
- documents = [
177
- Document(page_content="This is a public doc", metadata={"doc_id": "public-doc"}),
178
- Document(page_content="This is a private doc", metadata={"doc_id": "private-doc"}),
179
- ]
180
-
181
- # Create a vector store:
182
- vector_store = VectorStoreIndex.from_documents(documents)
183
-
184
- # Create a retriever:
185
- base_retriever = vector_store.as_retriever()
186
-
187
- # Create the FGA retriever wrapper:
188
- retriever = FGARetriever(
189
- base_retriever,
190
- build_query=lambda node: ClientCheckRequest(
191
- user=f'user:{user}',
192
- object=f'doc:{node.metadata["doc_id"]}',
193
- relation="viewer",
194
- )
195
- )
196
-
197
- # Create a query engine:
198
- query_engine = RetrieverQueryEngine.from_args(
199
- retriever=retriever,
200
- llm=OpenAI()
201
- )
202
-
203
- # Query:
204
- response = query_engine.query("What is the forecast for ZEKO?")
205
-
206
- print(response)
207
- ```
208
-
209
- ---
210
-
211
- <p align="center">
212
- <picture>
213
- <source media="(prefers-color-scheme: light)" srcset="https://cdn.auth0.com/website/sdks/logos/auth0_light_mode.png" width="150">
214
- <source media="(prefers-color-scheme: dark)" srcset="https://cdn.auth0.com/website/sdks/logos/auth0_dark_mode.png" width="150">
215
- <img alt="Auth0 Logo" src="https://cdn.auth0.com/website/sdks/logos/auth0_light_mode.png" width="150">
216
- </picture>
217
- </p>
218
- <p align="center">Auth0 is an easy to implement, adaptable authentication and authorization platform. To learn more checkout <a href="https://auth0.com/why-auth0">Why Auth0?</a></p>
219
- <p align="center">
220
- This project is licensed under the Apache 2.0 license. See the <a href="https://github.com/auth0-lab/auth0-ai-python/blob/main/LICENSE"> LICENSE</a> file for more info.</p>
221
-
@@ -1,19 +0,0 @@
1
- auth0_ai_langchain/FGARetriever.py,sha256=6nQXRkbDLHZt9zYZJsS5iQljrogQVLW0aVwDIf6Mpac,6002
2
- auth0_ai_langchain/__init__.py,sha256=I331Kz-q97ZU7TfXaOR5UBbJamGEJ15twbf2HP1iCHs,67
3
- auth0_ai_langchain/auth0_ai.py,sha256=8NUV_80SxR8qQt_3RQGf0Oga178kChuROHuhz7rfOyU,1919
4
- auth0_ai_langchain/ciba/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- auth0_ai_langchain/ciba/ciba_graph/ciba_graph.py,sha256=Wi7qXSMzvcfqdO8WsUJejmQzOVM469TFJCkH7eRlaR8,4115
6
- auth0_ai_langchain/ciba/ciba_graph/initialize_ciba.py,sha256=a41KedBzxfLqG2AhvkFnemcEqWwQWVh1r-Oro-qJX-M,3752
7
- auth0_ai_langchain/ciba/ciba_graph/initialize_hitl.py,sha256=CR3jMolZYYOBHx1AXb6yERBaZThMg677qGGo_vRy6I8,1901
8
- auth0_ai_langchain/ciba/ciba_graph/types.py,sha256=NZS99vPOgJRc2O7mO5MWj6nAa4RSG1R5oSvzYhkz0RA,4234
9
- auth0_ai_langchain/ciba/ciba_graph/utils.py,sha256=ZPAh0Gs7Hj59_xngg8M7yx1v52dTn2pNpMNRpFKCSII,560
10
- auth0_ai_langchain/ciba/ciba_poller_graph.py,sha256=rjlxsTheJrN2J6E5BCE9aVyDO8V7UFhdKyX4KT_hB8k,3828
11
- auth0_ai_langchain/ciba/types.py,sha256=gybqYEprklZwcMBgaWFooBsJ1GcNUK8ZWRvAX5PZWdE,177
12
- auth0_ai_langchain/federated_connections/__init__.py,sha256=nWA0eZj88nkamiZz8Wx-KVZ9r1faNNjWBdQAYfrPO1A,480
13
- auth0_ai_langchain/federated_connections/federated_connection_authorizer.py,sha256=ZLF4p7fPTrODOeHWIShfBTsReSy27u73rIp0L_Umhjg,2218
14
- auth0_ai_langchain/fga/fga_authorizer.py,sha256=uDaGDSXaxQd1X-2w2zTvnfizMB-DtQ-1G6SIaDNBrho,137
15
- auth0_ai_langchain/utils/interrupt.py,sha256=HHmlwKwQR_sx8dsV_cZTCYLDo6n6JuiPyLJxbhiI84w,449
16
- auth0_ai_langchain-0.2.0.dist-info/LICENSE,sha256=Lu_2YH0oK8b_VVisAhNQ2WIdtwY8pSU2PLbll-y6Cj8,9792
17
- auth0_ai_langchain-0.2.0.dist-info/METADATA,sha256=Gn337MU0yUTAFP_DUyRhkyxj6j5jw4frYmVpJmPMqis,7793
18
- auth0_ai_langchain-0.2.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
19
- auth0_ai_langchain-0.2.0.dist-info/RECORD,,