Skip to content

Commit 956591d

Browse files
authored
feat(sdk): make ClientSession optional when initializing ToolboxClient (#55)
1 parent d790ab6 commit 956591d

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ from toolbox_langchain_sdk import ToolboxClient
4040
toolbox = ToolboxClient("http://localhost:5000")
4141
```
4242

43+
> [!TIP]
44+
> You can also pass your own `ClientSession` so that the `ToolboxClient` can
45+
> reuse the same session.
46+
> ```
47+
> async with ClientSession() as session:
48+
> client = ToolboxClient(http://localhost:5000, session)
49+
> ```
50+
4351
## Load a toolset
4452
4553
You can load a toolset, a collection of related tools.

src/toolbox_langchain_sdk/client.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import asyncio
12
from typing import Optional
23

34
from aiohttp import ClientSession
@@ -8,20 +9,47 @@
89

910

1011
class ToolboxClient:
11-
def __init__(self, url: str, session: ClientSession):
12+
def __init__(self, url: str, session: Optional[ClientSession] = None):
1213
"""
1314
Initializes the ToolboxClient for the Toolbox service at the given URL.
1415
1516
Args:
1617
url: The base URL of the Toolbox service.
1718
session: The HTTP client session.
19+
Default: None
1820
"""
1921
self._url: str = url
20-
self._session = session
22+
self._should_close_session: bool = session != None
23+
self._session: ClientSession = session or ClientSession()
24+
25+
async def close(self) -> None:
26+
"""
27+
Close the Toolbox client and its tools.
28+
"""
29+
# We check whether _should_close_session is set or not since we do not
30+
# want to close the session in case the user had passed their own
31+
# ClientSession object, since then we expect the user to be owning its
32+
# lifecycle.
33+
if self._session and self._should_close_session:
34+
await self._session.close()
35+
36+
def __del__(self):
37+
try:
38+
loop = asyncio.get_event_loop()
39+
if loop.is_running():
40+
loop.create_task(self.close())
41+
else:
42+
loop.run_until_complete(self.close())
43+
except Exception:
44+
# We "pass" assuming that the exception is thrown because the event
45+
# loop is no longer running, but at that point the Session should
46+
# have been closed already anyway.
47+
pass
2148

2249
async def _load_tool_manifest(self, tool_name: str) -> ManifestSchema:
2350
"""
24-
Fetches and parses the YAML manifest for the given tool from the Toolbox service.
51+
Fetches and parses the YAML manifest for the given tool from the Toolbox
52+
service.
2553
2654
Args:
2755
tool_name: The name of the tool to load.
@@ -40,7 +68,8 @@ async def _load_toolset_manifest(
4068
4169
Args:
4270
toolset_name: The name of the toolset to load.
43-
Default: None. If not provided, then all the available tools are loaded.
71+
Default: None. If not provided, then all the available tools are
72+
loaded.
4473
4574
Returns:
4675
The parsed Toolbox manifest.
@@ -52,7 +81,8 @@ def _generate_tool(
5281
self, tool_name: str, manifest: ManifestSchema
5382
) -> StructuredTool:
5483
"""
55-
Creates a StructuredTool object and a dynamically generated BaseModel for the given tool.
84+
Creates a StructuredTool object and a dynamically generated BaseModel
85+
for the given tool.
5686
5787
Args:
5888
tool_name: The name of the tool to generate.
@@ -93,7 +123,8 @@ async def load_toolset(
93123
self, toolset_name: Optional[str] = None
94124
) -> list[StructuredTool]:
95125
"""
96-
Loads tools from the Toolbox service, optionally filtered by toolset name.
126+
Loads tools from the Toolbox service, optionally filtered by toolset
127+
name.
97128
98129
Args:
99130
toolset_name: The name of the toolset to load.

src/toolbox_langchain_sdk/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Type, Optional
1+
from typing import Any, Optional, Type
22

33
import yaml
44
from aiohttp import ClientSession

0 commit comments

Comments
 (0)