langchain-apiverve 0.1.0__tar.gz
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.
- langchain_apiverve-0.1.0/LICENSE +21 -0
- langchain_apiverve-0.1.0/PKG-INFO +285 -0
- langchain_apiverve-0.1.0/README.md +248 -0
- langchain_apiverve-0.1.0/pyproject.toml +98 -0
- langchain_apiverve-0.1.0/src/langchain_apiverve/__init__.py +31 -0
- langchain_apiverve-0.1.0/src/langchain_apiverve/client.py +145 -0
- langchain_apiverve-0.1.0/src/langchain_apiverve/schemas.py +50 -0
- langchain_apiverve-0.1.0/src/langchain_apiverve/toolkit.py +305 -0
- langchain_apiverve-0.1.0/src/langchain_apiverve/tools.py +13 -0
- langchain_apiverve-0.1.0/src/langchain_apiverve/utils.py +26 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 EvlarSoft LLC and APIVerve
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: langchain-apiverve
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: LangChain integration for APIVerve - Access 310+ utility APIs for AI agents
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: langchain,langchain-integration,apiverve,api,ai,llm,agents,tools,validation,utilities
|
|
8
|
+
Author: APIVerve
|
|
9
|
+
Author-email: hello@apiverve.com
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: langchain-core (>=0.2.0)
|
|
24
|
+
Requires-Dist: mypy (>=1.0.0) ; extra == "dev"
|
|
25
|
+
Requires-Dist: pydantic (>=2.0.0)
|
|
26
|
+
Requires-Dist: pytest (>=7.0.0) ; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-asyncio (>=0.21.0) ; extra == "dev"
|
|
28
|
+
Requires-Dist: requests (>=2.28.0)
|
|
29
|
+
Requires-Dist: ruff (>=0.1.0) ; extra == "dev"
|
|
30
|
+
Project-URL: Changelog, https://github.com/apiverve/langchain-apiverve/releases
|
|
31
|
+
Project-URL: Documentation, https://docs.apiverve.com
|
|
32
|
+
Project-URL: Homepage, https://apiverve.com
|
|
33
|
+
Project-URL: Issues, https://github.com/apiverve/langchain-apiverve/issues
|
|
34
|
+
Project-URL: Repository, https://github.com/apiverve/langchain-apiverve
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# langchain-apiverve
|
|
38
|
+
|
|
39
|
+
[](https://pypi.org/project/langchain-apiverve/)
|
|
40
|
+
[](https://pypi.org/project/langchain-apiverve/)
|
|
41
|
+
[](https://opensource.org/licenses/MIT)
|
|
42
|
+
[](https://python.langchain.com/)
|
|
43
|
+
|
|
44
|
+
**LangChain integration for [APIVerve](https://apiverve.com)** - Access 310+ utility APIs for AI agents and LLM applications.
|
|
45
|
+
|
|
46
|
+
Build powerful AI agents with access to validation, conversion, generation, analysis, and lookup APIs.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Features
|
|
51
|
+
|
|
52
|
+
- **310+ APIs** - Email validation, DNS lookup, IP geolocation, QR codes, currency conversion, and more
|
|
53
|
+
- **29 Categories** - Data Lookup, News, Domain Data, Data Conversion, Entertainment, and more
|
|
54
|
+
- **LangChain Native** - Works with any LangChain agent or chain
|
|
55
|
+
- **Type Safe** - Full Pydantic schemas for inputs and outputs
|
|
56
|
+
- **Async Support** - Both sync and async API calls
|
|
57
|
+
- **Flexible** - Use individual tools or the "run any" meta-tool
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Installation
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install langchain-apiverve
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from langchain_apiverve import APIVerveToolkit
|
|
71
|
+
from langchain_openai import ChatOpenAI
|
|
72
|
+
from langchain.agents import create_tool_calling_agent, AgentExecutor
|
|
73
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
74
|
+
|
|
75
|
+
# Initialize toolkit with your API key
|
|
76
|
+
toolkit = APIVerveToolkit(api_key="your-api-key")
|
|
77
|
+
# Or set APIVERVE_API_KEY environment variable
|
|
78
|
+
|
|
79
|
+
# Get tools
|
|
80
|
+
tools = toolkit.get_tools()
|
|
81
|
+
|
|
82
|
+
# Create an agent
|
|
83
|
+
llm = ChatOpenAI(model="gpt-4")
|
|
84
|
+
prompt = ChatPromptTemplate.from_messages([
|
|
85
|
+
("system", "You are a helpful assistant with access to various utility APIs."),
|
|
86
|
+
("human", "{input}"),
|
|
87
|
+
("placeholder", "{agent_scratchpad}"),
|
|
88
|
+
])
|
|
89
|
+
|
|
90
|
+
agent = create_tool_calling_agent(llm, tools, prompt)
|
|
91
|
+
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
|
|
92
|
+
|
|
93
|
+
# Use the agent
|
|
94
|
+
result = executor.invoke({"input": "Is test@example.com a valid email?"})
|
|
95
|
+
print(result["output"])
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Usage Examples
|
|
101
|
+
|
|
102
|
+
### Using Individual Tools
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from langchain_apiverve import APIVerveToolkit
|
|
106
|
+
|
|
107
|
+
toolkit = APIVerveToolkit(api_key="your-api-key")
|
|
108
|
+
|
|
109
|
+
# Get specific tools
|
|
110
|
+
tools = toolkit.get_tools(include_apis=["emailvalidator", "dnslookup"])
|
|
111
|
+
|
|
112
|
+
# Use a tool directly
|
|
113
|
+
email_tool = tools[0]
|
|
114
|
+
result = email_tool.invoke({"email": "user@example.com"})
|
|
115
|
+
print(result)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Using the "Run Any" Tool
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from langchain_apiverve import APIVerveToolkit
|
|
122
|
+
|
|
123
|
+
toolkit = APIVerveToolkit(api_key="your-api-key")
|
|
124
|
+
|
|
125
|
+
# Get the flexible run-any tool
|
|
126
|
+
run_any = toolkit.get_run_any_tool()
|
|
127
|
+
|
|
128
|
+
# Call any API dynamically
|
|
129
|
+
result = run_any.invoke({
|
|
130
|
+
"api_id": "qrcodegenerator",
|
|
131
|
+
"parameters": {"value": "https://example.com"}
|
|
132
|
+
})
|
|
133
|
+
print(result)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Filtering Tools by Category
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from langchain_apiverve import APIVerveToolkit
|
|
140
|
+
|
|
141
|
+
toolkit = APIVerveToolkit(api_key="your-api-key")
|
|
142
|
+
|
|
143
|
+
# Get only validation tools
|
|
144
|
+
validation_tools = toolkit.get_tools(categories=["Validation"])
|
|
145
|
+
|
|
146
|
+
# Get only lookup tools
|
|
147
|
+
lookup_tools = toolkit.get_tools(categories=["Lookup"])
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Low-Level Client Usage
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from langchain_apiverve import APIVerveClient
|
|
154
|
+
|
|
155
|
+
client = APIVerveClient(api_key="your-api-key")
|
|
156
|
+
|
|
157
|
+
# Make API calls directly
|
|
158
|
+
result = client.call_api("emailvalidator", {"email": "test@example.com"})
|
|
159
|
+
print(result)
|
|
160
|
+
|
|
161
|
+
# Async usage
|
|
162
|
+
import asyncio
|
|
163
|
+
|
|
164
|
+
async def main():
|
|
165
|
+
result = await client.acall_api("dnslookup", {"domain": "example.com"})
|
|
166
|
+
print(result)
|
|
167
|
+
|
|
168
|
+
asyncio.run(main())
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Available APIs
|
|
174
|
+
|
|
175
|
+
APIVerve provides 310+ APIs across 29 categories:
|
|
176
|
+
|
|
177
|
+
| Category | APIs | Examples |
|
|
178
|
+
|----------|------|----------|
|
|
179
|
+
| **Data Lookup** | 15 | World Time, Thesaurus, Emoji Lookup |
|
|
180
|
+
| **News** | 1 | World News |
|
|
181
|
+
| **Domain Data** | 15 | DNS Lookup, WHOIS Lookup, SSL Certificate Checker |
|
|
182
|
+
| **Data Conversion** | 32 | Unit Converter, Number to Words, Words to Numbers |
|
|
183
|
+
| **Entertainment** | 24 | Chuck Norris Jokes, Historical Events, Random Facts |
|
|
184
|
+
| **Weather** | 8 | Air Quality, Marine Weather, Weather |
|
|
185
|
+
| **Science** | 4 | Meteorite Landings, Stars Lookup, Periodic Table |
|
|
186
|
+
| **Finance** | 13 | Mortgage Calculator, Loan Calculator, Currency Symbols |
|
|
187
|
+
| **Transportation** | 4 | Airports Lookup, Airline Lookup, Car Models |
|
|
188
|
+
| **Data Generation** | 32 | Baby Name Generator, Random Word, Random User Generator |
|
|
189
|
+
|
|
190
|
+
[Browse all APIs →](https://apiverve.com/marketplace)
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## API Response Format
|
|
195
|
+
|
|
196
|
+
All APIVerve APIs return a consistent response format:
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"status": "ok",
|
|
201
|
+
"error": null,
|
|
202
|
+
"data": {
|
|
203
|
+
// API-specific response data
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Configuration
|
|
211
|
+
|
|
212
|
+
### Environment Variables
|
|
213
|
+
|
|
214
|
+
| Variable | Description |
|
|
215
|
+
|----------|-------------|
|
|
216
|
+
| `APIVERVE_API_KEY` | Your APIVerve API key |
|
|
217
|
+
|
|
218
|
+
### Toolkit Options
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
toolkit = APIVerveToolkit(
|
|
222
|
+
api_key="...", # API key (or use env var)
|
|
223
|
+
base_url="...", # Custom API base URL
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
tools = toolkit.get_tools(
|
|
227
|
+
categories=["..."], # Filter by category
|
|
228
|
+
include_apis=["..."], # Only include specific APIs
|
|
229
|
+
exclude_apis=["..."], # Exclude specific APIs
|
|
230
|
+
include_run_any=True, # Include the "run any" tool
|
|
231
|
+
include_popular=True, # Include pre-built popular tools
|
|
232
|
+
)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Development
|
|
238
|
+
|
|
239
|
+
### Setup
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# Clone the repository
|
|
243
|
+
git clone https://github.com/apiverve/langchain-apiverve.git
|
|
244
|
+
cd langchain-apiverve
|
|
245
|
+
|
|
246
|
+
# Install with Poetry
|
|
247
|
+
poetry install
|
|
248
|
+
|
|
249
|
+
# Or with pip
|
|
250
|
+
pip install -e ".[dev]"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Running Tests
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
pytest
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Linting
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
ruff check .
|
|
263
|
+
mypy src/
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Resources
|
|
269
|
+
|
|
270
|
+
| Resource | Link |
|
|
271
|
+
|----------|------|
|
|
272
|
+
| APIVerve Website | [apiverve.com](https://apiverve.com) |
|
|
273
|
+
| API Documentation | [docs.apiverve.com](https://docs.apiverve.com) |
|
|
274
|
+
| API Marketplace | [apiverve.com/marketplace](https://apiverve.com/marketplace) |
|
|
275
|
+
| LangChain Docs | [python.langchain.com](https://python.langchain.com) |
|
|
276
|
+
| GitHub Issues | [github.com/apiverve/langchain-apiverve/issues](https://github.com/apiverve/langchain-apiverve/issues) |
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
283
|
+
|
|
284
|
+
Copyright (c) 2025 [APIVerve](https://apiverve.com)
|
|
285
|
+
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# langchain-apiverve
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/langchain-apiverve/)
|
|
4
|
+
[](https://pypi.org/project/langchain-apiverve/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://python.langchain.com/)
|
|
7
|
+
|
|
8
|
+
**LangChain integration for [APIVerve](https://apiverve.com)** - Access 310+ utility APIs for AI agents and LLM applications.
|
|
9
|
+
|
|
10
|
+
Build powerful AI agents with access to validation, conversion, generation, analysis, and lookup APIs.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- **310+ APIs** - Email validation, DNS lookup, IP geolocation, QR codes, currency conversion, and more
|
|
17
|
+
- **29 Categories** - Data Lookup, News, Domain Data, Data Conversion, Entertainment, and more
|
|
18
|
+
- **LangChain Native** - Works with any LangChain agent or chain
|
|
19
|
+
- **Type Safe** - Full Pydantic schemas for inputs and outputs
|
|
20
|
+
- **Async Support** - Both sync and async API calls
|
|
21
|
+
- **Flexible** - Use individual tools or the "run any" meta-tool
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install langchain-apiverve
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from langchain_apiverve import APIVerveToolkit
|
|
35
|
+
from langchain_openai import ChatOpenAI
|
|
36
|
+
from langchain.agents import create_tool_calling_agent, AgentExecutor
|
|
37
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
38
|
+
|
|
39
|
+
# Initialize toolkit with your API key
|
|
40
|
+
toolkit = APIVerveToolkit(api_key="your-api-key")
|
|
41
|
+
# Or set APIVERVE_API_KEY environment variable
|
|
42
|
+
|
|
43
|
+
# Get tools
|
|
44
|
+
tools = toolkit.get_tools()
|
|
45
|
+
|
|
46
|
+
# Create an agent
|
|
47
|
+
llm = ChatOpenAI(model="gpt-4")
|
|
48
|
+
prompt = ChatPromptTemplate.from_messages([
|
|
49
|
+
("system", "You are a helpful assistant with access to various utility APIs."),
|
|
50
|
+
("human", "{input}"),
|
|
51
|
+
("placeholder", "{agent_scratchpad}"),
|
|
52
|
+
])
|
|
53
|
+
|
|
54
|
+
agent = create_tool_calling_agent(llm, tools, prompt)
|
|
55
|
+
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
|
|
56
|
+
|
|
57
|
+
# Use the agent
|
|
58
|
+
result = executor.invoke({"input": "Is test@example.com a valid email?"})
|
|
59
|
+
print(result["output"])
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Usage Examples
|
|
65
|
+
|
|
66
|
+
### Using Individual Tools
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from langchain_apiverve import APIVerveToolkit
|
|
70
|
+
|
|
71
|
+
toolkit = APIVerveToolkit(api_key="your-api-key")
|
|
72
|
+
|
|
73
|
+
# Get specific tools
|
|
74
|
+
tools = toolkit.get_tools(include_apis=["emailvalidator", "dnslookup"])
|
|
75
|
+
|
|
76
|
+
# Use a tool directly
|
|
77
|
+
email_tool = tools[0]
|
|
78
|
+
result = email_tool.invoke({"email": "user@example.com"})
|
|
79
|
+
print(result)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Using the "Run Any" Tool
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from langchain_apiverve import APIVerveToolkit
|
|
86
|
+
|
|
87
|
+
toolkit = APIVerveToolkit(api_key="your-api-key")
|
|
88
|
+
|
|
89
|
+
# Get the flexible run-any tool
|
|
90
|
+
run_any = toolkit.get_run_any_tool()
|
|
91
|
+
|
|
92
|
+
# Call any API dynamically
|
|
93
|
+
result = run_any.invoke({
|
|
94
|
+
"api_id": "qrcodegenerator",
|
|
95
|
+
"parameters": {"value": "https://example.com"}
|
|
96
|
+
})
|
|
97
|
+
print(result)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Filtering Tools by Category
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from langchain_apiverve import APIVerveToolkit
|
|
104
|
+
|
|
105
|
+
toolkit = APIVerveToolkit(api_key="your-api-key")
|
|
106
|
+
|
|
107
|
+
# Get only validation tools
|
|
108
|
+
validation_tools = toolkit.get_tools(categories=["Validation"])
|
|
109
|
+
|
|
110
|
+
# Get only lookup tools
|
|
111
|
+
lookup_tools = toolkit.get_tools(categories=["Lookup"])
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Low-Level Client Usage
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from langchain_apiverve import APIVerveClient
|
|
118
|
+
|
|
119
|
+
client = APIVerveClient(api_key="your-api-key")
|
|
120
|
+
|
|
121
|
+
# Make API calls directly
|
|
122
|
+
result = client.call_api("emailvalidator", {"email": "test@example.com"})
|
|
123
|
+
print(result)
|
|
124
|
+
|
|
125
|
+
# Async usage
|
|
126
|
+
import asyncio
|
|
127
|
+
|
|
128
|
+
async def main():
|
|
129
|
+
result = await client.acall_api("dnslookup", {"domain": "example.com"})
|
|
130
|
+
print(result)
|
|
131
|
+
|
|
132
|
+
asyncio.run(main())
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Available APIs
|
|
138
|
+
|
|
139
|
+
APIVerve provides 310+ APIs across 29 categories:
|
|
140
|
+
|
|
141
|
+
| Category | APIs | Examples |
|
|
142
|
+
|----------|------|----------|
|
|
143
|
+
| **Data Lookup** | 15 | World Time, Thesaurus, Emoji Lookup |
|
|
144
|
+
| **News** | 1 | World News |
|
|
145
|
+
| **Domain Data** | 15 | DNS Lookup, WHOIS Lookup, SSL Certificate Checker |
|
|
146
|
+
| **Data Conversion** | 32 | Unit Converter, Number to Words, Words to Numbers |
|
|
147
|
+
| **Entertainment** | 24 | Chuck Norris Jokes, Historical Events, Random Facts |
|
|
148
|
+
| **Weather** | 8 | Air Quality, Marine Weather, Weather |
|
|
149
|
+
| **Science** | 4 | Meteorite Landings, Stars Lookup, Periodic Table |
|
|
150
|
+
| **Finance** | 13 | Mortgage Calculator, Loan Calculator, Currency Symbols |
|
|
151
|
+
| **Transportation** | 4 | Airports Lookup, Airline Lookup, Car Models |
|
|
152
|
+
| **Data Generation** | 32 | Baby Name Generator, Random Word, Random User Generator |
|
|
153
|
+
|
|
154
|
+
[Browse all APIs →](https://apiverve.com/marketplace)
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## API Response Format
|
|
159
|
+
|
|
160
|
+
All APIVerve APIs return a consistent response format:
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"status": "ok",
|
|
165
|
+
"error": null,
|
|
166
|
+
"data": {
|
|
167
|
+
// API-specific response data
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Configuration
|
|
175
|
+
|
|
176
|
+
### Environment Variables
|
|
177
|
+
|
|
178
|
+
| Variable | Description |
|
|
179
|
+
|----------|-------------|
|
|
180
|
+
| `APIVERVE_API_KEY` | Your APIVerve API key |
|
|
181
|
+
|
|
182
|
+
### Toolkit Options
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
toolkit = APIVerveToolkit(
|
|
186
|
+
api_key="...", # API key (or use env var)
|
|
187
|
+
base_url="...", # Custom API base URL
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
tools = toolkit.get_tools(
|
|
191
|
+
categories=["..."], # Filter by category
|
|
192
|
+
include_apis=["..."], # Only include specific APIs
|
|
193
|
+
exclude_apis=["..."], # Exclude specific APIs
|
|
194
|
+
include_run_any=True, # Include the "run any" tool
|
|
195
|
+
include_popular=True, # Include pre-built popular tools
|
|
196
|
+
)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Development
|
|
202
|
+
|
|
203
|
+
### Setup
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Clone the repository
|
|
207
|
+
git clone https://github.com/apiverve/langchain-apiverve.git
|
|
208
|
+
cd langchain-apiverve
|
|
209
|
+
|
|
210
|
+
# Install with Poetry
|
|
211
|
+
poetry install
|
|
212
|
+
|
|
213
|
+
# Or with pip
|
|
214
|
+
pip install -e ".[dev]"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Running Tests
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
pytest
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Linting
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
ruff check .
|
|
227
|
+
mypy src/
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Resources
|
|
233
|
+
|
|
234
|
+
| Resource | Link |
|
|
235
|
+
|----------|------|
|
|
236
|
+
| APIVerve Website | [apiverve.com](https://apiverve.com) |
|
|
237
|
+
| API Documentation | [docs.apiverve.com](https://docs.apiverve.com) |
|
|
238
|
+
| API Marketplace | [apiverve.com/marketplace](https://apiverve.com/marketplace) |
|
|
239
|
+
| LangChain Docs | [python.langchain.com](https://python.langchain.com) |
|
|
240
|
+
| GitHub Issues | [github.com/apiverve/langchain-apiverve/issues](https://github.com/apiverve/langchain-apiverve/issues) |
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## License
|
|
245
|
+
|
|
246
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
247
|
+
|
|
248
|
+
Copyright (c) 2025 [APIVerve](https://apiverve.com)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["poetry-core>=1.0.0"]
|
|
3
|
+
build-backend = "poetry.core.masonry.api"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "langchain-apiverve"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "LangChain integration for APIVerve - Access 310+ utility APIs for AI agents"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{name = "APIVerve", email = "hello@apiverve.com"}
|
|
12
|
+
]
|
|
13
|
+
license = {text = "MIT"}
|
|
14
|
+
requires-python = ">=3.9"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.9",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
|
+
]
|
|
28
|
+
keywords = [
|
|
29
|
+
"langchain",
|
|
30
|
+
"langchain-integration",
|
|
31
|
+
"apiverve",
|
|
32
|
+
"api",
|
|
33
|
+
"ai",
|
|
34
|
+
"llm",
|
|
35
|
+
"agents",
|
|
36
|
+
"tools",
|
|
37
|
+
"validation",
|
|
38
|
+
"utilities"
|
|
39
|
+
]
|
|
40
|
+
dependencies = [
|
|
41
|
+
"langchain-core>=0.2.0",
|
|
42
|
+
"requests>=2.28.0",
|
|
43
|
+
"pydantic>=2.0.0",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[project.optional-dependencies]
|
|
47
|
+
dev = [
|
|
48
|
+
"pytest>=7.0.0",
|
|
49
|
+
"pytest-asyncio>=0.21.0",
|
|
50
|
+
"ruff>=0.1.0",
|
|
51
|
+
"mypy>=1.0.0",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
[project.urls]
|
|
55
|
+
Homepage = "https://apiverve.com"
|
|
56
|
+
Documentation = "https://docs.apiverve.com"
|
|
57
|
+
Repository = "https://github.com/apiverve/langchain-apiverve"
|
|
58
|
+
Changelog = "https://github.com/apiverve/langchain-apiverve/releases"
|
|
59
|
+
Issues = "https://github.com/apiverve/langchain-apiverve/issues"
|
|
60
|
+
|
|
61
|
+
[tool.poetry]
|
|
62
|
+
name = "langchain-apiverve"
|
|
63
|
+
version = "0.1.0"
|
|
64
|
+
description = "LangChain integration for APIVerve - Access 310+ utility APIs for AI agents"
|
|
65
|
+
authors = ["APIVerve <hello@apiverve.com>"]
|
|
66
|
+
license = "MIT"
|
|
67
|
+
readme = "README.md"
|
|
68
|
+
packages = [{include = "langchain_apiverve", from = "src"}]
|
|
69
|
+
|
|
70
|
+
[tool.poetry.dependencies]
|
|
71
|
+
python = ">=3.9,<4.0"
|
|
72
|
+
langchain-core = ">=0.2.0"
|
|
73
|
+
requests = ">=2.28.0"
|
|
74
|
+
pydantic = ">=2.0.0"
|
|
75
|
+
|
|
76
|
+
[tool.poetry.group.dev.dependencies]
|
|
77
|
+
pytest = ">=7.0.0"
|
|
78
|
+
pytest-asyncio = ">=0.21.0"
|
|
79
|
+
ruff = ">=0.1.0"
|
|
80
|
+
mypy = ">=1.0.0"
|
|
81
|
+
|
|
82
|
+
[tool.ruff]
|
|
83
|
+
line-length = 120
|
|
84
|
+
target-version = "py39"
|
|
85
|
+
|
|
86
|
+
[tool.ruff.lint]
|
|
87
|
+
select = ["E", "F", "I", "W"]
|
|
88
|
+
ignore = ["E501"]
|
|
89
|
+
|
|
90
|
+
[tool.mypy]
|
|
91
|
+
python_version = "3.9"
|
|
92
|
+
warn_return_any = true
|
|
93
|
+
warn_unused_configs = true
|
|
94
|
+
ignore_missing_imports = true
|
|
95
|
+
|
|
96
|
+
[tool.pytest.ini_options]
|
|
97
|
+
asyncio_mode = "auto"
|
|
98
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LangChain integration for APIVerve.
|
|
3
|
+
|
|
4
|
+
Dynamically loads 300+ utility APIs including validation, conversion,
|
|
5
|
+
generation, analysis, and lookup tools for AI agents.
|
|
6
|
+
|
|
7
|
+
Schemas are fetched from APIVerve at initialization and cached in memory
|
|
8
|
+
for the lifetime of the process.
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
>>> from langchain_apiverve import APIVerveToolkit
|
|
12
|
+
>>> toolkit = APIVerveToolkit(api_key="your-api-key")
|
|
13
|
+
>>> tools = toolkit.get_tools() # All 300+ tools with proper schemas!
|
|
14
|
+
>>> # Use tools with any LangChain agent
|
|
15
|
+
|
|
16
|
+
For more information, see: https://docs.apiverve.com
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from langchain_apiverve.toolkit import APIVerveToolkit, DynamicAPIVerveTool, load_api_schemas
|
|
20
|
+
from langchain_apiverve.client import APIVerveClient, APIVerveError
|
|
21
|
+
|
|
22
|
+
__version__ = "0.1.0"
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"APIVerveToolkit",
|
|
26
|
+
"DynamicAPIVerveTool",
|
|
27
|
+
"APIVerveClient",
|
|
28
|
+
"APIVerveError",
|
|
29
|
+
"load_api_schemas",
|
|
30
|
+
"__version__",
|
|
31
|
+
]
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""
|
|
2
|
+
APIVerve API Client.
|
|
3
|
+
|
|
4
|
+
Low-level client for making API requests to APIVerve.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
from typing import Any, Dict, Optional
|
|
9
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
10
|
+
|
|
11
|
+
import requests
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class APIVerveError(Exception):
|
|
15
|
+
"""Base exception for APIVerve errors."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, message: str, status_code: Optional[int] = None, response: Optional[dict] = None):
|
|
18
|
+
super().__init__(message)
|
|
19
|
+
self.status_code = status_code
|
|
20
|
+
self.response = response
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class APIVerveClient:
|
|
24
|
+
"""
|
|
25
|
+
Client for making requests to APIVerve APIs.
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
>>> client = APIVerveClient(api_key="your-api-key")
|
|
29
|
+
>>> result = client.call_api("emailvalidator", {"email": "test@example.com"})
|
|
30
|
+
>>> print(result)
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
api_key: str,
|
|
36
|
+
base_url: str = "https://api.apiverve.com/v1",
|
|
37
|
+
timeout: int = 30,
|
|
38
|
+
):
|
|
39
|
+
"""
|
|
40
|
+
Initialize the APIVerve client.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
api_key: Your APIVerve API key
|
|
44
|
+
base_url: Base URL for API requests
|
|
45
|
+
timeout: Request timeout in seconds
|
|
46
|
+
"""
|
|
47
|
+
self.api_key = api_key
|
|
48
|
+
self.base_url = base_url.rstrip('/')
|
|
49
|
+
self.timeout = timeout
|
|
50
|
+
self._session: Optional[requests.Session] = None
|
|
51
|
+
self._executor = ThreadPoolExecutor(max_workers=4)
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def session(self) -> requests.Session:
|
|
55
|
+
"""Get or create the requests session."""
|
|
56
|
+
if self._session is None:
|
|
57
|
+
self._session = requests.Session()
|
|
58
|
+
self._session.headers.update({
|
|
59
|
+
"x-api-key": self.api_key,
|
|
60
|
+
"Accept": "application/json",
|
|
61
|
+
"User-Agent": "langchain-apiverve/0.1.0",
|
|
62
|
+
})
|
|
63
|
+
return self._session
|
|
64
|
+
|
|
65
|
+
def call_api(
|
|
66
|
+
self,
|
|
67
|
+
api_id: str,
|
|
68
|
+
parameters: Optional[Dict[str, Any]] = None,
|
|
69
|
+
method: str = "GET",
|
|
70
|
+
) -> Dict[str, Any]:
|
|
71
|
+
"""
|
|
72
|
+
Call an APIVerve API synchronously.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
api_id: The API identifier (e.g., "emailvalidator", "dnslookup")
|
|
76
|
+
parameters: Parameters to pass to the API
|
|
77
|
+
method: HTTP method (GET or POST)
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
API response as a dictionary
|
|
81
|
+
|
|
82
|
+
Raises:
|
|
83
|
+
APIVerveError: If the API call fails
|
|
84
|
+
"""
|
|
85
|
+
url = f"{self.base_url}/{api_id}"
|
|
86
|
+
params = parameters or {}
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
if method.upper() == "POST":
|
|
90
|
+
response = self.session.post(url, json=params, timeout=self.timeout)
|
|
91
|
+
else:
|
|
92
|
+
response = self.session.get(url, params=params, timeout=self.timeout)
|
|
93
|
+
|
|
94
|
+
response.raise_for_status()
|
|
95
|
+
return response.json()
|
|
96
|
+
except requests.exceptions.HTTPError as e:
|
|
97
|
+
error_msg = f"API request failed: {e}"
|
|
98
|
+
try:
|
|
99
|
+
error_response = response.json()
|
|
100
|
+
if "error" in error_response:
|
|
101
|
+
error_msg = error_response["error"]
|
|
102
|
+
except Exception:
|
|
103
|
+
pass
|
|
104
|
+
raise APIVerveError(error_msg, status_code=response.status_code)
|
|
105
|
+
except requests.exceptions.RequestException as e:
|
|
106
|
+
raise APIVerveError(f"Request failed: {e}")
|
|
107
|
+
|
|
108
|
+
async def acall_api(
|
|
109
|
+
self,
|
|
110
|
+
api_id: str,
|
|
111
|
+
parameters: Optional[Dict[str, Any]] = None,
|
|
112
|
+
method: str = "GET",
|
|
113
|
+
) -> Dict[str, Any]:
|
|
114
|
+
"""
|
|
115
|
+
Call an APIVerve API asynchronously.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
api_id: The API identifier (e.g., "emailvalidator", "dnslookup")
|
|
119
|
+
parameters: Parameters to pass to the API
|
|
120
|
+
method: HTTP method (GET or POST)
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
API response as a dictionary
|
|
124
|
+
|
|
125
|
+
Raises:
|
|
126
|
+
APIVerveError: If the API call fails
|
|
127
|
+
"""
|
|
128
|
+
loop = asyncio.get_event_loop()
|
|
129
|
+
return await loop.run_in_executor(
|
|
130
|
+
self._executor,
|
|
131
|
+
lambda: self.call_api(api_id, parameters, method)
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
def close(self):
|
|
135
|
+
"""Close the client and release resources."""
|
|
136
|
+
if self._session:
|
|
137
|
+
self._session.close()
|
|
138
|
+
self._session = None
|
|
139
|
+
self._executor.shutdown(wait=False)
|
|
140
|
+
|
|
141
|
+
def __enter__(self):
|
|
142
|
+
return self
|
|
143
|
+
|
|
144
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
145
|
+
self.close()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pydantic schemas for APIVerve API inputs and outputs.
|
|
3
|
+
|
|
4
|
+
These schemas provide type safety and validation for API parameters.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, Optional, List
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class APIResponse(BaseModel):
|
|
12
|
+
"""Standard APIVerve API response format."""
|
|
13
|
+
|
|
14
|
+
status: str = Field(description="Response status: 'ok' or 'error'")
|
|
15
|
+
error: Optional[str] = Field(default=None, description="Error message if status is 'error'")
|
|
16
|
+
data: Optional[Dict[str, Any]] = Field(default=None, description="Response data")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class EmailValidationResult(BaseModel):
|
|
20
|
+
"""Result of email validation."""
|
|
21
|
+
|
|
22
|
+
valid: bool = Field(description="Whether the email is valid")
|
|
23
|
+
email: str = Field(description="The email address that was validated")
|
|
24
|
+
domain: Optional[str] = Field(default=None, description="The email domain")
|
|
25
|
+
disposable: Optional[bool] = Field(default=None, description="Whether the email is from a disposable provider")
|
|
26
|
+
mx_found: Optional[bool] = Field(default=None, description="Whether MX records were found")
|
|
27
|
+
syntax_valid: Optional[bool] = Field(default=None, description="Whether the email syntax is valid")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class DNSRecord(BaseModel):
|
|
31
|
+
"""A DNS record."""
|
|
32
|
+
|
|
33
|
+
type: str = Field(description="Record type (A, AAAA, MX, TXT, etc.)")
|
|
34
|
+
value: str = Field(description="Record value")
|
|
35
|
+
ttl: Optional[int] = Field(default=None, description="Time to live in seconds")
|
|
36
|
+
priority: Optional[int] = Field(default=None, description="Priority (for MX records)")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class IPGeolocationResult(BaseModel):
|
|
40
|
+
"""Result of IP geolocation lookup."""
|
|
41
|
+
|
|
42
|
+
ip: str = Field(description="The IP address")
|
|
43
|
+
country: Optional[str] = Field(default=None, description="Country name")
|
|
44
|
+
country_code: Optional[str] = Field(default=None, description="ISO country code")
|
|
45
|
+
region: Optional[str] = Field(default=None, description="Region/state name")
|
|
46
|
+
city: Optional[str] = Field(default=None, description="City name")
|
|
47
|
+
latitude: Optional[float] = Field(default=None, description="Latitude coordinate")
|
|
48
|
+
longitude: Optional[float] = Field(default=None, description="Longitude coordinate")
|
|
49
|
+
timezone: Optional[str] = Field(default=None, description="Timezone")
|
|
50
|
+
isp: Optional[str] = Field(default=None, description="Internet Service Provider")
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"""
|
|
2
|
+
APIVerve Toolkit for LangChain.
|
|
3
|
+
|
|
4
|
+
Provides a convenient way to get all APIVerve tools for use with LangChain agents.
|
|
5
|
+
Schemas are fetched from APIVerve at initialization time.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
from typing import Any, Dict, List, Optional, Type
|
|
10
|
+
|
|
11
|
+
import requests
|
|
12
|
+
from pydantic import BaseModel, Field, create_model
|
|
13
|
+
from langchain_core.tools import BaseTool
|
|
14
|
+
from langchain_core.callbacks import CallbackManagerForToolRun
|
|
15
|
+
|
|
16
|
+
from langchain_apiverve.client import APIVerveClient
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Schema source URL - always fetched fresh at init
|
|
20
|
+
SCHEMA_URL = "https://api.apiverve.com/publicapis/mcp-schemas.json"
|
|
21
|
+
|
|
22
|
+
# Module-level cache for schemas (persists for the lifetime of the process)
|
|
23
|
+
_schemas_cache: Optional[Dict] = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def load_api_schemas(force_refresh: bool = False) -> Dict:
|
|
27
|
+
"""
|
|
28
|
+
Load API schemas from APIVerve.
|
|
29
|
+
|
|
30
|
+
Schemas are cached in memory after the first fetch. Subsequent calls
|
|
31
|
+
return the cached schemas unless force_refresh=True.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
force_refresh: Force re-fetch even if schemas are already cached.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Dict with 'schemas' and 'totalAPIs' keys.
|
|
38
|
+
|
|
39
|
+
Raises:
|
|
40
|
+
RuntimeError: If schemas cannot be fetched from APIVerve.
|
|
41
|
+
"""
|
|
42
|
+
global _schemas_cache
|
|
43
|
+
|
|
44
|
+
# Return cached if available and not forcing refresh
|
|
45
|
+
if _schemas_cache is not None and not force_refresh:
|
|
46
|
+
return _schemas_cache
|
|
47
|
+
|
|
48
|
+
# Fetch schemas from APIVerve (required - no fallback)
|
|
49
|
+
try:
|
|
50
|
+
response = requests.get(SCHEMA_URL, timeout=30)
|
|
51
|
+
response.raise_for_status()
|
|
52
|
+
data = response.json()
|
|
53
|
+
|
|
54
|
+
if not data.get("schemas"):
|
|
55
|
+
raise ValueError("Response missing 'schemas' field")
|
|
56
|
+
|
|
57
|
+
_schemas_cache = data
|
|
58
|
+
return _schemas_cache
|
|
59
|
+
|
|
60
|
+
except requests.exceptions.RequestException as e:
|
|
61
|
+
raise RuntimeError(
|
|
62
|
+
f"Failed to fetch API schemas from {SCHEMA_URL}: {e}. "
|
|
63
|
+
"APIVerve schema endpoint must be accessible to use this toolkit."
|
|
64
|
+
) from e
|
|
65
|
+
except (ValueError, KeyError) as e:
|
|
66
|
+
raise RuntimeError(
|
|
67
|
+
f"Invalid schema response from {SCHEMA_URL}: {e}"
|
|
68
|
+
) from e
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _python_type_from_schema(param_type: str) -> Type:
|
|
72
|
+
"""Convert JSON schema type to Python type."""
|
|
73
|
+
type_map = {
|
|
74
|
+
"string": str,
|
|
75
|
+
"integer": int,
|
|
76
|
+
"number": float,
|
|
77
|
+
"boolean": bool,
|
|
78
|
+
"array": list,
|
|
79
|
+
"object": dict,
|
|
80
|
+
}
|
|
81
|
+
return type_map.get(param_type, str)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _create_pydantic_model(api_schema: Dict) -> Type[BaseModel]:
|
|
85
|
+
"""Dynamically create a Pydantic model from API schema."""
|
|
86
|
+
api_id = api_schema.get("apiId", "unknown")
|
|
87
|
+
parameters = api_schema.get("parameters", [])
|
|
88
|
+
|
|
89
|
+
if not parameters:
|
|
90
|
+
# No parameters - create empty model
|
|
91
|
+
return create_model(f"{api_id}Input")
|
|
92
|
+
|
|
93
|
+
# Build field definitions
|
|
94
|
+
fields = {}
|
|
95
|
+
for param in parameters:
|
|
96
|
+
name = param.get("name", "")
|
|
97
|
+
param_type = _python_type_from_schema(param.get("type", "string"))
|
|
98
|
+
required = param.get("required", False)
|
|
99
|
+
description = param.get("description", "")
|
|
100
|
+
example = param.get("example")
|
|
101
|
+
|
|
102
|
+
# Add example to description if available
|
|
103
|
+
if example:
|
|
104
|
+
description = f"{description} (e.g., {example})"
|
|
105
|
+
|
|
106
|
+
if required:
|
|
107
|
+
fields[name] = (param_type, Field(description=description))
|
|
108
|
+
else:
|
|
109
|
+
fields[name] = (Optional[param_type], Field(default=None, description=description))
|
|
110
|
+
|
|
111
|
+
return create_model(f"{api_id}Input", **fields)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class DynamicAPIVerveTool(BaseTool):
|
|
115
|
+
"""A dynamically-created tool for a specific APIVerve API."""
|
|
116
|
+
|
|
117
|
+
name: str = Field(description="The tool name")
|
|
118
|
+
description: str = Field(description="What the tool does")
|
|
119
|
+
api_id: str = Field(description="The APIVerve API identifier")
|
|
120
|
+
method: str = Field(default="GET", description="HTTP method")
|
|
121
|
+
client: APIVerveClient = Field(description="The API client")
|
|
122
|
+
args_schema: Type[BaseModel] = Field(description="The input schema")
|
|
123
|
+
|
|
124
|
+
class Config:
|
|
125
|
+
arbitrary_types_allowed = True
|
|
126
|
+
|
|
127
|
+
def _run(
|
|
128
|
+
self,
|
|
129
|
+
run_manager: Optional[CallbackManagerForToolRun] = None,
|
|
130
|
+
**kwargs,
|
|
131
|
+
) -> Dict[str, Any]:
|
|
132
|
+
"""Execute the API call."""
|
|
133
|
+
# Filter out None values
|
|
134
|
+
params = {k: v for k, v in kwargs.items() if v is not None}
|
|
135
|
+
return self.client.call_api(self.api_id, params, method=self.method)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class APIVerveToolkit:
|
|
139
|
+
"""
|
|
140
|
+
Toolkit for accessing APIVerve APIs through LangChain.
|
|
141
|
+
|
|
142
|
+
Dynamically loads API schemas and creates properly-typed tools.
|
|
143
|
+
Schemas are fetched from APIVerve at initialization and cached in memory.
|
|
144
|
+
|
|
145
|
+
Example:
|
|
146
|
+
>>> from langchain_apiverve import APIVerveToolkit
|
|
147
|
+
>>>
|
|
148
|
+
>>> # Initialize with API key
|
|
149
|
+
>>> toolkit = APIVerveToolkit(api_key="your-api-key")
|
|
150
|
+
>>>
|
|
151
|
+
>>> # Or use environment variable APIVERVE_API_KEY
|
|
152
|
+
>>> toolkit = APIVerveToolkit()
|
|
153
|
+
>>>
|
|
154
|
+
>>> # Get all tools (with full parameter schemas!)
|
|
155
|
+
>>> tools = toolkit.get_tools()
|
|
156
|
+
>>>
|
|
157
|
+
>>> # Get tools for specific categories
|
|
158
|
+
>>> validation_tools = toolkit.get_tools(categories=["Validation"])
|
|
159
|
+
>>>
|
|
160
|
+
>>> # Get only specific APIs
|
|
161
|
+
>>> selected_tools = toolkit.get_tools(
|
|
162
|
+
... include_apis=["emailvalidator", "dnslookup", "iplookup"]
|
|
163
|
+
... )
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
api_key: APIVerve API key. If not provided, uses APIVERVE_API_KEY env var.
|
|
167
|
+
base_url: Base URL for API calls. Defaults to https://api.apiverve.com/v1
|
|
168
|
+
refresh_schemas: Force re-fetch schemas even if already cached. Default False.
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
def __init__(
|
|
172
|
+
self,
|
|
173
|
+
api_key: Optional[str] = None,
|
|
174
|
+
base_url: str = "https://api.apiverve.com/v1",
|
|
175
|
+
refresh_schemas: bool = False,
|
|
176
|
+
):
|
|
177
|
+
self.api_key = api_key or os.environ.get("APIVERVE_API_KEY")
|
|
178
|
+
if not self.api_key:
|
|
179
|
+
raise ValueError(
|
|
180
|
+
"API key is required. Provide api_key parameter or set APIVERVE_API_KEY environment variable. "
|
|
181
|
+
"Get your API key at https://dashboard.apiverve.com"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
self.client = APIVerveClient(api_key=self.api_key, base_url=base_url)
|
|
185
|
+
|
|
186
|
+
# Load API schemas (cached)
|
|
187
|
+
schema_data = load_api_schemas(force_refresh=refresh_schemas)
|
|
188
|
+
self._schemas = schema_data.get("schemas", {})
|
|
189
|
+
self._total_apis = schema_data.get("totalAPIs", len(self._schemas))
|
|
190
|
+
|
|
191
|
+
def get_tools(
|
|
192
|
+
self,
|
|
193
|
+
categories: Optional[List[str]] = None,
|
|
194
|
+
include_apis: Optional[List[str]] = None,
|
|
195
|
+
exclude_apis: Optional[List[str]] = None,
|
|
196
|
+
max_tools: Optional[int] = None,
|
|
197
|
+
) -> List[BaseTool]:
|
|
198
|
+
"""
|
|
199
|
+
Get LangChain tools for APIVerve APIs.
|
|
200
|
+
|
|
201
|
+
Each tool has a properly-typed schema based on the API's parameters,
|
|
202
|
+
so the LLM knows exactly what arguments to pass.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
categories: Only include APIs from these categories.
|
|
206
|
+
include_apis: Only include these specific API IDs.
|
|
207
|
+
exclude_apis: Exclude these specific API IDs.
|
|
208
|
+
max_tools: Maximum number of tools to return (for token limits).
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
List of LangChain BaseTool instances with proper schemas.
|
|
212
|
+
"""
|
|
213
|
+
tools: List[BaseTool] = []
|
|
214
|
+
exclude_set = set(exclude_apis or [])
|
|
215
|
+
|
|
216
|
+
for api_id, schema in self._schemas.items():
|
|
217
|
+
# Skip if excluded
|
|
218
|
+
if api_id in exclude_set:
|
|
219
|
+
continue
|
|
220
|
+
|
|
221
|
+
# Filter by category
|
|
222
|
+
if categories and schema.get("category") not in categories:
|
|
223
|
+
continue
|
|
224
|
+
|
|
225
|
+
# Filter by include list
|
|
226
|
+
if include_apis and api_id not in include_apis:
|
|
227
|
+
continue
|
|
228
|
+
|
|
229
|
+
# Create tool with dynamic schema
|
|
230
|
+
try:
|
|
231
|
+
tool = self._create_tool(schema)
|
|
232
|
+
tools.append(tool)
|
|
233
|
+
except Exception:
|
|
234
|
+
# Skip APIs that fail to create (malformed schema, etc.)
|
|
235
|
+
continue
|
|
236
|
+
|
|
237
|
+
# Respect max_tools limit
|
|
238
|
+
if max_tools and len(tools) >= max_tools:
|
|
239
|
+
break
|
|
240
|
+
|
|
241
|
+
return tools
|
|
242
|
+
|
|
243
|
+
def _create_tool(self, schema: Dict) -> DynamicAPIVerveTool:
|
|
244
|
+
"""Create a tool from an API schema."""
|
|
245
|
+
api_id = schema.get("apiId", "")
|
|
246
|
+
title = schema.get("title", api_id)
|
|
247
|
+
description = schema.get("description", f"Execute the {title} API")
|
|
248
|
+
methods = schema.get("methods", ["GET"])
|
|
249
|
+
method = methods[0] if methods else "GET"
|
|
250
|
+
|
|
251
|
+
# Create Pydantic model from parameters
|
|
252
|
+
args_schema = _create_pydantic_model(schema)
|
|
253
|
+
|
|
254
|
+
return DynamicAPIVerveTool(
|
|
255
|
+
name=api_id,
|
|
256
|
+
description=description,
|
|
257
|
+
api_id=api_id,
|
|
258
|
+
method=method,
|
|
259
|
+
client=self.client,
|
|
260
|
+
args_schema=args_schema,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
def get_tool(self, api_id: str) -> Optional[DynamicAPIVerveTool]:
|
|
264
|
+
"""
|
|
265
|
+
Get a single tool by API ID.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
api_id: The API identifier (e.g., "emailvalidator")
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
The tool, or None if not found.
|
|
272
|
+
"""
|
|
273
|
+
schema = self._schemas.get(api_id)
|
|
274
|
+
if not schema:
|
|
275
|
+
return None
|
|
276
|
+
return self._create_tool(schema)
|
|
277
|
+
|
|
278
|
+
def list_available_apis(self) -> List[Dict]:
|
|
279
|
+
"""
|
|
280
|
+
List all available APIs.
|
|
281
|
+
|
|
282
|
+
Returns:
|
|
283
|
+
List of dicts with id, title, description, and category.
|
|
284
|
+
"""
|
|
285
|
+
return [
|
|
286
|
+
{
|
|
287
|
+
"id": schema.get("apiId"),
|
|
288
|
+
"title": schema.get("title"),
|
|
289
|
+
"description": schema.get("description"),
|
|
290
|
+
"category": schema.get("category"),
|
|
291
|
+
}
|
|
292
|
+
for schema in self._schemas.values()
|
|
293
|
+
]
|
|
294
|
+
|
|
295
|
+
def list_categories(self) -> List[str]:
|
|
296
|
+
"""List all available API categories."""
|
|
297
|
+
return sorted(set(
|
|
298
|
+
schema.get("category", "Other")
|
|
299
|
+
for schema in self._schemas.values()
|
|
300
|
+
))
|
|
301
|
+
|
|
302
|
+
@property
|
|
303
|
+
def total_apis(self) -> int:
|
|
304
|
+
"""Total number of available APIs."""
|
|
305
|
+
return self._total_apis
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""
|
|
2
|
+
APIVerve LangChain Tools - Base classes and utilities.
|
|
3
|
+
|
|
4
|
+
Tools are dynamically generated from API schemas in the toolkit module.
|
|
5
|
+
This module provides the base tool class used by the toolkit.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# Tools are dynamically created in toolkit.py using DynamicAPIVerveTool
|
|
9
|
+
# See toolkit.py for the implementation
|
|
10
|
+
|
|
11
|
+
from langchain_apiverve.toolkit import DynamicAPIVerveTool
|
|
12
|
+
|
|
13
|
+
__all__ = ["DynamicAPIVerveTool"]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility functions for langchain-apiverve.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from typing import List
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def to_snake_case(name: str) -> str:
|
|
10
|
+
"""Convert a string to snake_case."""
|
|
11
|
+
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
|
|
12
|
+
name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name)
|
|
13
|
+
return name.lower().replace('-', '_').replace(' ', '_')
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def to_pascal_case(name: str) -> str:
|
|
17
|
+
"""Convert a string to PascalCase."""
|
|
18
|
+
words = re.split(r'[-_\s]+', name)
|
|
19
|
+
return ''.join(word.capitalize() for word in words)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def truncate_text(text: str, max_length: int = 200, suffix: str = "...") -> str:
|
|
23
|
+
"""Truncate text to a maximum length."""
|
|
24
|
+
if len(text) <= max_length:
|
|
25
|
+
return text
|
|
26
|
+
return text[:max_length - len(suffix)] + suffix
|