langchain-openapi-tools 1.0.2__tar.gz → 2.0.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.
Files changed (161) hide show
  1. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/ARCHITECTURE.md +57 -13
  2. langchain_openapi_tools-2.0.0/CHANGELOG.md +58 -0
  3. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/Makefile +1 -1
  4. langchain_openapi_tools-2.0.0/PKG-INFO +311 -0
  5. langchain_openapi_tools-2.0.0/README.md +271 -0
  6. langchain_openapi_tools-2.0.0/docs/api/executor.md +5 -0
  7. langchain_openapi_tools-2.0.0/docs/api/loader.md +3 -0
  8. langchain_openapi_tools-2.0.0/docs/api/middleware.md +8 -0
  9. langchain_openapi_tools-2.0.0/docs/api/parser.md +4 -0
  10. langchain_openapi_tools-2.0.0/docs/api/toolkit.md +4 -0
  11. langchain_openapi_tools-2.0.0/docs/architecture.md +72 -0
  12. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/docs/authentication.md +5 -5
  13. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/docs/examples/crossref.md +1 -1
  14. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/docs/examples/petstore.md +1 -1
  15. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/docs/index.md +1 -1
  16. langchain_openapi_tools-2.0.0/docs/installation.md +65 -0
  17. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/docs/middleware.md +9 -5
  18. langchain_openapi_tools-2.0.0/docs/prompt_optimization.md +140 -0
  19. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/docs/quickstart.md +2 -2
  20. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/docs/toolkit.md +13 -1
  21. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/examples/crossref/main.py +1 -1
  22. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/examples/petstore/main.py +1 -1
  23. langchain_openapi_tools-2.0.0/langchain_openapi/__init__.py +19 -0
  24. langchain_openapi_tools-2.0.0/langchain_openapi/py.typed +1 -0
  25. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/__init__.py +29 -13
  26. langchain_openapi_tools-2.0.0/langchain_openapi_tools/adapters.py +126 -0
  27. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/executor.py +159 -16
  28. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/loader.py +15 -10
  29. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/middleware.py +1 -1
  30. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/models.py +27 -6
  31. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/parser.py +133 -19
  32. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/providers.py +1 -1
  33. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/schema_converter.py +107 -5
  34. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/swagger.py +46 -14
  35. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/toolkit.py +205 -24
  36. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/utils.py +1 -1
  37. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/mkdocs.yml +1 -0
  38. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/pyproject.toml +8 -3
  39. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/404.html +35 -8
  40. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/api/executor/index.html +270 -235
  41. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/api/loader/index.html +69 -42
  42. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/api/middleware/index.html +70 -43
  43. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/api/parser/index.html +54 -27
  44. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/api/toolkit/index.html +583 -464
  45. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/architecture/index.html +36 -9
  46. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/authentication/index.html +40 -13
  47. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/contributing/index.html +35 -8
  48. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/examples/crossref/index.html +36 -9
  49. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/examples/petstore/index.html +36 -9
  50. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/index.html +36 -9
  51. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/installation/index.html +150 -16
  52. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/middleware/index.html +55 -24
  53. langchain_openapi_tools-2.0.0/site/objects.inv +0 -0
  54. langchain_openapi_tools-2.0.0/site/prompt_optimization/index.html +1364 -0
  55. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/quickstart/index.html +38 -11
  56. langchain_openapi_tools-2.0.0/site/search/search_index.json +1 -0
  57. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/sitemap.xml +4 -0
  58. langchain_openapi_tools-2.0.0/site/sitemap.xml.gz +0 -0
  59. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/toolkit/index.html +36 -9
  60. langchain_openapi_tools-2.0.0/tests/test_adapters.py +96 -0
  61. langchain_openapi_tools-2.0.0/tests/test_base_url_resolution.py +324 -0
  62. langchain_openapi_tools-2.0.0/tests/test_compat_matrix.py +486 -0
  63. langchain_openapi_tools-2.0.0/tests/test_compatibility.py +35 -0
  64. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/tests/test_e2e.py +1 -1
  65. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/tests/test_executor.py +1 -1
  66. langchain_openapi_tools-2.0.0/tests/test_import.py +6 -0
  67. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/tests/test_loader.py +5 -2
  68. langchain_openapi_tools-2.0.0/tests/test_media_types.py +204 -0
  69. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/tests/test_middleware.py +1 -1
  70. langchain_openapi_tools-2.0.0/tests/test_openapi_31.py +190 -0
  71. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/tests/test_parser.py +1 -1
  72. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/tests/test_providers.py +2 -2
  73. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/tests/test_resolver.py +1 -1
  74. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/tests/test_schema_converter.py +1 -1
  75. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/tests/test_swagger.py +33 -1
  76. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/tests/test_toolkit.py +137 -1
  77. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/uv.lock +167 -1
  78. langchain_openapi_tools-1.0.2/CHANGELOG.md +0 -22
  79. langchain_openapi_tools-1.0.2/PKG-INFO +0 -306
  80. langchain_openapi_tools-1.0.2/README.md +0 -266
  81. langchain_openapi_tools-1.0.2/docs/api/executor.md +0 -5
  82. langchain_openapi_tools-1.0.2/docs/api/loader.md +0 -3
  83. langchain_openapi_tools-1.0.2/docs/api/middleware.md +0 -8
  84. langchain_openapi_tools-1.0.2/docs/api/parser.md +0 -4
  85. langchain_openapi_tools-1.0.2/docs/api/toolkit.md +0 -4
  86. langchain_openapi_tools-1.0.2/docs/architecture.md +0 -60
  87. langchain_openapi_tools-1.0.2/docs/installation.md +0 -40
  88. langchain_openapi_tools-1.0.2/site/objects.inv +0 -0
  89. langchain_openapi_tools-1.0.2/site/search/search_index.json +0 -1
  90. langchain_openapi_tools-1.0.2/site/sitemap.xml.gz +0 -0
  91. langchain_openapi_tools-1.0.2/tests/test_import.py +0 -6
  92. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  93. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  94. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  95. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  96. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.github/dependabot.yml +0 -0
  97. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.github/workflows/ci.yml +0 -0
  98. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.github/workflows/pages.yml +0 -0
  99. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.github/workflows/publish.yml +0 -0
  100. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.github/workflows/release.yml +0 -0
  101. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.gitignore +0 -0
  102. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/.pre-commit-config.yaml +0 -0
  103. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/CODE_OF_CONDUCT.md +0 -0
  104. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/CONTRIBUTING.md +0 -0
  105. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/LICENSE +0 -0
  106. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/benchmarks/benchmark.py +0 -0
  107. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/docs/contributing.md +0 -0
  108. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/examples/README.md +0 -0
  109. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/examples/crossref/README.md +0 -0
  110. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/examples/crossref/crossref.json +0 -0
  111. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/examples/crossref/requirements.txt +0 -0
  112. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/examples/petstore/README.md +0 -0
  113. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/examples/petstore/petstore.json +0 -0
  114. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/examples/petstore/requirements.txt +0 -0
  115. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/enums.py +0 -0
  116. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/exceptions.py +0 -0
  117. {langchain_openapi_tools-1.0.2/langchain_openapi → langchain_openapi_tools-2.0.0/langchain_openapi_tools}/py.typed +0 -0
  118. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/_mkdocstrings.css +0 -0
  119. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/images/favicon.png +0 -0
  120. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/bundle.d7400e89.min.js +0 -0
  121. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/bundle.d7400e89.min.js.map +0 -0
  122. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.ar.min.js +0 -0
  123. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.da.min.js +0 -0
  124. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.de.min.js +0 -0
  125. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.du.min.js +0 -0
  126. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.el.min.js +0 -0
  127. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.es.min.js +0 -0
  128. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.fi.min.js +0 -0
  129. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.fr.min.js +0 -0
  130. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.he.min.js +0 -0
  131. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.hi.min.js +0 -0
  132. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.hu.min.js +0 -0
  133. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.hy.min.js +0 -0
  134. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.it.min.js +0 -0
  135. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.ja.min.js +0 -0
  136. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.jp.min.js +0 -0
  137. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.kn.min.js +0 -0
  138. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.ko.min.js +0 -0
  139. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.multi.min.js +0 -0
  140. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.nl.min.js +0 -0
  141. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.no.min.js +0 -0
  142. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.pt.min.js +0 -0
  143. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.ro.min.js +0 -0
  144. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.ru.min.js +0 -0
  145. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.sa.min.js +0 -0
  146. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +0 -0
  147. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.sv.min.js +0 -0
  148. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.ta.min.js +0 -0
  149. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.te.min.js +0 -0
  150. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.th.min.js +0 -0
  151. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.tr.min.js +0 -0
  152. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.vi.min.js +0 -0
  153. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/min/lunr.zh.min.js +0 -0
  154. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/tinyseg.js +0 -0
  155. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/lunr/wordcut.js +0 -0
  156. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/workers/search.2c215733.min.js +0 -0
  157. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/javascripts/workers/search.2c215733.min.js.map +0 -0
  158. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/stylesheets/main.ec1eaa64.min.css +0 -0
  159. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/stylesheets/main.ec1eaa64.min.css.map +0 -0
  160. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/stylesheets/palette.ab4e12ef.min.css +0 -0
  161. {langchain_openapi_tools-1.0.2 → langchain_openapi_tools-2.0.0}/site/assets/stylesheets/palette.ab4e12ef.min.css.map +0 -0
@@ -30,13 +30,24 @@ The library is structured as a linear transform pipeline with isolated responsib
30
30
  │ OpenAPI Loader │
31
31
  │ - Parsing (JSON / YAML) │
32
32
  │ - Ref Resolution ($ref expansion) │
33
+ │ - Remembers spec source URL │
34
+ └───────────────────────────┬────────────────────────────┘
35
+
36
+
37
+ ┌────────────────────────────────────────────────────────┐
38
+ │ Spec Adapter Layer │
39
+ │ - Version detection (swagger2 / 3.0 / 3.1) │
40
+ │ - Swagger2Adapter → OpenAPI 3.0 normalization │
41
+ │ - OpenAPI3Adapter (pass-through, 3.0 & 3.1) │
33
42
  └───────────────────────────┬────────────────────────────┘
34
43
 
35
44
 
36
45
  ┌────────────────────────────────────────────────────────┐
37
46
  │ Internal Models │
38
47
  │ - Parsed Spec & Operation trees │
39
- │ - Schema normalization
48
+ │ - Schema normalization (incl. oneOf/anyOf/
49
+ │ allOf / const / read-write flags) │
50
+ │ - `spec_family` tag preserved from adapter │
40
51
  └───────────────────────────┬────────────────────────────┘
41
52
 
42
53
 
@@ -75,7 +86,31 @@ The library is structured as a linear transform pipeline with isolated responsib
75
86
 
76
87
  The **OpenAPI Loader** is responsible for reading OpenAPI specifications from local file paths, raw strings, or remote HTTP URLs. It handles format auto-detection (JSON vs. YAML), syntax validation, and recursively resolves relative and external `$ref` pointers into a unified, flattened schema representation.
77
88
 
78
- ### 3.2 Internal Models & Specification Parser
89
+ When loading from a URL, the loader preserves the source URL on the resulting `OpenAPISpec` (`spec.source_url`). This lets `OpenAPISpec.from_dict` and `SwaggerNormalizer` resolve relative `servers` entries and missing `host` fields to absolute URLs, so `RequestBuilder` always receives an absolute base URL — even for specs like `https://fakerestapi.azurewebsites.net/swagger/v1/swagger.json` that omit the `servers` block entirely.
90
+
91
+ ### 3.2 Spec Adapter Layer
92
+
93
+ The **Spec Adapter Layer** (`langchain_openapi_tools.adapters`) provides a
94
+ uniform entry point across every supported specification family. It exposes:
95
+
96
+ * `detect_spec_version(spec_dict) -> Literal["swagger2", "openapi30", "openapi31"]`
97
+ * `SpecAdapter` (`typing.Protocol`) — the shared adapter interface.
98
+ * `Swagger2Adapter` — wraps `SwaggerNormalizer` to lift Swagger 2.0 documents
99
+ into an OpenAPI 3.0-compatible dictionary while remembering the source URL
100
+ so `host`/`basePath` gaps can be filled in from the fetch location.
101
+ * `OpenAPI3Adapter` — a pass-through adapter for both OpenAPI 3.0.x and
102
+ 3.1.x documents.
103
+ * `select_adapter(spec_dict)` and `normalize_spec(spec_dict, source_url)` —
104
+ convenience helpers that pick the right adapter and return a `(normalized
105
+ dict, spec_family)` tuple.
106
+
107
+ `OpenAPISpec.from_dict` calls `normalize_spec` before parsing so downstream
108
+ components (`OpenAPIParser`, `SchemaConverter`, `RequestBuilder`) only ever
109
+ see a single canonical shape. `OpenAPISpec.spec_family` records which
110
+ family the document originated from, which is useful for logging and for
111
+ version-aware feature toggles in the future.
112
+
113
+ ### 3.3 Internal Models & Specification Parser
79
114
 
80
115
  The **OpenAPI Parser** (`OpenAPIParser`) transforms an `OpenAPISpec` into strongly typed, normalized Python dataclasses using the `ReferenceResolver` for local `$ref` pointer resolution:
81
116
 
@@ -99,16 +134,19 @@ OpenAPI Spec (File / URL / Dict)
99
134
  * **`RequestBody`**: Defines the payload expected by POST/PUT/PATCH operations (`required`, `description`, `content`).
100
135
  * **`Response`**: Defines an HTTP response status definition (`status_code`, `description`, `content`).
101
136
  * **`MediaType`**: Maps a MIME content-type string to its schema and example payloads (`content_type`, `schema`, `example`, `examples`).
102
- * **`Schema`**: Normalized schema structure representing primitive and complex types (`type`, `format`, `properties`, `items`, `required`, `enum`, `default`, `nullable`, `description`).
137
+ * **`Schema`**: Normalized schema structure representing primitive and complex types (`type`, `format`, `properties`, `items`, `required`, `enum`, `default`, `nullable`, `description`, `const`, `one_of`, `any_of`, `all_of`, `read_only`, `write_only`, `deprecated`).
103
138
 
104
139
  #### Current Scope Limitations
105
140
 
106
- The Milestone 3 parser intentionally skips:
107
- - Polymorphic composition keywords (`oneOf`, `anyOf`, `allOf`, `discriminator`).
141
+ The parser handles JSON Schema union keywords (`oneOf`, `anyOf`, `allOf`) and
142
+ OpenAPI 3.1 features such as list-form `type` and `const`, but intentionally
143
+ skips:
144
+ - `discriminator`-driven union routing.
108
145
  - OpenAPI callbacks, links, and webhooks.
146
+ - `patternProperties`, `$dynamicRef`, `$dynamicAnchor`.
109
147
  - Advanced example inheritance chains.
110
148
 
111
- ### 3.3 Schema Converter
149
+ ### 3.4 Schema Converter
112
150
 
113
151
  The **Schema Converter** (`SchemaConverter` and `PydanticFactory`) converts internal schema models (`Schema`) into dynamic Pydantic `BaseModel` classes using `pydantic.create_model()`.
114
152
 
@@ -135,6 +173,11 @@ Dynamic Pydantic Model (type[BaseModel])
135
173
  | `array` | `list[T]` | Recursively typed items (e.g. `list[str]`) |
136
174
  | `object` | Dynamic `BaseModel` | Dynamic nested models (e.g. `SearchWorksInput_Address`) |
137
175
  | `enum` | Dynamic `Enum` | String Enum subclass (e.g. `SortEnum`) |
176
+ | `oneOf` / `anyOf` | `typing.Union[...]` | Variants are recursively converted |
177
+ | `allOf` | Merged `BaseModel` | Properties and `required` sets are combined |
178
+ | `type: [X, "null"]` | `Optional[X]` | 3.1-style nullable union |
179
+ | `nullable: true` | `Optional[X]` | 3.0-style nullable flag |
180
+ | `const` | `Literal[value]` | Fixed constant value |
138
181
 
139
182
  #### Model Naming Conventions
140
183
 
@@ -144,13 +187,14 @@ Dynamic Pydantic Model (type[BaseModel])
144
187
 
145
188
  #### Current Limitations
146
189
 
147
- The converter currently skips:
148
- - Polymorphic composition keywords (`oneOf`, `anyOf`, `allOf`, `discriminator`).
190
+ The converter now covers `oneOf` / `anyOf` / `allOf`, list-form `type`,
191
+ `nullable`, and `const`. It intentionally does not yet cover:
192
+ - `discriminator`-driven union routing (variants are unions without tag dispatch).
149
193
  - Recursive schemas.
150
- - XML schema options.
151
- - Complex union types beyond `Optional`.
194
+ - XML schema-driven request serialization.
195
+ - `patternProperties`, `$dynamicRef`, `$dynamicAnchor`.
152
196
 
153
- ### 3.4 Async HTTP Executor Engine
197
+ ### 3.5 Async HTTP Executor Engine
154
198
 
155
199
  The **Async HTTP Executor** (`AsyncHTTPExecutor`) executes an `Operation` asynchronously using `httpx.AsyncClient`, transforming inputs into normalized `ResponseData` instances.
156
200
 
@@ -190,11 +234,11 @@ OpenAPIError
190
234
  └── ExecutionTimeoutError
191
235
  ```
192
236
 
193
- ### 3.5 Authentication Provider
237
+ ### 3.6 Authentication Provider
194
238
 
195
239
  The **Authentication Provider** manages auth headers and query parameters dynamically. It supports multiple authentication schemes (API Key, HTTP Bearer, HTTP Basic, OAuth2) and securely injects credentials into outbound HTTP requests without exposing secret values to the LLM agent or tool definitions.
196
240
 
197
- ### 3.6 Tool Generator
241
+ ### 3.7 Tool Generator
198
242
 
199
243
  The **Tool Generator** acts as the high-level factory interface for end users. It converts parsed operations into `langchain_core.tools.BaseTool` instances. It supports configuration options such as filtering by HTTP method, operation tags, or path patterns, as well as customizing tool naming conventions and prompt description templates.
200
244
 
@@ -0,0 +1,58 @@
1
+ # Changelog
2
+
3
+ All notable changes to `langchain-openapi` will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ---
9
+
10
+ ## [Unreleased]
11
+
12
+ ### Added
13
+ - **Spec Adapter Architecture (`langchain_openapi_tools.adapters`)**: Introduced a `SpecAdapter` protocol plus concrete `Swagger2Adapter` and `OpenAPI3Adapter` implementations that provide a uniform pipeline entry for Swagger 2.0, OpenAPI 3.0.x, and OpenAPI 3.1.x documents. New public helpers: `detect_spec_version`, `select_adapter`, and `normalize_spec`. `OpenAPISpec.spec_family` records the source family, and `OpenAPISpec.from_dict` now routes through the adapter layer.
14
+ - **OpenAPI 3.1 Schema Support**: Parser and `SchemaConverter` now understand union `type` arrays (`["string", "null"]`), `const`, `oneOf` / `anyOf` (rendered as `typing.Union`), `allOf` (merged into a single Pydantic model), and the `readOnly` / `writeOnly` / `deprecated` field flags. `Schema` gained `const`, `one_of`, `any_of`, `all_of`, `read_only`, `write_only`, and `deprecated` attributes.
15
+ - **Full Media-Type Dispatch**: `RequestBuilder` now inspects each operation's declared `requestBody` content types and dispatches to the correct httpx encoding path — `application/json` (and `+json` vendor variants), `application/x-www-form-urlencoded`, `multipart/form-data` (with file-part support), `text/*`, and `application/xml`. Pydantic-model bodies produced by the dynamic args schema are coerced back to JSON-safe primitives before serialization. `BuiltRequest` gained `data`, `files`, and `content` fields.
16
+ - **Real-World Compatibility Tests**: Added `tests/test_adapters.py`, `tests/test_openapi_31.py`, `tests/test_media_types.py`, and `tests/test_compat_matrix.py` (Petstore, Crossref, GitHub, Stripe, Kubernetes, ASP.NET fakerestapi excerpts) exercising the full pipeline end-to-end via `respx`.
17
+
18
+ ### Fixed
19
+ - **Base URL Resolution Across the Pipeline**: The specification's source URL is now propagated from `OpenAPILoader.from_url` → `OpenAPISpec` → `OpenAPIParser` → `RequestBuilder`. This closes an architectural gap where relative or missing `servers` entries produced relative request URLs.
20
+ - OpenAPI 3.x specs that omit the `servers` block (e.g. `https://fakerestapi.azurewebsites.net/swagger/v1/swagger.json`) now default to the document's `scheme://host` origin, matching the OpenAPI 3.x specification.
21
+ - OpenAPI 3.x relative server URLs (e.g. `"/api/v2"`) are resolved against the document location via `urllib.parse.urljoin`.
22
+ - Swagger 2.0 specs that omit `host` fall back to the source URL's host and scheme.
23
+ - `OpenAPISpec` gained a `source_url` field; `OpenAPISpec.from_dict` and `SwaggerNormalizer` accept an optional `source_url` argument for programmatic use.
24
+ - Redundant Swagger normalization calls in `OpenAPILoader.load` and `OpenAPIParser.__init__` were removed — `OpenAPISpec.from_dict` is now the single normalization site.
25
+ - No changes to `RequestBuilder` or `AsyncHTTPExecutor` were required to fix base-URL resolution; they transparently receive an absolute base URL because `spec.servers[0]` is guaranteed absolute whenever the spec was loaded from a URL.
26
+
27
+ ### Compatibility
28
+ - All previously public APIs (`OpenAPIToolkit`, `OpenAPILoader`, `OpenAPIParser`, `OpenAPISpec`, `SwaggerNormalizer`, `RequestBuilder`, `AsyncHTTPExecutor`, middleware, providers) retain their original signatures. New parameters (`source_url`, `spec_family`) are optional.
29
+
30
+ ---
31
+
32
+ ## [1.0.2] - 2026-08-01
33
+
34
+ ### Fixed
35
+ - **Base URL Generation**: Fixed Swagger 2.0 base URL generation (e.g. Crossref host/basePath/schemes resolution) to prevent relative URL execution errors.
36
+ - **URL Resolution**: Updated `RequestBuilder` to use `urllib.parse.urljoin` for safe URL concatenation.
37
+
38
+ ### Added
39
+ - **Package Naming Clarification**: Clarified PyPI package name (`langchain-openapi-tools`) vs import module name (`langchain_openapi`) across documentation.
40
+ - **Prompt Optimization & Config**: Introduced `OpenAPIToolkitConfig` for user-controlled description modes (`full`, `compact`, `minimal`) and description prompt compression (`compress_descriptions=True`).
41
+ - **Tool Description Customization**: Added `tool_description_overrides` dict and custom `description_builder` callback functions.
42
+ - **Operation & Tag Filtering**: Added tag filtering (`include_tags`, `exclude_tags`) and operation filtering (`include_operations`, `exclude_operations`) at initial toolkit construction level.
43
+
44
+ ---
45
+
46
+ ## [1.0.0] - 2026-08-01
47
+
48
+ ### Added
49
+ - **First Production Release (v1.0.0)**.
50
+ - **OpenAPI Loader**: Load specs from remote URLs, local JSON/YAML files, or Python dictionaries.
51
+ - **OpenAPI Parser**: Strongly typed internal data models for operations, parameters, request bodies, and responses with local `$ref` resolution.
52
+ - **Schema Converter Engine**: Convert JSON Schema parameters and request bodies to dynamic Pydantic models at runtime with optional multi-page pagination controls.
53
+ - **Async HTTP Executor Engine**: Asynchronous execution using `httpx.AsyncClient` with dynamic parameter formatting and response parsing.
54
+ - **LangChain Tool Factory**: Convert OpenAPI operations into dynamic LangChain `StructuredTool` collections with filtering options.
55
+ - **Authentication & Request Providers**: Pluggable provider system (`BearerAuthProvider`, `APIKeyHeaderProvider`, `APIKeyQueryProvider`, `BasicAuthProvider`, `CompositeProvider`).
56
+ - **Production Middleware**: Onion-style pipeline (`RetryMiddleware`, `RateLimitMiddleware`, `CacheMiddleware`, `PaginationMiddleware`, `LoggingMiddleware`).
57
+ - **Documentation & Examples**: Comprehensive MkDocs site, complete example applications (Crossref, GitHub, Petstore, JSONPlaceholder), and benchmark suite.
58
+ - **CI/CD & Release Automation**: GitHub Actions for CI, Release generation, PyPI Trusted Publishing, and GitHub Pages deployment.
@@ -10,7 +10,7 @@ lint:
10
10
  uv run ruff check .
11
11
 
12
12
  typecheck:
13
- uv run mypy langchain_openapi tests examples
13
+ uv run mypy langchain_openapi_tools langchain_openapi tests examples
14
14
 
15
15
  format:
16
16
  uv run ruff format .
@@ -0,0 +1,311 @@
1
+ Metadata-Version: 2.4
2
+ Name: langchain-openapi-tools
3
+ Version: 2.0.0
4
+ Summary: Convert OpenAPI specifications into native, production-grade LangChain tools.
5
+ Project-URL: Homepage, https://github.com/abhaywani114/langchain-openapi
6
+ Project-URL: Documentation, https://abhaywani114.github.io/langchain-openapi/
7
+ Project-URL: Repository, https://github.com/abhaywani114/langchain-openapi
8
+ Project-URL: Issues, https://github.com/abhaywani114/langchain-openapi/issues
9
+ Author: langchain-openapi contributors
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: agents,ai,langchain,llm,openapi,swagger,tools
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: httpx>=0.25.0
23
+ Requires-Dist: langchain-core>=1.5.3
24
+ Requires-Dist: pydantic>=2.13.4
25
+ Requires-Dist: pytest-asyncio>=1.4.0
26
+ Requires-Dist: pyyaml>=6.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: build>=1.0.0; extra == 'dev'
29
+ Requires-Dist: mkdocs-material>=9.5.0; extra == 'dev'
30
+ Requires-Dist: mkdocstrings[python]>=0.24.0; extra == 'dev'
31
+ Requires-Dist: mypy>=1.8.0; extra == 'dev'
32
+ Requires-Dist: pre-commit>=3.6.0; extra == 'dev'
33
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
34
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
35
+ Requires-Dist: respx>=0.21.0; extra == 'dev'
36
+ Requires-Dist: ruff>=0.3.0; extra == 'dev'
37
+ Requires-Dist: twine>=5.0.0; extra == 'dev'
38
+ Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
39
+ Description-Content-Type: text/markdown
40
+
41
+ # langchain-openapi
42
+
43
+ <p align="center">
44
+ <!-- Logo Placeholder -->
45
+ <img src="docs/assets/logo.png" alt="langchain-openapi logo" width="200" onerror="this.style.display='none'"/>
46
+ </p>
47
+
48
+ <p align="center">
49
+ <em>Convert OpenAPI v3.0 & v3.1 and Swagger 2.0 specifications into native, production-grade LangChain tools.</em>
50
+ </p>
51
+
52
+ <p align="center">
53
+ <a href="https://github.com/abhaywani114/langchain-openapi/actions/workflows/ci.yml"><img src="https://github.com/abhaywani114/langchain-openapi/actions/workflows/ci.yml/badge.svg" alt="CI Status"/></a>
54
+ <a href="https://pypi.org/project/langchain-openapi-tools/"><img src="https://img.shields.io/pypi/v/langchain-openapi-tools.svg" alt="PyPI Version"/></a>
55
+ <a href="https://abhaywani114.github.io/langchain-openapi/"><img src="https://img.shields.io/badge/docs-mkdocs-blue.svg" alt="Documentation"/></a>
56
+ <a href="https://python.org"><img src="https://img.shields.io/badge/python-3.11%2B-blue.svg" alt="Python 3.11+"/></a>
57
+ <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/badge/code%20style-ruff-000000.svg" alt="Code Style: Ruff"/></a>
58
+ <a href="http://mypy-lang.org/"><img src="https://img.shields.io/badge/mypy-checked-blue.svg" alt="Checked with MyPy"/></a>
59
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License: MIT"/></a>
60
+ </p>
61
+
62
+ ---
63
+
64
+ `langchain_openapi` is a modern Python library designed to seamlessly convert OpenAPI v3.0, v3.1, and Swagger 2.0 specifications into native, type-safe [LangChain](https://github.com/langchain-ai/langchain) tools for AI agents and LLM applications.
65
+
66
+ No python code generation is required—tools are generated dynamically at runtime with strict Pydantic input schemas, prompt optimization options, and production-ready middleware.
67
+
68
+ ---
69
+
70
+ ## Installation & Importing
71
+
72
+ Install the PyPI package:
73
+
74
+ ```bash
75
+ pip install langchain-openapi-tools
76
+ # or using uv
77
+ uv add langchain-openapi-tools
78
+ ```
79
+
80
+ Import in Python:
81
+
82
+ ```python
83
+ from langchain_openapi_tools import OpenAPIToolkit, OpenAPIToolkitConfig
84
+ ```
85
+
86
+ ### Migration Note
87
+
88
+ ```python
89
+ # Old (deprecated, but still works for backward compatibility):
90
+ from langchain_openapi import OpenAPIToolkit
91
+
92
+ # New (recommended):
93
+ from langchain_openapi_tools import OpenAPIToolkit
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Features
99
+
100
+ - ⚡ **Zero-Code Tool Generation**: Runtime conversion of OpenAPI specs (YAML/JSON) into LangChain `StructuredTool`s.
101
+ - 🚀 **Swagger 2.0 & OpenAPI 3.x**: Native normalization of legacy Swagger 2.0 and modern OpenAPI 3.0/3.1 specs.
102
+ - 🗜️ **Prompt Optimization & Filtering**: Description modes (`full`, `compact`, `minimal`), description compression, overrides, callbacks, and operation/tag filtering to drastically reduce context window usage.
103
+ - 🔒 **Pluggable Authentication**: Built-in support for Bearer Tokens, API Key Headers, Query Parameters, Basic Auth, and custom request providers.
104
+ - 🛡️ **Production Middleware**: Composable middleware architecture for Retries (exponential backoff), Rate Limiting (token-bucket), Caching (TTL), Pagination aggregation, and Sanitized Logging.
105
+ - 🎯 **Type-Safe Validation**: Dynamically generated Pydantic input schemas ensure LLM arguments adhere strictly to specification types before network transport.
106
+ - 🌐 **Async Engine**: Non-blocking asynchronous network transport powered by `httpx.AsyncClient`.
107
+
108
+ ---
109
+
110
+ ## Supported Specifications
111
+
112
+ - ✅ **Swagger 2.0** (Automatically normalized to OpenAPI 3.0 via the built-in adapter layer)
113
+ - ✅ **OpenAPI 3.0.x** (JSON and YAML)
114
+ - ✅ **OpenAPI 3.1.x** (JSON and YAML, including union `type` arrays, `oneOf` / `anyOf` / `allOf`, and `const`)
115
+
116
+ > **Note:** Swagger 2.0 is commonly referred to as OpenAPI 2.0.
117
+
118
+ ### Compatibility Matrix
119
+
120
+ | Feature | Swagger 2.0 | OpenAPI 3.0 | OpenAPI 3.1 |
121
+ | -------------------------------------- | :---------: | :---------: | :---------: |
122
+ | Path / query / header / cookie params | ✅ | ✅ | ✅ |
123
+ | `$ref` resolution (internal) | ✅ | ✅ | ✅ |
124
+ | Base URL from `host` + `basePath` | ✅ | — | — |
125
+ | Base URL from `servers[]` | — | ✅ | ✅ |
126
+ | Fallback base URL from spec source URL | ✅ | ✅ | ✅ |
127
+ | `application/json` request bodies | ✅ | ✅ | ✅ |
128
+ | `application/x-www-form-urlencoded` | ✅ | ✅ | ✅ |
129
+ | `multipart/form-data` (incl. files) | ✅ | ✅ | ✅ |
130
+ | `text/*` and `application/xml` | ✅ | ✅ | ✅ |
131
+ | Vendor `+json` media types | ✅ | ✅ | ✅ |
132
+ | `oneOf` / `anyOf` (as Python `Union`) | — | ✅ | ✅ |
133
+ | `allOf` merge into single model | — | ✅ | ✅ |
134
+ | `nullable: true` (3.0) | — | ✅ | — |
135
+ | `type: ["string", "null"]` (3.1) | — | — | ✅ |
136
+ | `const` | — | — | ✅ |
137
+ | `readOnly` / `writeOnly` / `deprecated`| ✅ | ✅ | ✅ |
138
+ | Security: Bearer / API key / Basic | ✅ | ✅ | ✅ |
139
+ | Async execution (`httpx.AsyncClient`) | ✅ | ✅ | ✅ |
140
+
141
+ Not yet supported: `discriminator`-driven union routing, `patternProperties`,
142
+ `$dynamicRef` / `$dynamicAnchor`, callbacks, links, webhooks, and XML request-body
143
+ serialization from Python dicts.
144
+
145
+ ---
146
+
147
+ ## Quick Start
148
+
149
+ ```python
150
+ from langchain_openapi_tools import OpenAPIToolkit
151
+
152
+ # Load spec from remote URL or local file
153
+ toolkit = OpenAPIToolkit.from_url("https://api.crossref.org/swagger-docs")
154
+
155
+ # Extract generated tools
156
+ tools = toolkit.get_tools()
157
+
158
+ print(f"Generated {len(tools)} tools:")
159
+ for tool in tools[:3]:
160
+ print(f"- {tool.name}: {tool.description}")
161
+ ```
162
+
163
+ ### Agent Integration
164
+
165
+ ```python
166
+ import asyncio
167
+ from langchain_openapi_tools import OpenAPIToolkit
168
+
169
+
170
+ async def main():
171
+ toolkit = OpenAPIToolkit.from_url("https://api.crossref.org/swagger-docs")
172
+ search_tool = toolkit.get_tool("get_works")
173
+
174
+ if search_tool:
175
+ result = await search_tool.ainvoke({"query": "LangGraph"})
176
+ print("Search Result:", result)
177
+
178
+
179
+ if __name__ == "__main__":
180
+ asyncio.run(main())
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Prompt Optimization & Tool Customization
186
+
187
+ Large OpenAPI specifications can generate extensive tool descriptions that exceed model context windows. `langchain_openapi_tools` provides full control over description generation and context footprint.
188
+
189
+ ### Configuration Object (`OpenAPIToolkitConfig`)
190
+
191
+ ```python
192
+ from langchain_openapi_tools import OpenAPIToolkit, OpenAPIToolkitConfig
193
+
194
+ config = OpenAPIToolkitConfig(
195
+ description_mode="compact",
196
+ compress_descriptions=True,
197
+ include_tags=["Works"],
198
+ tool_description_overrides={
199
+ "get_works": "Search scholarly papers registered with Crossref."
200
+ },
201
+ )
202
+
203
+ toolkit = OpenAPIToolkit.from_url(
204
+ "https://api.crossref.org/swagger-docs", config=config
205
+ )
206
+ ```
207
+
208
+ ### Description Modes (`description_mode`)
209
+
210
+ - `full` *(default)*: Complete summary, description, HTTP method, path, and schema parameter details.
211
+ - `compact`: Summary and short parameter list without response schemas or redundant examples.
212
+ - `minimal`: A single-sentence summary ideal for large specifications with dozens of tools.
213
+
214
+ ```python
215
+ toolkit = OpenAPIToolkit.from_url(url, description_mode="minimal")
216
+ ```
217
+
218
+ ### Description Compression (`compress_descriptions=True`)
219
+
220
+ Removes duplicate text, redundant whitespace, and empty sections without altering tool semantics:
221
+
222
+ ```python
223
+ toolkit = OpenAPIToolkit.from_url(url, compress_descriptions=True)
224
+ ```
225
+
226
+ ### Custom Overrides & Callbacks
227
+
228
+ Override descriptions for specific tools:
229
+
230
+ ```python
231
+ toolkit = OpenAPIToolkit.from_url(
232
+ url, tool_description_overrides={"get_works": "Search scholarly papers."}
233
+ )
234
+ ```
235
+
236
+ Or pass a custom builder callback:
237
+
238
+ ```python
239
+ def my_builder(operation):
240
+ return f"Execute {operation.name} on path {operation.path}."
241
+
242
+
243
+ toolkit = OpenAPIToolkit.from_url(url, description_builder=my_builder)
244
+ ```
245
+
246
+ ### Operation Filtering
247
+
248
+ Filter tools before they are created to reduce context window overhead:
249
+
250
+ ```python
251
+ # Filter by Tags
252
+ toolkit = OpenAPIToolkit.from_url(url, include_tags=["Works"], exclude_tags=["Admin"])
253
+
254
+ # Filter by Operations
255
+ toolkit = OpenAPIToolkit.from_url(
256
+ url, include_operations=["get_works"], exclude_operations=["delete_work"]
257
+ )
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Architecture Pipeline
263
+
264
+ ```text
265
+ Swagger 2.0 / OpenAPI 3.x
266
+
267
+
268
+ Swagger Normalizer
269
+
270
+
271
+ Normalized OpenAPI Model
272
+
273
+
274
+ Existing Parser
275
+
276
+
277
+ Internal Operation Models
278
+
279
+
280
+ Schema Converter
281
+
282
+
283
+ HTTP Executor
284
+
285
+
286
+ LangChain StructuredTools
287
+ ```
288
+
289
+ ### Example:
290
+
291
+ ```python
292
+ from langchain_openapi_tools import OpenAPIToolkit
293
+ from langchain.agents import create_agent
294
+ from langchain.chat_models import init_chat_model
295
+
296
+ toolkit = OpenAPIToolkit.from_url(
297
+ "https://api.crossref.org/swagger-docs"
298
+ )
299
+
300
+ model = init_chat_model("openrouter:qwen/qwen3-32b:free")
301
+
302
+ agent = create_agent(
303
+ model=model,
304
+ tools=toolkit.get_tools(tags=["Works"]),
305
+ )
306
+
307
+ response = agent.invoke({
308
+ "messages": "Find papers about Kashmir"
309
+ })
310
+
311
+ ```