Skip to content

Commit d5ade14

Browse files
authored
doc(langchain-sdk): Add guidance for configuring and using authenticated tools in Toolbox. (#146)
1 parent b95bb90 commit d5ade14

File tree

1 file changed

+104
-8
lines changed

1 file changed

+104
-8
lines changed

README.md

Lines changed: 104 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ applications, enabling advanced orchestration and interaction with GenAI models.
1616
- [Represent Tools as Nodes](#represent-tools-as-nodes)
1717
- [Connect Tools with LLM](#connect-tools-with-llm)
1818
- [Manual usage](#manual-usage)
19+
- [Authenticating Tools](#authenticating-tools)
20+
- [Supported Authentication Mechanisms](#supported-authentication-mechanisms)
21+
- [Configuring Tools for Authentication](#configuring-tools-for-authentication)
22+
- [Configure SDK for Authentication](#configure-sdk-for-authentication)
23+
- [Complete Example](#complete-example)
1924

2025
<!-- /TOC -->
2126
## Installation
@@ -33,7 +38,7 @@ pip install toolbox-langchain-sdk
3338

3439
Import and initialize the toolbox client.
3540

36-
```python
41+
```py
3742
from toolbox_langchain_sdk import ToolboxClient
3843

3944
# Replace with your Toolbox service's URL
@@ -48,7 +53,7 @@ toolbox = ToolboxClient("http://127.0.0.1:5000")
4853
> [!TIP]
4954
> You can also pass your own `ClientSession` so that the `ToolboxClient` can
5055
> reuse the same session.
51-
> ```
56+
> ```py
5257
> async with ClientSession() as session:
5358
> toolbox = ToolboxClient("http://localhost:5000", session)
5459
> ```
@@ -57,7 +62,7 @@ toolbox = ToolboxClient("http://127.0.0.1:5000")
5762
5863
You can load a toolset, a collection of related tools.
5964
60-
```python
65+
```py
6166
# Load all tools
6267
tools = await toolbox.load_toolset()
6368
@@ -69,7 +74,7 @@ tools = await toolbox.load_toolset("my-toolset")
6974

7075
You can also load a single tool.
7176

72-
```python
77+
```py
7378
tool = await toolbox.load_tool("my-tool")
7479
```
7580

@@ -79,7 +84,7 @@ LangChain's agents can dynamically choose and execute tools based on the user
7984
input. The user can include the tools loaded from the Toolbox SDK in the agent's
8085
toolkit.
8186

82-
```python
87+
```py
8388
from langchain_google_vertexai import ChatVertexAI
8489

8590
model = ChatVertexAI(model="gemini-1.5-flash")
@@ -103,7 +108,7 @@ minimal changes.
103108
Each tool generated by the SDK can be represented as a LangGraph node. The
104109
node's functionality would encapsulate the execution of the corresponding tool.
105110

106-
```python
111+
```py
107112
from toolbox_langchain_sdk import ToolboxClient
108113
from langgraph.graph import StateGraph, MessagesState
109114
from langgraph.prebuilt import ToolNode
@@ -130,7 +135,7 @@ to use based on the user input or the context of the conversation. The output
130135
from a tool can then be fed back into the LLM for further processing or
131136
decision-making.
132137

133-
```python
138+
```py
134139
from typing import Literal
135140
from langgraph.graph import END, START
136141
from langchain_core.messages import HumanMessage
@@ -163,6 +168,97 @@ graph.invoke(
163168

164169
You can also execute a tool manually using the `arun` method.
165170

166-
```python
171+
```py
167172
result = await tools[0].arun({ "name": "Alice", "age": 30 })
168173
```
174+
175+
## Authenticating Tools
176+
177+
> [!WARNING]
178+
> Always use HTTPS to connect your application with the Toolbox service,
179+
> especially when using tools with authentication configured. Using HTTP exposes
180+
> your application to serious security risks, including unauthorized access to
181+
> user information and man-in-the-middle attacks, where sensitive data can be
182+
> intercepted.
183+
184+
Some tools in your Toolbox configuration might require user authentication to
185+
access sensitive data. This section guides you on how to configure tools for
186+
authentication and use them with the SDK.
187+
188+
### Supported Authentication Mechanisms
189+
The Toolbox SDK currently supports authentication using [OIDC
190+
protocol](https://openid.net/specs/openid-connect-core-1_0.html). Specifically,
191+
it uses [ID
192+
tokens](https://openid.net/specs/openid-connect-core-1_0.html#IDToken) and *not*
193+
access tokens for [Google OAuth
194+
2.0](https://cloud.google.com/apigee/docs/api-platform/security/oauth/oauth-home).
195+
196+
### Configuring Tools for Authentication
197+
198+
Refer to [these instructions](https://github.com/googleapis/genai-toolbox/blob/main/docs/tools/README.md#authenticated-parameters) on configuring tools for authenticated parameters.
199+
200+
### Configure SDK for Authentication
201+
202+
Provide the `auth_headers` parameter to the `load_tool` or `load_toolset` calls
203+
with a dictionary. The keys of this dictionary should match the names of the
204+
authentication sources configured in your tools file (e.g., `my_auth_service`),
205+
and the values should be callable functions (e.g., lambdas or regular functions)
206+
that return the ID token of the logged-in user.
207+
208+
Here's an example:
209+
210+
```py
211+
def get_auth_header():
212+
# ... Logic to retrieve ID token (e.g., from local storage, OAuth flow)
213+
# This example just returns a placeholder. Replace with your actual token retrieval.
214+
return "YOUR_ID_TOKEN"
215+
216+
toolbox = ToolboxClient("http://localhost:5000")
217+
218+
tools = toolbox.load_toolset(auth_headers={ "my_auth_service": get_auth_header })
219+
220+
# OR
221+
222+
tool = toolbox.load_tool("my_tool", auth_headers={ "my_auth_service": get_auth_header })
223+
```
224+
225+
Alternatively, you can call the `add_auth_header` method to configure
226+
authentication separately.
227+
228+
```py
229+
toolbox.add_auth_header("my_auth_service", get_auth_header)
230+
```
231+
232+
> [!NOTE]
233+
> After adding authentication headers, either through `load_tool`,
234+
> `load_toolset`, or `add_auth_header`, all subsequent tool invocations from
235+
> that point onward will use these authentications, regardless of whether the
236+
> tool was loaded before or after calling these methods. This maintains a
237+
> consistent authentication context.
238+
239+
### Complete Example
240+
241+
```py
242+
import asyncio
243+
from toolbox_langchain_sdk import ToolboxClient
244+
245+
async def get_auth_header():
246+
# Replace with your actual ID token retrieval logic.
247+
# For example, using a library like google-auth
248+
# from google.oauth2 import id_token
249+
# from google.auth.transport import requests
250+
# request = requests.Request()
251+
# id_token_string = id_token.fetch_id_token(request, "YOUR_AUDIENCE")# Replace with your audience
252+
# return id_token_string
253+
return "YOUR_ACTUAL_ID_TOKEN" # placeholder
254+
255+
async def main():
256+
toolbox = ToolboxClient("http://localhost:5000")
257+
toolbox.add_auth_header("my_auth_service", get_auth_header)
258+
tools = await toolbox.load_toolset()
259+
result = await tools[0].arun({"input": "some input"})
260+
print(result)
261+
262+
if __name__ == "__main__":
263+
asyncio.run(main())
264+
```

0 commit comments

Comments
 (0)