langchain 0.3.27__py3-none-any.whl → 1.0.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (1365) hide show
  1. langchain/__init__.py +2 -452
  2. langchain/agents/__init__.py +9 -178
  3. langchain/agents/factory.py +1582 -0
  4. langchain/agents/middleware/__init__.py +80 -0
  5. langchain/agents/middleware/_execution.py +388 -0
  6. langchain/agents/middleware/_redaction.py +350 -0
  7. langchain/agents/middleware/context_editing.py +274 -0
  8. langchain/agents/middleware/file_search.py +382 -0
  9. langchain/agents/middleware/human_in_the_loop.py +351 -0
  10. langchain/agents/middleware/model_call_limit.py +210 -0
  11. langchain/agents/middleware/model_fallback.py +137 -0
  12. langchain/agents/middleware/pii.py +317 -0
  13. langchain/agents/middleware/shell_tool.py +718 -0
  14. langchain/agents/middleware/summarization.py +249 -0
  15. langchain/agents/middleware/todo.py +219 -0
  16. langchain/agents/middleware/tool_call_limit.py +333 -0
  17. langchain/agents/middleware/tool_emulator.py +200 -0
  18. langchain/agents/middleware/tool_retry.py +384 -0
  19. langchain/agents/middleware/tool_selection.py +310 -0
  20. langchain/agents/middleware/types.py +1572 -0
  21. langchain/agents/structured_output.py +426 -0
  22. langchain/chat_models/__init__.py +7 -72
  23. langchain/chat_models/base.py +264 -317
  24. langchain/embeddings/__init__.py +7 -217
  25. langchain/embeddings/base.py +32 -42
  26. langchain/messages/__init__.py +72 -0
  27. langchain/rate_limiters/__init__.py +13 -0
  28. langchain/tools/__init__.py +17 -197
  29. langchain/tools/tool_node.py +1700 -0
  30. langchain-1.0.0.dist-info/METADATA +87 -0
  31. langchain-1.0.0.dist-info/RECORD +34 -0
  32. {langchain-0.3.27.dist-info → langchain-1.0.0.dist-info}/WHEEL +1 -1
  33. langchain/_api/__init__.py +0 -28
  34. langchain/_api/deprecation.py +0 -32
  35. langchain/_api/interactive_env.py +0 -5
  36. langchain/_api/module_import.py +0 -153
  37. langchain/_api/path.py +0 -3
  38. langchain/adapters/__init__.py +0 -0
  39. langchain/adapters/openai.py +0 -63
  40. langchain/agents/agent.py +0 -1828
  41. langchain/agents/agent_iterator.py +0 -431
  42. langchain/agents/agent_toolkits/__init__.py +0 -167
  43. langchain/agents/agent_toolkits/ainetwork/__init__.py +0 -1
  44. langchain/agents/agent_toolkits/ainetwork/toolkit.py +0 -25
  45. langchain/agents/agent_toolkits/amadeus/toolkit.py +0 -23
  46. langchain/agents/agent_toolkits/azure_cognitive_services.py +0 -29
  47. langchain/agents/agent_toolkits/base.py +0 -3
  48. langchain/agents/agent_toolkits/clickup/__init__.py +0 -0
  49. langchain/agents/agent_toolkits/clickup/toolkit.py +0 -25
  50. langchain/agents/agent_toolkits/conversational_retrieval/__init__.py +0 -0
  51. langchain/agents/agent_toolkits/conversational_retrieval/openai_functions.py +0 -87
  52. langchain/agents/agent_toolkits/conversational_retrieval/tool.py +0 -3
  53. langchain/agents/agent_toolkits/csv/__init__.py +0 -28
  54. langchain/agents/agent_toolkits/file_management/__init__.py +0 -31
  55. langchain/agents/agent_toolkits/file_management/toolkit.py +0 -29
  56. langchain/agents/agent_toolkits/github/__init__.py +0 -1
  57. langchain/agents/agent_toolkits/github/toolkit.py +0 -69
  58. langchain/agents/agent_toolkits/gitlab/__init__.py +0 -1
  59. langchain/agents/agent_toolkits/gitlab/toolkit.py +0 -25
  60. langchain/agents/agent_toolkits/gmail/__init__.py +0 -1
  61. langchain/agents/agent_toolkits/gmail/toolkit.py +0 -23
  62. langchain/agents/agent_toolkits/jira/__init__.py +0 -1
  63. langchain/agents/agent_toolkits/jira/toolkit.py +0 -23
  64. langchain/agents/agent_toolkits/json/__init__.py +0 -1
  65. langchain/agents/agent_toolkits/json/base.py +0 -25
  66. langchain/agents/agent_toolkits/json/prompt.py +0 -24
  67. langchain/agents/agent_toolkits/json/toolkit.py +0 -23
  68. langchain/agents/agent_toolkits/multion/__init__.py +0 -1
  69. langchain/agents/agent_toolkits/multion/toolkit.py +0 -25
  70. langchain/agents/agent_toolkits/nasa/__init__.py +0 -1
  71. langchain/agents/agent_toolkits/nasa/toolkit.py +0 -23
  72. langchain/agents/agent_toolkits/nla/__init__.py +0 -0
  73. langchain/agents/agent_toolkits/nla/tool.py +0 -23
  74. langchain/agents/agent_toolkits/nla/toolkit.py +0 -23
  75. langchain/agents/agent_toolkits/office365/__init__.py +0 -1
  76. langchain/agents/agent_toolkits/office365/toolkit.py +0 -25
  77. langchain/agents/agent_toolkits/openapi/__init__.py +0 -1
  78. langchain/agents/agent_toolkits/openapi/base.py +0 -25
  79. langchain/agents/agent_toolkits/openapi/planner.py +0 -52
  80. langchain/agents/agent_toolkits/openapi/planner_prompt.py +0 -103
  81. langchain/agents/agent_toolkits/openapi/prompt.py +0 -29
  82. langchain/agents/agent_toolkits/openapi/spec.py +0 -30
  83. langchain/agents/agent_toolkits/openapi/toolkit.py +0 -30
  84. langchain/agents/agent_toolkits/pandas/__init__.py +0 -28
  85. langchain/agents/agent_toolkits/playwright/__init__.py +0 -29
  86. langchain/agents/agent_toolkits/playwright/toolkit.py +0 -27
  87. langchain/agents/agent_toolkits/powerbi/__init__.py +0 -1
  88. langchain/agents/agent_toolkits/powerbi/base.py +0 -25
  89. langchain/agents/agent_toolkits/powerbi/chat_base.py +0 -27
  90. langchain/agents/agent_toolkits/powerbi/prompt.py +0 -36
  91. langchain/agents/agent_toolkits/powerbi/toolkit.py +0 -25
  92. langchain/agents/agent_toolkits/python/__init__.py +0 -28
  93. langchain/agents/agent_toolkits/slack/__init__.py +0 -1
  94. langchain/agents/agent_toolkits/slack/toolkit.py +0 -23
  95. langchain/agents/agent_toolkits/spark/__init__.py +0 -28
  96. langchain/agents/agent_toolkits/spark_sql/__init__.py +0 -1
  97. langchain/agents/agent_toolkits/spark_sql/base.py +0 -25
  98. langchain/agents/agent_toolkits/spark_sql/prompt.py +0 -27
  99. langchain/agents/agent_toolkits/spark_sql/toolkit.py +0 -25
  100. langchain/agents/agent_toolkits/sql/__init__.py +0 -1
  101. langchain/agents/agent_toolkits/sql/base.py +0 -23
  102. langchain/agents/agent_toolkits/sql/prompt.py +0 -29
  103. langchain/agents/agent_toolkits/sql/toolkit.py +0 -25
  104. langchain/agents/agent_toolkits/steam/__init__.py +0 -1
  105. langchain/agents/agent_toolkits/steam/toolkit.py +0 -23
  106. langchain/agents/agent_toolkits/vectorstore/__init__.py +0 -1
  107. langchain/agents/agent_toolkits/vectorstore/base.py +0 -217
  108. langchain/agents/agent_toolkits/vectorstore/prompt.py +0 -11
  109. langchain/agents/agent_toolkits/vectorstore/toolkit.py +0 -97
  110. langchain/agents/agent_toolkits/xorbits/__init__.py +0 -28
  111. langchain/agents/agent_toolkits/zapier/__init__.py +0 -1
  112. langchain/agents/agent_toolkits/zapier/toolkit.py +0 -25
  113. langchain/agents/agent_types.py +0 -57
  114. langchain/agents/chat/__init__.py +0 -0
  115. langchain/agents/chat/base.py +0 -178
  116. langchain/agents/chat/output_parser.py +0 -74
  117. langchain/agents/chat/prompt.py +0 -29
  118. langchain/agents/conversational/__init__.py +0 -1
  119. langchain/agents/conversational/base.py +0 -176
  120. langchain/agents/conversational/output_parser.py +0 -51
  121. langchain/agents/conversational/prompt.py +0 -35
  122. langchain/agents/conversational_chat/__init__.py +0 -1
  123. langchain/agents/conversational_chat/base.py +0 -181
  124. langchain/agents/conversational_chat/output_parser.py +0 -57
  125. langchain/agents/conversational_chat/prompt.py +0 -56
  126. langchain/agents/format_scratchpad/__init__.py +0 -25
  127. langchain/agents/format_scratchpad/log.py +0 -25
  128. langchain/agents/format_scratchpad/log_to_messages.py +0 -26
  129. langchain/agents/format_scratchpad/openai_functions.py +0 -80
  130. langchain/agents/format_scratchpad/openai_tools.py +0 -5
  131. langchain/agents/format_scratchpad/tools.py +0 -65
  132. langchain/agents/format_scratchpad/xml.py +0 -52
  133. langchain/agents/initialize.py +0 -105
  134. langchain/agents/json_chat/__init__.py +0 -0
  135. langchain/agents/json_chat/base.py +0 -195
  136. langchain/agents/json_chat/prompt.py +0 -8
  137. langchain/agents/load_tools.py +0 -13
  138. langchain/agents/loading.py +0 -148
  139. langchain/agents/mrkl/__init__.py +0 -1
  140. langchain/agents/mrkl/base.py +0 -216
  141. langchain/agents/mrkl/output_parser.py +0 -103
  142. langchain/agents/mrkl/prompt.py +0 -15
  143. langchain/agents/openai_assistant/__init__.py +0 -3
  144. langchain/agents/openai_assistant/base.py +0 -818
  145. langchain/agents/openai_functions_agent/__init__.py +0 -0
  146. langchain/agents/openai_functions_agent/agent_token_buffer_memory.py +0 -101
  147. langchain/agents/openai_functions_agent/base.py +0 -381
  148. langchain/agents/openai_functions_multi_agent/__init__.py +0 -0
  149. langchain/agents/openai_functions_multi_agent/base.py +0 -337
  150. langchain/agents/openai_tools/__init__.py +0 -0
  151. langchain/agents/openai_tools/base.py +0 -108
  152. langchain/agents/output_parsers/__init__.py +0 -35
  153. langchain/agents/output_parsers/json.py +0 -62
  154. langchain/agents/output_parsers/openai_functions.py +0 -96
  155. langchain/agents/output_parsers/openai_tools.py +0 -70
  156. langchain/agents/output_parsers/react_json_single_input.py +0 -84
  157. langchain/agents/output_parsers/react_single_input.py +0 -99
  158. langchain/agents/output_parsers/self_ask.py +0 -51
  159. langchain/agents/output_parsers/tools.py +0 -107
  160. langchain/agents/output_parsers/xml.py +0 -123
  161. langchain/agents/react/__init__.py +0 -1
  162. langchain/agents/react/agent.py +0 -144
  163. langchain/agents/react/base.py +0 -185
  164. langchain/agents/react/output_parser.py +0 -33
  165. langchain/agents/react/textworld_prompt.py +0 -51
  166. langchain/agents/react/wiki_prompt.py +0 -70
  167. langchain/agents/schema.py +0 -35
  168. langchain/agents/self_ask_with_search/__init__.py +0 -4
  169. langchain/agents/self_ask_with_search/base.py +0 -215
  170. langchain/agents/self_ask_with_search/output_parser.py +0 -4
  171. langchain/agents/self_ask_with_search/prompt.py +0 -43
  172. langchain/agents/structured_chat/__init__.py +0 -0
  173. langchain/agents/structured_chat/base.py +0 -304
  174. langchain/agents/structured_chat/output_parser.py +0 -99
  175. langchain/agents/structured_chat/prompt.py +0 -34
  176. langchain/agents/tool_calling_agent/__init__.py +0 -0
  177. langchain/agents/tool_calling_agent/base.py +0 -110
  178. langchain/agents/tools.py +0 -47
  179. langchain/agents/types.py +0 -27
  180. langchain/agents/utils.py +0 -19
  181. langchain/agents/xml/__init__.py +0 -0
  182. langchain/agents/xml/base.py +0 -231
  183. langchain/agents/xml/prompt.py +0 -21
  184. langchain/base_language.py +0 -7
  185. langchain/cache.py +0 -72
  186. langchain/callbacks/__init__.py +0 -139
  187. langchain/callbacks/aim_callback.py +0 -33
  188. langchain/callbacks/argilla_callback.py +0 -25
  189. langchain/callbacks/arize_callback.py +0 -25
  190. langchain/callbacks/arthur_callback.py +0 -25
  191. langchain/callbacks/base.py +0 -29
  192. langchain/callbacks/clearml_callback.py +0 -25
  193. langchain/callbacks/comet_ml_callback.py +0 -25
  194. langchain/callbacks/confident_callback.py +0 -25
  195. langchain/callbacks/context_callback.py +0 -25
  196. langchain/callbacks/file.py +0 -3
  197. langchain/callbacks/flyte_callback.py +0 -25
  198. langchain/callbacks/human.py +0 -33
  199. langchain/callbacks/infino_callback.py +0 -25
  200. langchain/callbacks/labelstudio_callback.py +0 -33
  201. langchain/callbacks/llmonitor_callback.py +0 -27
  202. langchain/callbacks/manager.py +0 -89
  203. langchain/callbacks/mlflow_callback.py +0 -38
  204. langchain/callbacks/openai_info.py +0 -25
  205. langchain/callbacks/promptlayer_callback.py +0 -27
  206. langchain/callbacks/sagemaker_callback.py +0 -27
  207. langchain/callbacks/stdout.py +0 -3
  208. langchain/callbacks/streaming_aiter.py +0 -75
  209. langchain/callbacks/streaming_aiter_final_only.py +0 -91
  210. langchain/callbacks/streaming_stdout.py +0 -5
  211. langchain/callbacks/streaming_stdout_final_only.py +0 -91
  212. langchain/callbacks/streamlit/__init__.py +0 -86
  213. langchain/callbacks/streamlit/mutable_expander.py +0 -33
  214. langchain/callbacks/streamlit/streamlit_callback_handler.py +0 -49
  215. langchain/callbacks/tracers/__init__.py +0 -38
  216. langchain/callbacks/tracers/base.py +0 -6
  217. langchain/callbacks/tracers/comet.py +0 -30
  218. langchain/callbacks/tracers/evaluation.py +0 -8
  219. langchain/callbacks/tracers/langchain.py +0 -8
  220. langchain/callbacks/tracers/langchain_v1.py +0 -3
  221. langchain/callbacks/tracers/log_stream.py +0 -9
  222. langchain/callbacks/tracers/logging.py +0 -46
  223. langchain/callbacks/tracers/root_listeners.py +0 -3
  224. langchain/callbacks/tracers/run_collector.py +0 -3
  225. langchain/callbacks/tracers/schemas.py +0 -27
  226. langchain/callbacks/tracers/stdout.py +0 -6
  227. langchain/callbacks/tracers/wandb.py +0 -27
  228. langchain/callbacks/trubrics_callback.py +0 -25
  229. langchain/callbacks/utils.py +0 -48
  230. langchain/callbacks/wandb_callback.py +0 -25
  231. langchain/callbacks/whylabs_callback.py +0 -25
  232. langchain/chains/__init__.py +0 -96
  233. langchain/chains/api/__init__.py +0 -1
  234. langchain/chains/api/base.py +0 -394
  235. langchain/chains/api/news_docs.py +0 -31
  236. langchain/chains/api/open_meteo_docs.py +0 -32
  237. langchain/chains/api/openapi/__init__.py +0 -0
  238. langchain/chains/api/openapi/chain.py +0 -23
  239. langchain/chains/api/openapi/prompts.py +0 -27
  240. langchain/chains/api/openapi/requests_chain.py +0 -29
  241. langchain/chains/api/openapi/response_chain.py +0 -29
  242. langchain/chains/api/podcast_docs.py +0 -27
  243. langchain/chains/api/prompt.py +0 -35
  244. langchain/chains/api/tmdb_docs.py +0 -36
  245. langchain/chains/base.py +0 -800
  246. langchain/chains/chat_vector_db/__init__.py +0 -0
  247. langchain/chains/chat_vector_db/prompts.py +0 -19
  248. langchain/chains/combine_documents/__init__.py +0 -15
  249. langchain/chains/combine_documents/base.py +0 -287
  250. langchain/chains/combine_documents/map_reduce.py +0 -300
  251. langchain/chains/combine_documents/map_rerank.py +0 -247
  252. langchain/chains/combine_documents/reduce.py +0 -381
  253. langchain/chains/combine_documents/refine.py +0 -236
  254. langchain/chains/combine_documents/stuff.py +0 -288
  255. langchain/chains/constitutional_ai/__init__.py +0 -2
  256. langchain/chains/constitutional_ai/base.py +0 -321
  257. langchain/chains/constitutional_ai/models.py +0 -11
  258. langchain/chains/constitutional_ai/principles.py +0 -278
  259. langchain/chains/constitutional_ai/prompts.py +0 -120
  260. langchain/chains/conversation/__init__.py +0 -1
  261. langchain/chains/conversation/base.py +0 -143
  262. langchain/chains/conversation/memory.py +0 -45
  263. langchain/chains/conversation/prompt.py +0 -28
  264. langchain/chains/conversational_retrieval/__init__.py +0 -1
  265. langchain/chains/conversational_retrieval/base.py +0 -568
  266. langchain/chains/conversational_retrieval/prompts.py +0 -19
  267. langchain/chains/elasticsearch_database/__init__.py +0 -3
  268. langchain/chains/elasticsearch_database/base.py +0 -211
  269. langchain/chains/elasticsearch_database/prompts.py +0 -35
  270. langchain/chains/ernie_functions/__init__.py +0 -44
  271. langchain/chains/ernie_functions/base.py +0 -49
  272. langchain/chains/example_generator.py +0 -22
  273. langchain/chains/flare/__init__.py +0 -1
  274. langchain/chains/flare/base.py +0 -282
  275. langchain/chains/flare/prompts.py +0 -44
  276. langchain/chains/graph_qa/__init__.py +0 -0
  277. langchain/chains/graph_qa/arangodb.py +0 -23
  278. langchain/chains/graph_qa/base.py +0 -23
  279. langchain/chains/graph_qa/cypher.py +0 -39
  280. langchain/chains/graph_qa/cypher_utils.py +0 -27
  281. langchain/chains/graph_qa/falkordb.py +0 -29
  282. langchain/chains/graph_qa/gremlin.py +0 -36
  283. langchain/chains/graph_qa/hugegraph.py +0 -23
  284. langchain/chains/graph_qa/kuzu.py +0 -29
  285. langchain/chains/graph_qa/nebulagraph.py +0 -23
  286. langchain/chains/graph_qa/neptune_cypher.py +0 -39
  287. langchain/chains/graph_qa/neptune_sparql.py +0 -36
  288. langchain/chains/graph_qa/ontotext_graphdb.py +0 -25
  289. langchain/chains/graph_qa/prompts.py +0 -96
  290. langchain/chains/graph_qa/sparql.py +0 -23
  291. langchain/chains/history_aware_retriever.py +0 -68
  292. langchain/chains/hyde/__init__.py +0 -4
  293. langchain/chains/hyde/base.py +0 -124
  294. langchain/chains/hyde/prompts.py +0 -46
  295. langchain/chains/llm.py +0 -442
  296. langchain/chains/llm_bash/__init__.py +0 -10
  297. langchain/chains/llm_checker/__init__.py +0 -4
  298. langchain/chains/llm_checker/base.py +0 -194
  299. langchain/chains/llm_checker/prompt.py +0 -30
  300. langchain/chains/llm_math/__init__.py +0 -4
  301. langchain/chains/llm_math/base.py +0 -311
  302. langchain/chains/llm_math/prompt.py +0 -43
  303. langchain/chains/llm_requests.py +0 -23
  304. langchain/chains/llm_summarization_checker/__init__.py +0 -7
  305. langchain/chains/llm_summarization_checker/base.py +0 -205
  306. langchain/chains/llm_summarization_checker/prompts/are_all_true_prompt.txt +0 -38
  307. langchain/chains/llm_summarization_checker/prompts/check_facts.txt +0 -10
  308. langchain/chains/llm_summarization_checker/prompts/create_facts.txt +0 -10
  309. langchain/chains/llm_summarization_checker/prompts/revise_summary.txt +0 -17
  310. langchain/chains/llm_symbolic_math/__init__.py +0 -10
  311. langchain/chains/loading.py +0 -732
  312. langchain/chains/mapreduce.py +0 -121
  313. langchain/chains/moderation.py +0 -132
  314. langchain/chains/natbot/__init__.py +0 -4
  315. langchain/chains/natbot/base.py +0 -163
  316. langchain/chains/natbot/crawler.py +0 -443
  317. langchain/chains/natbot/prompt.py +0 -143
  318. langchain/chains/openai_functions/__init__.py +0 -44
  319. langchain/chains/openai_functions/base.py +0 -235
  320. langchain/chains/openai_functions/citation_fuzzy_match.py +0 -160
  321. langchain/chains/openai_functions/extraction.py +0 -197
  322. langchain/chains/openai_functions/openapi.py +0 -405
  323. langchain/chains/openai_functions/qa_with_structure.py +0 -142
  324. langchain/chains/openai_functions/tagging.py +0 -172
  325. langchain/chains/openai_functions/utils.py +0 -40
  326. langchain/chains/openai_tools/__init__.py +0 -3
  327. langchain/chains/openai_tools/extraction.py +0 -79
  328. langchain/chains/prompt_selector.py +0 -65
  329. langchain/chains/qa_generation/__init__.py +0 -0
  330. langchain/chains/qa_generation/base.py +0 -124
  331. langchain/chains/qa_generation/prompt.py +0 -50
  332. langchain/chains/qa_with_sources/__init__.py +0 -5
  333. langchain/chains/qa_with_sources/base.py +0 -263
  334. langchain/chains/qa_with_sources/loading.py +0 -209
  335. langchain/chains/qa_with_sources/map_reduce_prompt.py +0 -54
  336. langchain/chains/qa_with_sources/refine_prompts.py +0 -37
  337. langchain/chains/qa_with_sources/retrieval.py +0 -75
  338. langchain/chains/qa_with_sources/stuff_prompt.py +0 -43
  339. langchain/chains/qa_with_sources/vector_db.py +0 -86
  340. langchain/chains/query_constructor/__init__.py +0 -3
  341. langchain/chains/query_constructor/base.py +0 -376
  342. langchain/chains/query_constructor/ir.py +0 -23
  343. langchain/chains/query_constructor/parser.py +0 -210
  344. langchain/chains/query_constructor/prompt.py +0 -226
  345. langchain/chains/query_constructor/schema.py +0 -14
  346. langchain/chains/question_answering/__init__.py +0 -6
  347. langchain/chains/question_answering/chain.py +0 -279
  348. langchain/chains/question_answering/map_reduce_prompt.py +0 -80
  349. langchain/chains/question_answering/map_rerank_prompt.py +0 -66
  350. langchain/chains/question_answering/refine_prompts.py +0 -72
  351. langchain/chains/question_answering/stuff_prompt.py +0 -33
  352. langchain/chains/retrieval.py +0 -67
  353. langchain/chains/retrieval_qa/__init__.py +0 -1
  354. langchain/chains/retrieval_qa/base.py +0 -370
  355. langchain/chains/retrieval_qa/prompt.py +0 -11
  356. langchain/chains/router/__init__.py +0 -12
  357. langchain/chains/router/base.py +0 -142
  358. langchain/chains/router/embedding_router.py +0 -93
  359. langchain/chains/router/llm_router.py +0 -196
  360. langchain/chains/router/multi_prompt.py +0 -181
  361. langchain/chains/router/multi_prompt_prompt.py +0 -32
  362. langchain/chains/router/multi_retrieval_prompt.py +0 -30
  363. langchain/chains/router/multi_retrieval_qa.py +0 -109
  364. langchain/chains/sequential.py +0 -220
  365. langchain/chains/sql_database/__init__.py +0 -1
  366. langchain/chains/sql_database/prompt.py +0 -282
  367. langchain/chains/sql_database/query.py +0 -166
  368. langchain/chains/structured_output/__init__.py +0 -6
  369. langchain/chains/structured_output/base.py +0 -582
  370. langchain/chains/summarize/__init__.py +0 -6
  371. langchain/chains/summarize/chain.py +0 -174
  372. langchain/chains/summarize/map_reduce_prompt.py +0 -10
  373. langchain/chains/summarize/refine_prompts.py +0 -23
  374. langchain/chains/summarize/stuff_prompt.py +0 -10
  375. langchain/chains/transform.py +0 -84
  376. langchain/chat_loaders/__init__.py +0 -19
  377. langchain/chat_loaders/base.py +0 -3
  378. langchain/chat_loaders/facebook_messenger.py +0 -32
  379. langchain/chat_loaders/gmail.py +0 -23
  380. langchain/chat_loaders/imessage.py +0 -23
  381. langchain/chat_loaders/langsmith.py +0 -30
  382. langchain/chat_loaders/slack.py +0 -23
  383. langchain/chat_loaders/telegram.py +0 -23
  384. langchain/chat_loaders/utils.py +0 -36
  385. langchain/chat_loaders/whatsapp.py +0 -23
  386. langchain/chat_models/anthropic.py +0 -30
  387. langchain/chat_models/anyscale.py +0 -23
  388. langchain/chat_models/azure_openai.py +0 -23
  389. langchain/chat_models/azureml_endpoint.py +0 -30
  390. langchain/chat_models/baichuan.py +0 -23
  391. langchain/chat_models/baidu_qianfan_endpoint.py +0 -27
  392. langchain/chat_models/bedrock.py +0 -27
  393. langchain/chat_models/cohere.py +0 -23
  394. langchain/chat_models/databricks.py +0 -23
  395. langchain/chat_models/ernie.py +0 -23
  396. langchain/chat_models/everlyai.py +0 -23
  397. langchain/chat_models/fake.py +0 -30
  398. langchain/chat_models/fireworks.py +0 -23
  399. langchain/chat_models/gigachat.py +0 -23
  400. langchain/chat_models/google_palm.py +0 -30
  401. langchain/chat_models/human.py +0 -23
  402. langchain/chat_models/hunyuan.py +0 -23
  403. langchain/chat_models/javelin_ai_gateway.py +0 -30
  404. langchain/chat_models/jinachat.py +0 -23
  405. langchain/chat_models/konko.py +0 -23
  406. langchain/chat_models/litellm.py +0 -30
  407. langchain/chat_models/meta.py +0 -25
  408. langchain/chat_models/minimax.py +0 -23
  409. langchain/chat_models/mlflow.py +0 -23
  410. langchain/chat_models/mlflow_ai_gateway.py +0 -30
  411. langchain/chat_models/ollama.py +0 -23
  412. langchain/chat_models/openai.py +0 -23
  413. langchain/chat_models/pai_eas_endpoint.py +0 -25
  414. langchain/chat_models/promptlayer_openai.py +0 -25
  415. langchain/chat_models/tongyi.py +0 -23
  416. langchain/chat_models/vertexai.py +0 -23
  417. langchain/chat_models/volcengine_maas.py +0 -30
  418. langchain/chat_models/yandex.py +0 -23
  419. langchain/docstore/__init__.py +0 -48
  420. langchain/docstore/arbitrary_fn.py +0 -23
  421. langchain/docstore/base.py +0 -27
  422. langchain/docstore/document.py +0 -3
  423. langchain/docstore/in_memory.py +0 -23
  424. langchain/docstore/wikipedia.py +0 -23
  425. langchain/document_loaders/__init__.py +0 -553
  426. langchain/document_loaders/acreom.py +0 -23
  427. langchain/document_loaders/airbyte.py +0 -48
  428. langchain/document_loaders/airbyte_json.py +0 -23
  429. langchain/document_loaders/airtable.py +0 -23
  430. langchain/document_loaders/apify_dataset.py +0 -23
  431. langchain/document_loaders/arcgis_loader.py +0 -23
  432. langchain/document_loaders/arxiv.py +0 -23
  433. langchain/document_loaders/assemblyai.py +0 -28
  434. langchain/document_loaders/async_html.py +0 -23
  435. langchain/document_loaders/azlyrics.py +0 -23
  436. langchain/document_loaders/azure_ai_data.py +0 -23
  437. langchain/document_loaders/azure_blob_storage_container.py +0 -25
  438. langchain/document_loaders/azure_blob_storage_file.py +0 -25
  439. langchain/document_loaders/baiducloud_bos_directory.py +0 -29
  440. langchain/document_loaders/baiducloud_bos_file.py +0 -27
  441. langchain/document_loaders/base.py +0 -3
  442. langchain/document_loaders/base_o365.py +0 -23
  443. langchain/document_loaders/bibtex.py +0 -23
  444. langchain/document_loaders/bigquery.py +0 -23
  445. langchain/document_loaders/bilibili.py +0 -23
  446. langchain/document_loaders/blackboard.py +0 -23
  447. langchain/document_loaders/blob_loaders/__init__.py +0 -36
  448. langchain/document_loaders/blob_loaders/file_system.py +0 -23
  449. langchain/document_loaders/blob_loaders/schema.py +0 -29
  450. langchain/document_loaders/blob_loaders/youtube_audio.py +0 -23
  451. langchain/document_loaders/blockchain.py +0 -28
  452. langchain/document_loaders/brave_search.py +0 -23
  453. langchain/document_loaders/browserless.py +0 -23
  454. langchain/document_loaders/chatgpt.py +0 -28
  455. langchain/document_loaders/chromium.py +0 -23
  456. langchain/document_loaders/college_confidential.py +0 -25
  457. langchain/document_loaders/concurrent.py +0 -23
  458. langchain/document_loaders/confluence.py +0 -28
  459. langchain/document_loaders/conllu.py +0 -23
  460. langchain/document_loaders/couchbase.py +0 -23
  461. langchain/document_loaders/csv_loader.py +0 -27
  462. langchain/document_loaders/cube_semantic.py +0 -23
  463. langchain/document_loaders/datadog_logs.py +0 -23
  464. langchain/document_loaders/dataframe.py +0 -28
  465. langchain/document_loaders/diffbot.py +0 -23
  466. langchain/document_loaders/directory.py +0 -23
  467. langchain/document_loaders/discord.py +0 -23
  468. langchain/document_loaders/docugami.py +0 -23
  469. langchain/document_loaders/docusaurus.py +0 -23
  470. langchain/document_loaders/dropbox.py +0 -23
  471. langchain/document_loaders/duckdb_loader.py +0 -23
  472. langchain/document_loaders/email.py +0 -30
  473. langchain/document_loaders/epub.py +0 -23
  474. langchain/document_loaders/etherscan.py +0 -23
  475. langchain/document_loaders/evernote.py +0 -23
  476. langchain/document_loaders/excel.py +0 -23
  477. langchain/document_loaders/facebook_chat.py +0 -28
  478. langchain/document_loaders/fauna.py +0 -23
  479. langchain/document_loaders/figma.py +0 -23
  480. langchain/document_loaders/gcs_directory.py +0 -23
  481. langchain/document_loaders/gcs_file.py +0 -23
  482. langchain/document_loaders/generic.py +0 -23
  483. langchain/document_loaders/geodataframe.py +0 -23
  484. langchain/document_loaders/git.py +0 -23
  485. langchain/document_loaders/gitbook.py +0 -23
  486. langchain/document_loaders/github.py +0 -28
  487. langchain/document_loaders/google_speech_to_text.py +0 -23
  488. langchain/document_loaders/googledrive.py +0 -23
  489. langchain/document_loaders/gutenberg.py +0 -23
  490. langchain/document_loaders/helpers.py +0 -30
  491. langchain/document_loaders/hn.py +0 -23
  492. langchain/document_loaders/html.py +0 -23
  493. langchain/document_loaders/html_bs.py +0 -23
  494. langchain/document_loaders/hugging_face_dataset.py +0 -23
  495. langchain/document_loaders/ifixit.py +0 -23
  496. langchain/document_loaders/image.py +0 -23
  497. langchain/document_loaders/image_captions.py +0 -23
  498. langchain/document_loaders/imsdb.py +0 -23
  499. langchain/document_loaders/iugu.py +0 -23
  500. langchain/document_loaders/joplin.py +0 -23
  501. langchain/document_loaders/json_loader.py +0 -23
  502. langchain/document_loaders/lakefs.py +0 -33
  503. langchain/document_loaders/larksuite.py +0 -23
  504. langchain/document_loaders/markdown.py +0 -25
  505. langchain/document_loaders/mastodon.py +0 -23
  506. langchain/document_loaders/max_compute.py +0 -23
  507. langchain/document_loaders/mediawikidump.py +0 -23
  508. langchain/document_loaders/merge.py +0 -23
  509. langchain/document_loaders/mhtml.py +0 -23
  510. langchain/document_loaders/modern_treasury.py +0 -23
  511. langchain/document_loaders/mongodb.py +0 -23
  512. langchain/document_loaders/news.py +0 -23
  513. langchain/document_loaders/notebook.py +0 -33
  514. langchain/document_loaders/notion.py +0 -23
  515. langchain/document_loaders/notiondb.py +0 -23
  516. langchain/document_loaders/nuclia.py +0 -23
  517. langchain/document_loaders/obs_directory.py +0 -23
  518. langchain/document_loaders/obs_file.py +0 -23
  519. langchain/document_loaders/obsidian.py +0 -23
  520. langchain/document_loaders/odt.py +0 -23
  521. langchain/document_loaders/onedrive.py +0 -23
  522. langchain/document_loaders/onedrive_file.py +0 -23
  523. langchain/document_loaders/onenote.py +0 -23
  524. langchain/document_loaders/open_city_data.py +0 -23
  525. langchain/document_loaders/org_mode.py +0 -25
  526. langchain/document_loaders/parsers/__init__.py +0 -58
  527. langchain/document_loaders/parsers/audio.py +0 -33
  528. langchain/document_loaders/parsers/docai.py +0 -30
  529. langchain/document_loaders/parsers/generic.py +0 -25
  530. langchain/document_loaders/parsers/grobid.py +0 -30
  531. langchain/document_loaders/parsers/html/__init__.py +0 -25
  532. langchain/document_loaders/parsers/html/bs4.py +0 -25
  533. langchain/document_loaders/parsers/language/__init__.py +0 -29
  534. langchain/document_loaders/parsers/language/cobol.py +0 -27
  535. langchain/document_loaders/parsers/language/code_segmenter.py +0 -29
  536. langchain/document_loaders/parsers/language/javascript.py +0 -29
  537. langchain/document_loaders/parsers/language/language_parser.py +0 -29
  538. langchain/document_loaders/parsers/language/python.py +0 -27
  539. langchain/document_loaders/parsers/msword.py +0 -25
  540. langchain/document_loaders/parsers/pdf.py +0 -50
  541. langchain/document_loaders/parsers/registry.py +0 -25
  542. langchain/document_loaders/parsers/txt.py +0 -23
  543. langchain/document_loaders/pdf.py +0 -65
  544. langchain/document_loaders/polars_dataframe.py +0 -23
  545. langchain/document_loaders/powerpoint.py +0 -25
  546. langchain/document_loaders/psychic.py +0 -23
  547. langchain/document_loaders/pubmed.py +0 -23
  548. langchain/document_loaders/pyspark_dataframe.py +0 -26
  549. langchain/document_loaders/python.py +0 -22
  550. langchain/document_loaders/quip.py +0 -23
  551. langchain/document_loaders/readthedocs.py +0 -23
  552. langchain/document_loaders/recursive_url_loader.py +0 -23
  553. langchain/document_loaders/reddit.py +0 -23
  554. langchain/document_loaders/roam.py +0 -23
  555. langchain/document_loaders/rocksetdb.py +0 -23
  556. langchain/document_loaders/rspace.py +0 -23
  557. langchain/document_loaders/rss.py +0 -23
  558. langchain/document_loaders/rst.py +0 -23
  559. langchain/document_loaders/rtf.py +0 -23
  560. langchain/document_loaders/s3_directory.py +0 -23
  561. langchain/document_loaders/s3_file.py +0 -23
  562. langchain/document_loaders/sharepoint.py +0 -23
  563. langchain/document_loaders/sitemap.py +0 -23
  564. langchain/document_loaders/slack_directory.py +0 -23
  565. langchain/document_loaders/snowflake_loader.py +0 -23
  566. langchain/document_loaders/spreedly.py +0 -23
  567. langchain/document_loaders/srt.py +0 -23
  568. langchain/document_loaders/stripe.py +0 -23
  569. langchain/document_loaders/telegram.py +0 -38
  570. langchain/document_loaders/tencent_cos_directory.py +0 -25
  571. langchain/document_loaders/tencent_cos_file.py +0 -23
  572. langchain/document_loaders/tensorflow_datasets.py +0 -23
  573. langchain/document_loaders/text.py +0 -23
  574. langchain/document_loaders/tomarkdown.py +0 -23
  575. langchain/document_loaders/toml.py +0 -23
  576. langchain/document_loaders/trello.py +0 -23
  577. langchain/document_loaders/tsv.py +0 -23
  578. langchain/document_loaders/twitter.py +0 -23
  579. langchain/document_loaders/unstructured.py +0 -54
  580. langchain/document_loaders/url.py +0 -23
  581. langchain/document_loaders/url_playwright.py +0 -33
  582. langchain/document_loaders/url_selenium.py +0 -23
  583. langchain/document_loaders/weather.py +0 -23
  584. langchain/document_loaders/web_base.py +0 -23
  585. langchain/document_loaders/whatsapp_chat.py +0 -28
  586. langchain/document_loaders/wikipedia.py +0 -23
  587. langchain/document_loaders/word_document.py +0 -30
  588. langchain/document_loaders/xml.py +0 -23
  589. langchain/document_loaders/xorbits.py +0 -23
  590. langchain/document_loaders/youtube.py +0 -33
  591. langchain/document_transformers/__init__.py +0 -77
  592. langchain/document_transformers/beautiful_soup_transformer.py +0 -25
  593. langchain/document_transformers/doctran_text_extract.py +0 -25
  594. langchain/document_transformers/doctran_text_qa.py +0 -25
  595. langchain/document_transformers/doctran_text_translate.py +0 -25
  596. langchain/document_transformers/embeddings_redundant_filter.py +0 -50
  597. langchain/document_transformers/google_translate.py +0 -25
  598. langchain/document_transformers/html2text.py +0 -25
  599. langchain/document_transformers/long_context_reorder.py +0 -23
  600. langchain/document_transformers/nuclia_text_transform.py +0 -25
  601. langchain/document_transformers/openai_functions.py +0 -32
  602. langchain/document_transformers/xsl/html_chunks_with_headers.xslt +0 -199
  603. langchain/embeddings/aleph_alpha.py +0 -30
  604. langchain/embeddings/awa.py +0 -23
  605. langchain/embeddings/azure_openai.py +0 -23
  606. langchain/embeddings/baidu_qianfan_endpoint.py +0 -23
  607. langchain/embeddings/bedrock.py +0 -23
  608. langchain/embeddings/bookend.py +0 -23
  609. langchain/embeddings/cache.py +0 -368
  610. langchain/embeddings/clarifai.py +0 -23
  611. langchain/embeddings/cloudflare_workersai.py +0 -29
  612. langchain/embeddings/cohere.py +0 -23
  613. langchain/embeddings/dashscope.py +0 -23
  614. langchain/embeddings/databricks.py +0 -23
  615. langchain/embeddings/deepinfra.py +0 -23
  616. langchain/embeddings/edenai.py +0 -23
  617. langchain/embeddings/elasticsearch.py +0 -23
  618. langchain/embeddings/embaas.py +0 -23
  619. langchain/embeddings/ernie.py +0 -23
  620. langchain/embeddings/fake.py +0 -30
  621. langchain/embeddings/fastembed.py +0 -23
  622. langchain/embeddings/google_palm.py +0 -23
  623. langchain/embeddings/gpt4all.py +0 -23
  624. langchain/embeddings/gradient_ai.py +0 -23
  625. langchain/embeddings/huggingface.py +0 -36
  626. langchain/embeddings/huggingface_hub.py +0 -23
  627. langchain/embeddings/infinity.py +0 -30
  628. langchain/embeddings/javelin_ai_gateway.py +0 -23
  629. langchain/embeddings/jina.py +0 -23
  630. langchain/embeddings/johnsnowlabs.py +0 -23
  631. langchain/embeddings/llamacpp.py +0 -23
  632. langchain/embeddings/llm_rails.py +0 -23
  633. langchain/embeddings/localai.py +0 -23
  634. langchain/embeddings/minimax.py +0 -23
  635. langchain/embeddings/mlflow.py +0 -23
  636. langchain/embeddings/mlflow_gateway.py +0 -23
  637. langchain/embeddings/modelscope_hub.py +0 -23
  638. langchain/embeddings/mosaicml.py +0 -23
  639. langchain/embeddings/nlpcloud.py +0 -23
  640. langchain/embeddings/octoai_embeddings.py +0 -23
  641. langchain/embeddings/ollama.py +0 -23
  642. langchain/embeddings/openai.py +0 -23
  643. langchain/embeddings/sagemaker_endpoint.py +0 -30
  644. langchain/embeddings/self_hosted.py +0 -23
  645. langchain/embeddings/self_hosted_hugging_face.py +0 -30
  646. langchain/embeddings/sentence_transformer.py +0 -21
  647. langchain/embeddings/spacy_embeddings.py +0 -23
  648. langchain/embeddings/tensorflow_hub.py +0 -23
  649. langchain/embeddings/vertexai.py +0 -23
  650. langchain/embeddings/voyageai.py +0 -23
  651. langchain/embeddings/xinference.py +0 -23
  652. langchain/env.py +0 -17
  653. langchain/evaluation/__init__.py +0 -128
  654. langchain/evaluation/agents/__init__.py +0 -5
  655. langchain/evaluation/agents/trajectory_eval_chain.py +0 -415
  656. langchain/evaluation/agents/trajectory_eval_prompt.py +0 -146
  657. langchain/evaluation/comparison/__init__.py +0 -36
  658. langchain/evaluation/comparison/eval_chain.py +0 -461
  659. langchain/evaluation/comparison/prompt.py +0 -59
  660. langchain/evaluation/criteria/__init__.py +0 -56
  661. langchain/evaluation/criteria/eval_chain.py +0 -603
  662. langchain/evaluation/criteria/prompt.py +0 -37
  663. langchain/evaluation/embedding_distance/__init__.py +0 -13
  664. langchain/evaluation/embedding_distance/base.py +0 -602
  665. langchain/evaluation/exact_match/__init__.py +0 -0
  666. langchain/evaluation/exact_match/base.py +0 -97
  667. langchain/evaluation/loading.py +0 -206
  668. langchain/evaluation/parsing/__init__.py +0 -0
  669. langchain/evaluation/parsing/base.py +0 -162
  670. langchain/evaluation/parsing/json_distance.py +0 -97
  671. langchain/evaluation/parsing/json_schema.py +0 -100
  672. langchain/evaluation/qa/__init__.py +0 -10
  673. langchain/evaluation/qa/eval_chain.py +0 -364
  674. langchain/evaluation/qa/eval_prompt.py +0 -78
  675. langchain/evaluation/qa/generate_chain.py +0 -34
  676. langchain/evaluation/qa/generate_prompt.py +0 -21
  677. langchain/evaluation/regex_match/__init__.py +0 -0
  678. langchain/evaluation/regex_match/base.py +0 -86
  679. langchain/evaluation/schema.py +0 -491
  680. langchain/evaluation/scoring/__init__.py +0 -31
  681. langchain/evaluation/scoring/eval_chain.py +0 -475
  682. langchain/evaluation/scoring/prompt.py +0 -53
  683. langchain/evaluation/string_distance/__init__.py +0 -13
  684. langchain/evaluation/string_distance/base.py +0 -466
  685. langchain/example_generator.py +0 -5
  686. langchain/formatting.py +0 -5
  687. langchain/globals.py +0 -180
  688. langchain/graphs/__init__.py +0 -57
  689. langchain/graphs/arangodb_graph.py +0 -28
  690. langchain/graphs/falkordb_graph.py +0 -23
  691. langchain/graphs/graph_document.py +0 -33
  692. langchain/graphs/graph_store.py +0 -23
  693. langchain/graphs/hugegraph.py +0 -23
  694. langchain/graphs/kuzu_graph.py +0 -23
  695. langchain/graphs/memgraph_graph.py +0 -23
  696. langchain/graphs/nebula_graph.py +0 -23
  697. langchain/graphs/neo4j_graph.py +0 -23
  698. langchain/graphs/neptune_graph.py +0 -23
  699. langchain/graphs/networkx_graph.py +0 -36
  700. langchain/graphs/rdf_graph.py +0 -23
  701. langchain/hub.py +0 -131
  702. langchain/indexes/__init__.py +0 -50
  703. langchain/indexes/_api.py +0 -5
  704. langchain/indexes/_sql_record_manager.py +0 -539
  705. langchain/indexes/graph.py +0 -28
  706. langchain/indexes/prompts/__init__.py +0 -13
  707. langchain/indexes/prompts/entity_extraction.py +0 -39
  708. langchain/indexes/prompts/entity_summarization.py +0 -24
  709. langchain/indexes/prompts/knowledge_triplet_extraction.py +0 -36
  710. langchain/indexes/vectorstore.py +0 -269
  711. langchain/input.py +0 -15
  712. langchain/llms/__init__.py +0 -734
  713. langchain/llms/ai21.py +0 -28
  714. langchain/llms/aleph_alpha.py +0 -23
  715. langchain/llms/amazon_api_gateway.py +0 -23
  716. langchain/llms/anthropic.py +0 -23
  717. langchain/llms/anyscale.py +0 -23
  718. langchain/llms/arcee.py +0 -23
  719. langchain/llms/aviary.py +0 -23
  720. langchain/llms/azureml_endpoint.py +0 -48
  721. langchain/llms/baidu_qianfan_endpoint.py +0 -23
  722. langchain/llms/bananadev.py +0 -23
  723. langchain/llms/base.py +0 -20
  724. langchain/llms/baseten.py +0 -23
  725. langchain/llms/beam.py +0 -23
  726. langchain/llms/bedrock.py +0 -28
  727. langchain/llms/bittensor.py +0 -23
  728. langchain/llms/cerebriumai.py +0 -23
  729. langchain/llms/chatglm.py +0 -23
  730. langchain/llms/clarifai.py +0 -23
  731. langchain/llms/cloudflare_workersai.py +0 -25
  732. langchain/llms/cohere.py +0 -23
  733. langchain/llms/ctransformers.py +0 -23
  734. langchain/llms/ctranslate2.py +0 -23
  735. langchain/llms/databricks.py +0 -23
  736. langchain/llms/deepinfra.py +0 -23
  737. langchain/llms/deepsparse.py +0 -23
  738. langchain/llms/edenai.py +0 -23
  739. langchain/llms/fake.py +0 -28
  740. langchain/llms/fireworks.py +0 -23
  741. langchain/llms/forefrontai.py +0 -23
  742. langchain/llms/gigachat.py +0 -23
  743. langchain/llms/google_palm.py +0 -23
  744. langchain/llms/gooseai.py +0 -23
  745. langchain/llms/gpt4all.py +0 -23
  746. langchain/llms/gradient_ai.py +0 -28
  747. langchain/llms/grammars/json.gbnf +0 -29
  748. langchain/llms/grammars/list.gbnf +0 -14
  749. langchain/llms/huggingface_endpoint.py +0 -23
  750. langchain/llms/huggingface_hub.py +0 -23
  751. langchain/llms/huggingface_pipeline.py +0 -23
  752. langchain/llms/huggingface_text_gen_inference.py +0 -23
  753. langchain/llms/human.py +0 -23
  754. langchain/llms/javelin_ai_gateway.py +0 -28
  755. langchain/llms/koboldai.py +0 -23
  756. langchain/llms/llamacpp.py +0 -23
  757. langchain/llms/loading.py +0 -27
  758. langchain/llms/manifest.py +0 -23
  759. langchain/llms/minimax.py +0 -23
  760. langchain/llms/mlflow.py +0 -23
  761. langchain/llms/mlflow_ai_gateway.py +0 -23
  762. langchain/llms/modal.py +0 -23
  763. langchain/llms/mosaicml.py +0 -23
  764. langchain/llms/nlpcloud.py +0 -23
  765. langchain/llms/octoai_endpoint.py +0 -23
  766. langchain/llms/ollama.py +0 -23
  767. langchain/llms/opaqueprompts.py +0 -23
  768. langchain/llms/openai.py +0 -32
  769. langchain/llms/openllm.py +0 -23
  770. langchain/llms/openlm.py +0 -23
  771. langchain/llms/pai_eas_endpoint.py +0 -23
  772. langchain/llms/petals.py +0 -23
  773. langchain/llms/pipelineai.py +0 -23
  774. langchain/llms/predibase.py +0 -23
  775. langchain/llms/predictionguard.py +0 -23
  776. langchain/llms/promptlayer_openai.py +0 -27
  777. langchain/llms/replicate.py +0 -23
  778. langchain/llms/rwkv.py +0 -23
  779. langchain/llms/sagemaker_endpoint.py +0 -28
  780. langchain/llms/self_hosted.py +0 -23
  781. langchain/llms/self_hosted_hugging_face.py +0 -23
  782. langchain/llms/stochasticai.py +0 -23
  783. langchain/llms/symblai_nebula.py +0 -23
  784. langchain/llms/textgen.py +0 -23
  785. langchain/llms/titan_takeoff.py +0 -23
  786. langchain/llms/titan_takeoff_pro.py +0 -23
  787. langchain/llms/together.py +0 -23
  788. langchain/llms/tongyi.py +0 -23
  789. langchain/llms/utils.py +0 -23
  790. langchain/llms/vertexai.py +0 -27
  791. langchain/llms/vllm.py +0 -27
  792. langchain/llms/volcengine_maas.py +0 -28
  793. langchain/llms/watsonxllm.py +0 -23
  794. langchain/llms/writer.py +0 -23
  795. langchain/llms/xinference.py +0 -23
  796. langchain/llms/yandex.py +0 -23
  797. langchain/load/__init__.py +0 -11
  798. langchain/load/dump.py +0 -3
  799. langchain/load/load.py +0 -3
  800. langchain/load/serializable.py +0 -19
  801. langchain/memory/__init__.py +0 -153
  802. langchain/memory/buffer.py +0 -173
  803. langchain/memory/buffer_window.py +0 -60
  804. langchain/memory/chat_memory.py +0 -104
  805. langchain/memory/chat_message_histories/__init__.py +0 -84
  806. langchain/memory/chat_message_histories/astradb.py +0 -25
  807. langchain/memory/chat_message_histories/cassandra.py +0 -25
  808. langchain/memory/chat_message_histories/cosmos_db.py +0 -25
  809. langchain/memory/chat_message_histories/dynamodb.py +0 -25
  810. langchain/memory/chat_message_histories/elasticsearch.py +0 -27
  811. langchain/memory/chat_message_histories/file.py +0 -25
  812. langchain/memory/chat_message_histories/firestore.py +0 -25
  813. langchain/memory/chat_message_histories/in_memory.py +0 -5
  814. langchain/memory/chat_message_histories/momento.py +0 -25
  815. langchain/memory/chat_message_histories/mongodb.py +0 -25
  816. langchain/memory/chat_message_histories/neo4j.py +0 -25
  817. langchain/memory/chat_message_histories/postgres.py +0 -25
  818. langchain/memory/chat_message_histories/redis.py +0 -25
  819. langchain/memory/chat_message_histories/rocksetdb.py +0 -25
  820. langchain/memory/chat_message_histories/singlestoredb.py +0 -27
  821. langchain/memory/chat_message_histories/sql.py +0 -33
  822. langchain/memory/chat_message_histories/streamlit.py +0 -25
  823. langchain/memory/chat_message_histories/upstash_redis.py +0 -27
  824. langchain/memory/chat_message_histories/xata.py +0 -25
  825. langchain/memory/chat_message_histories/zep.py +0 -25
  826. langchain/memory/combined.py +0 -85
  827. langchain/memory/entity.py +0 -564
  828. langchain/memory/kg.py +0 -23
  829. langchain/memory/motorhead_memory.py +0 -23
  830. langchain/memory/prompt.py +0 -164
  831. langchain/memory/readonly.py +0 -24
  832. langchain/memory/simple.py +0 -24
  833. langchain/memory/summary.py +0 -140
  834. langchain/memory/summary_buffer.py +0 -148
  835. langchain/memory/token_buffer.py +0 -72
  836. langchain/memory/utils.py +0 -21
  837. langchain/memory/vectorstore.py +0 -120
  838. langchain/memory/vectorstore_token_buffer_memory.py +0 -184
  839. langchain/memory/zep_memory.py +0 -23
  840. langchain/model_laboratory.py +0 -99
  841. langchain/output_parsers/__init__.py +0 -87
  842. langchain/output_parsers/boolean.py +0 -54
  843. langchain/output_parsers/combining.py +0 -57
  844. langchain/output_parsers/datetime.py +0 -58
  845. langchain/output_parsers/enum.py +0 -41
  846. langchain/output_parsers/ernie_functions.py +0 -45
  847. langchain/output_parsers/fix.py +0 -148
  848. langchain/output_parsers/format_instructions.py +0 -79
  849. langchain/output_parsers/json.py +0 -15
  850. langchain/output_parsers/list.py +0 -13
  851. langchain/output_parsers/loading.py +0 -22
  852. langchain/output_parsers/openai_functions.py +0 -13
  853. langchain/output_parsers/openai_tools.py +0 -7
  854. langchain/output_parsers/pandas_dataframe.py +0 -156
  855. langchain/output_parsers/prompts.py +0 -21
  856. langchain/output_parsers/pydantic.py +0 -3
  857. langchain/output_parsers/rail_parser.py +0 -25
  858. langchain/output_parsers/regex.py +0 -39
  859. langchain/output_parsers/regex_dict.py +0 -43
  860. langchain/output_parsers/retry.py +0 -296
  861. langchain/output_parsers/structured.py +0 -106
  862. langchain/output_parsers/xml.py +0 -3
  863. langchain/output_parsers/yaml.py +0 -73
  864. langchain/prompts/__init__.py +0 -102
  865. langchain/prompts/base.py +0 -21
  866. langchain/prompts/chat.py +0 -37
  867. langchain/prompts/example_selector/__init__.py +0 -42
  868. langchain/prompts/example_selector/base.py +0 -3
  869. langchain/prompts/example_selector/length_based.py +0 -5
  870. langchain/prompts/example_selector/ngram_overlap.py +0 -32
  871. langchain/prompts/example_selector/semantic_similarity.py +0 -11
  872. langchain/prompts/few_shot.py +0 -11
  873. langchain/prompts/few_shot_with_templates.py +0 -3
  874. langchain/prompts/loading.py +0 -23
  875. langchain/prompts/pipeline.py +0 -3
  876. langchain/prompts/prompt.py +0 -6
  877. langchain/pydantic_v1/__init__.py +0 -38
  878. langchain/pydantic_v1/dataclasses.py +0 -20
  879. langchain/pydantic_v1/main.py +0 -20
  880. langchain/python.py +0 -19
  881. langchain/requests.py +0 -35
  882. langchain/retrievers/__init__.py +0 -178
  883. langchain/retrievers/arcee.py +0 -23
  884. langchain/retrievers/arxiv.py +0 -23
  885. langchain/retrievers/azure_ai_search.py +0 -30
  886. langchain/retrievers/bedrock.py +0 -33
  887. langchain/retrievers/bm25.py +0 -28
  888. langchain/retrievers/chaindesk.py +0 -23
  889. langchain/retrievers/chatgpt_plugin_retriever.py +0 -23
  890. langchain/retrievers/cohere_rag_retriever.py +0 -23
  891. langchain/retrievers/contextual_compression.py +0 -81
  892. langchain/retrievers/databerry.py +0 -23
  893. langchain/retrievers/docarray.py +0 -28
  894. langchain/retrievers/document_compressors/__init__.py +0 -44
  895. langchain/retrievers/document_compressors/base.py +0 -82
  896. langchain/retrievers/document_compressors/chain_extract.py +0 -121
  897. langchain/retrievers/document_compressors/chain_extract_prompt.py +0 -10
  898. langchain/retrievers/document_compressors/chain_filter.py +0 -133
  899. langchain/retrievers/document_compressors/chain_filter_prompt.py +0 -8
  900. langchain/retrievers/document_compressors/cohere_rerank.py +0 -124
  901. langchain/retrievers/document_compressors/cross_encoder.py +0 -16
  902. langchain/retrievers/document_compressors/cross_encoder_rerank.py +0 -48
  903. langchain/retrievers/document_compressors/embeddings_filter.py +0 -137
  904. langchain/retrievers/document_compressors/flashrank_rerank.py +0 -27
  905. langchain/retrievers/document_compressors/listwise_rerank.py +0 -144
  906. langchain/retrievers/elastic_search_bm25.py +0 -23
  907. langchain/retrievers/embedchain.py +0 -23
  908. langchain/retrievers/ensemble.py +0 -336
  909. langchain/retrievers/google_cloud_documentai_warehouse.py +0 -25
  910. langchain/retrievers/google_vertex_ai_search.py +0 -33
  911. langchain/retrievers/kay.py +0 -23
  912. langchain/retrievers/kendra.py +0 -66
  913. langchain/retrievers/knn.py +0 -23
  914. langchain/retrievers/llama_index.py +0 -30
  915. langchain/retrievers/merger_retriever.py +0 -123
  916. langchain/retrievers/metal.py +0 -23
  917. langchain/retrievers/milvus.py +0 -28
  918. langchain/retrievers/multi_query.py +0 -231
  919. langchain/retrievers/multi_vector.py +0 -132
  920. langchain/retrievers/outline.py +0 -23
  921. langchain/retrievers/parent_document_retriever.py +0 -157
  922. langchain/retrievers/pinecone_hybrid_search.py +0 -23
  923. langchain/retrievers/pubmed.py +0 -23
  924. langchain/retrievers/pupmed.py +0 -23
  925. langchain/retrievers/re_phraser.py +0 -89
  926. langchain/retrievers/remote_retriever.py +0 -23
  927. langchain/retrievers/self_query/__init__.py +0 -0
  928. langchain/retrievers/self_query/astradb.py +0 -23
  929. langchain/retrievers/self_query/base.py +0 -397
  930. langchain/retrievers/self_query/chroma.py +0 -23
  931. langchain/retrievers/self_query/dashvector.py +0 -23
  932. langchain/retrievers/self_query/databricks_vector_search.py +0 -27
  933. langchain/retrievers/self_query/deeplake.py +0 -27
  934. langchain/retrievers/self_query/dingo.py +0 -23
  935. langchain/retrievers/self_query/elasticsearch.py +0 -25
  936. langchain/retrievers/self_query/milvus.py +0 -27
  937. langchain/retrievers/self_query/mongodb_atlas.py +0 -25
  938. langchain/retrievers/self_query/myscale.py +0 -23
  939. langchain/retrievers/self_query/opensearch.py +0 -23
  940. langchain/retrievers/self_query/pgvector.py +0 -23
  941. langchain/retrievers/self_query/pinecone.py +0 -23
  942. langchain/retrievers/self_query/qdrant.py +0 -23
  943. langchain/retrievers/self_query/redis.py +0 -23
  944. langchain/retrievers/self_query/supabase.py +0 -23
  945. langchain/retrievers/self_query/tencentvectordb.py +0 -27
  946. langchain/retrievers/self_query/timescalevector.py +0 -27
  947. langchain/retrievers/self_query/vectara.py +0 -27
  948. langchain/retrievers/self_query/weaviate.py +0 -23
  949. langchain/retrievers/svm.py +0 -23
  950. langchain/retrievers/tavily_search_api.py +0 -28
  951. langchain/retrievers/tfidf.py +0 -23
  952. langchain/retrievers/time_weighted_retriever.py +0 -193
  953. langchain/retrievers/vespa_retriever.py +0 -23
  954. langchain/retrievers/weaviate_hybrid_search.py +0 -23
  955. langchain/retrievers/web_research.py +0 -29
  956. langchain/retrievers/wikipedia.py +0 -23
  957. langchain/retrievers/you.py +0 -23
  958. langchain/retrievers/zep.py +0 -30
  959. langchain/retrievers/zilliz.py +0 -28
  960. langchain/runnables/__init__.py +0 -18
  961. langchain/runnables/hub.py +0 -32
  962. langchain/runnables/openai_functions.py +0 -51
  963. langchain/schema/__init__.py +0 -82
  964. langchain/schema/agent.py +0 -3
  965. langchain/schema/cache.py +0 -3
  966. langchain/schema/callbacks/__init__.py +0 -0
  967. langchain/schema/callbacks/base.py +0 -23
  968. langchain/schema/callbacks/manager.py +0 -55
  969. langchain/schema/callbacks/stdout.py +0 -3
  970. langchain/schema/callbacks/streaming_stdout.py +0 -3
  971. langchain/schema/callbacks/tracers/__init__.py +0 -0
  972. langchain/schema/callbacks/tracers/base.py +0 -4
  973. langchain/schema/callbacks/tracers/evaluation.py +0 -6
  974. langchain/schema/callbacks/tracers/langchain.py +0 -8
  975. langchain/schema/callbacks/tracers/langchain_v1.py +0 -3
  976. langchain/schema/callbacks/tracers/log_stream.py +0 -9
  977. langchain/schema/callbacks/tracers/root_listeners.py +0 -3
  978. langchain/schema/callbacks/tracers/run_collector.py +0 -3
  979. langchain/schema/callbacks/tracers/schemas.py +0 -27
  980. langchain/schema/callbacks/tracers/stdout.py +0 -13
  981. langchain/schema/chat.py +0 -3
  982. langchain/schema/chat_history.py +0 -3
  983. langchain/schema/document.py +0 -3
  984. langchain/schema/embeddings.py +0 -3
  985. langchain/schema/exceptions.py +0 -3
  986. langchain/schema/language_model.py +0 -15
  987. langchain/schema/memory.py +0 -3
  988. langchain/schema/messages.py +0 -51
  989. langchain/schema/output.py +0 -19
  990. langchain/schema/output_parser.py +0 -25
  991. langchain/schema/prompt.py +0 -3
  992. langchain/schema/prompt_template.py +0 -3
  993. langchain/schema/retriever.py +0 -3
  994. langchain/schema/runnable/__init__.py +0 -58
  995. langchain/schema/runnable/base.py +0 -38
  996. langchain/schema/runnable/branch.py +0 -3
  997. langchain/schema/runnable/config.py +0 -27
  998. langchain/schema/runnable/configurable.py +0 -15
  999. langchain/schema/runnable/fallbacks.py +0 -3
  1000. langchain/schema/runnable/history.py +0 -11
  1001. langchain/schema/runnable/passthrough.py +0 -8
  1002. langchain/schema/runnable/retry.py +0 -3
  1003. langchain/schema/runnable/router.py +0 -3
  1004. langchain/schema/runnable/utils.py +0 -51
  1005. langchain/schema/storage.py +0 -3
  1006. langchain/schema/vectorstore.py +0 -3
  1007. langchain/serpapi.py +0 -25
  1008. langchain/smith/__init__.py +0 -102
  1009. langchain/smith/evaluation/__init__.py +0 -68
  1010. langchain/smith/evaluation/config.py +0 -382
  1011. langchain/smith/evaluation/name_generation.py +0 -727
  1012. langchain/smith/evaluation/progress.py +0 -137
  1013. langchain/smith/evaluation/runner_utils.py +0 -1572
  1014. langchain/smith/evaluation/string_run_evaluator.py +0 -440
  1015. langchain/smith/evaluation/utils.py +0 -0
  1016. langchain/sql_database.py +0 -25
  1017. langchain/storage/__init__.py +0 -57
  1018. langchain/storage/_lc_store.py +0 -91
  1019. langchain/storage/encoder_backed.py +0 -127
  1020. langchain/storage/exceptions.py +0 -3
  1021. langchain/storage/file_system.py +0 -176
  1022. langchain/storage/in_memory.py +0 -13
  1023. langchain/storage/redis.py +0 -23
  1024. langchain/storage/upstash_redis.py +0 -27
  1025. langchain/text_splitter.py +0 -50
  1026. langchain/tools/ainetwork/__init__.py +0 -0
  1027. langchain/tools/ainetwork/app.py +0 -30
  1028. langchain/tools/ainetwork/base.py +0 -27
  1029. langchain/tools/ainetwork/owner.py +0 -28
  1030. langchain/tools/ainetwork/rule.py +0 -28
  1031. langchain/tools/ainetwork/transfer.py +0 -28
  1032. langchain/tools/ainetwork/value.py +0 -28
  1033. langchain/tools/amadeus/__init__.py +0 -30
  1034. langchain/tools/amadeus/base.py +0 -23
  1035. langchain/tools/amadeus/closest_airport.py +0 -30
  1036. langchain/tools/amadeus/flight_search.py +0 -30
  1037. langchain/tools/arxiv/__init__.py +0 -1
  1038. langchain/tools/arxiv/tool.py +0 -28
  1039. langchain/tools/azure_cognitive_services/__init__.py +0 -41
  1040. langchain/tools/azure_cognitive_services/form_recognizer.py +0 -23
  1041. langchain/tools/azure_cognitive_services/image_analysis.py +0 -23
  1042. langchain/tools/azure_cognitive_services/speech2text.py +0 -23
  1043. langchain/tools/azure_cognitive_services/text2speech.py +0 -23
  1044. langchain/tools/azure_cognitive_services/text_analytics_health.py +0 -23
  1045. langchain/tools/base.py +0 -19
  1046. langchain/tools/bearly/__init__.py +0 -0
  1047. langchain/tools/bearly/tool.py +0 -33
  1048. langchain/tools/bing_search/__init__.py +0 -29
  1049. langchain/tools/bing_search/tool.py +0 -27
  1050. langchain/tools/brave_search/__init__.py +0 -0
  1051. langchain/tools/brave_search/tool.py +0 -23
  1052. langchain/tools/clickup/__init__.py +0 -0
  1053. langchain/tools/clickup/tool.py +0 -23
  1054. langchain/tools/convert_to_openai.py +0 -4
  1055. langchain/tools/dataforseo_api_search/__init__.py +0 -34
  1056. langchain/tools/dataforseo_api_search/tool.py +0 -32
  1057. langchain/tools/ddg_search/__init__.py +0 -25
  1058. langchain/tools/ddg_search/tool.py +0 -32
  1059. langchain/tools/e2b_data_analysis/__init__.py +0 -0
  1060. langchain/tools/e2b_data_analysis/tool.py +0 -33
  1061. langchain/tools/edenai/__init__.py +0 -50
  1062. langchain/tools/edenai/audio_speech_to_text.py +0 -23
  1063. langchain/tools/edenai/audio_text_to_speech.py +0 -23
  1064. langchain/tools/edenai/edenai_base_tool.py +0 -23
  1065. langchain/tools/edenai/image_explicitcontent.py +0 -23
  1066. langchain/tools/edenai/image_objectdetection.py +0 -23
  1067. langchain/tools/edenai/ocr_identityparser.py +0 -23
  1068. langchain/tools/edenai/ocr_invoiceparser.py +0 -23
  1069. langchain/tools/edenai/text_moderation.py +0 -23
  1070. langchain/tools/eleven_labs/__init__.py +0 -25
  1071. langchain/tools/eleven_labs/models.py +0 -23
  1072. langchain/tools/eleven_labs/text2speech.py +0 -23
  1073. langchain/tools/file_management/__init__.py +0 -47
  1074. langchain/tools/file_management/copy.py +0 -28
  1075. langchain/tools/file_management/delete.py +0 -28
  1076. langchain/tools/file_management/file_search.py +0 -28
  1077. langchain/tools/file_management/list_dir.py +0 -28
  1078. langchain/tools/file_management/move.py +0 -28
  1079. langchain/tools/file_management/read.py +0 -28
  1080. langchain/tools/file_management/write.py +0 -28
  1081. langchain/tools/github/__init__.py +0 -1
  1082. langchain/tools/github/tool.py +0 -23
  1083. langchain/tools/gitlab/__init__.py +0 -1
  1084. langchain/tools/gitlab/tool.py +0 -23
  1085. langchain/tools/gmail/__init__.py +0 -41
  1086. langchain/tools/gmail/base.py +0 -23
  1087. langchain/tools/gmail/create_draft.py +0 -28
  1088. langchain/tools/gmail/get_message.py +0 -28
  1089. langchain/tools/gmail/get_thread.py +0 -28
  1090. langchain/tools/gmail/search.py +0 -30
  1091. langchain/tools/gmail/send_message.py +0 -28
  1092. langchain/tools/golden_query/__init__.py +0 -25
  1093. langchain/tools/golden_query/tool.py +0 -23
  1094. langchain/tools/google_cloud/__init__.py +0 -25
  1095. langchain/tools/google_cloud/texttospeech.py +0 -23
  1096. langchain/tools/google_finance/__init__.py +0 -27
  1097. langchain/tools/google_finance/tool.py +0 -25
  1098. langchain/tools/google_jobs/__init__.py +0 -25
  1099. langchain/tools/google_jobs/tool.py +0 -23
  1100. langchain/tools/google_lens/__init__.py +0 -25
  1101. langchain/tools/google_lens/tool.py +0 -23
  1102. langchain/tools/google_places/__init__.py +0 -25
  1103. langchain/tools/google_places/tool.py +0 -28
  1104. langchain/tools/google_scholar/__init__.py +0 -27
  1105. langchain/tools/google_scholar/tool.py +0 -25
  1106. langchain/tools/google_search/__init__.py +0 -29
  1107. langchain/tools/google_search/tool.py +0 -27
  1108. langchain/tools/google_serper/__init__.py +0 -30
  1109. langchain/tools/google_serper/tool.py +0 -27
  1110. langchain/tools/google_trends/__init__.py +0 -27
  1111. langchain/tools/google_trends/tool.py +0 -25
  1112. langchain/tools/graphql/__init__.py +0 -1
  1113. langchain/tools/graphql/tool.py +0 -23
  1114. langchain/tools/human/__init__.py +0 -25
  1115. langchain/tools/human/tool.py +0 -23
  1116. langchain/tools/ifttt.py +0 -23
  1117. langchain/tools/interaction/__init__.py +0 -1
  1118. langchain/tools/interaction/tool.py +0 -23
  1119. langchain/tools/jira/__init__.py +0 -1
  1120. langchain/tools/jira/tool.py +0 -42
  1121. langchain/tools/json/__init__.py +0 -1
  1122. langchain/tools/json/tool.py +0 -52
  1123. langchain/tools/memorize/__init__.py +0 -25
  1124. langchain/tools/memorize/tool.py +0 -27
  1125. langchain/tools/merriam_webster/__init__.py +0 -1
  1126. langchain/tools/merriam_webster/tool.py +0 -23
  1127. langchain/tools/metaphor_search/__init__.py +0 -25
  1128. langchain/tools/metaphor_search/tool.py +0 -23
  1129. langchain/tools/multion/__init__.py +0 -33
  1130. langchain/tools/multion/close_session.py +0 -30
  1131. langchain/tools/multion/create_session.py +0 -30
  1132. langchain/tools/multion/update_session.py +0 -30
  1133. langchain/tools/nasa/__init__.py +0 -0
  1134. langchain/tools/nasa/tool.py +0 -23
  1135. langchain/tools/nuclia/__init__.py +0 -23
  1136. langchain/tools/nuclia/tool.py +0 -27
  1137. langchain/tools/office365/__init__.py +0 -41
  1138. langchain/tools/office365/base.py +0 -23
  1139. langchain/tools/office365/create_draft_message.py +0 -32
  1140. langchain/tools/office365/events_search.py +0 -28
  1141. langchain/tools/office365/messages_search.py +0 -28
  1142. langchain/tools/office365/send_event.py +0 -28
  1143. langchain/tools/office365/send_message.py +0 -28
  1144. langchain/tools/openapi/__init__.py +0 -0
  1145. langchain/tools/openapi/utils/__init__.py +0 -0
  1146. langchain/tools/openapi/utils/api_models.py +0 -54
  1147. langchain/tools/openapi/utils/openapi_utils.py +0 -30
  1148. langchain/tools/openweathermap/__init__.py +0 -25
  1149. langchain/tools/openweathermap/tool.py +0 -23
  1150. langchain/tools/playwright/__init__.py +0 -47
  1151. langchain/tools/playwright/base.py +0 -23
  1152. langchain/tools/playwright/click.py +0 -28
  1153. langchain/tools/playwright/current_page.py +0 -23
  1154. langchain/tools/playwright/extract_hyperlinks.py +0 -32
  1155. langchain/tools/playwright/extract_text.py +0 -23
  1156. langchain/tools/playwright/get_elements.py +0 -28
  1157. langchain/tools/playwright/navigate.py +0 -28
  1158. langchain/tools/playwright/navigate_back.py +0 -23
  1159. langchain/tools/plugin.py +0 -32
  1160. langchain/tools/powerbi/__init__.py +0 -1
  1161. langchain/tools/powerbi/tool.py +0 -33
  1162. langchain/tools/pubmed/__init__.py +0 -1
  1163. langchain/tools/pubmed/tool.py +0 -23
  1164. langchain/tools/python/__init__.py +0 -13
  1165. langchain/tools/reddit_search/__init__.py +0 -0
  1166. langchain/tools/reddit_search/tool.py +0 -27
  1167. langchain/tools/render.py +0 -23
  1168. langchain/tools/requests/__init__.py +0 -1
  1169. langchain/tools/requests/tool.py +0 -42
  1170. langchain/tools/retriever.py +0 -11
  1171. langchain/tools/scenexplain/__init__.py +0 -1
  1172. langchain/tools/scenexplain/tool.py +0 -28
  1173. langchain/tools/searchapi/__init__.py +0 -30
  1174. langchain/tools/searchapi/tool.py +0 -27
  1175. langchain/tools/searx_search/__init__.py +0 -0
  1176. langchain/tools/searx_search/tool.py +0 -27
  1177. langchain/tools/shell/__init__.py +0 -25
  1178. langchain/tools/shell/tool.py +0 -28
  1179. langchain/tools/slack/__init__.py +0 -38
  1180. langchain/tools/slack/base.py +0 -23
  1181. langchain/tools/slack/get_channel.py +0 -23
  1182. langchain/tools/slack/get_message.py +0 -28
  1183. langchain/tools/slack/schedule_message.py +0 -28
  1184. langchain/tools/slack/send_message.py +0 -28
  1185. langchain/tools/sleep/__init__.py +0 -1
  1186. langchain/tools/sleep/tool.py +0 -28
  1187. langchain/tools/spark_sql/__init__.py +0 -1
  1188. langchain/tools/spark_sql/tool.py +0 -39
  1189. langchain/tools/sql_database/__init__.py +0 -1
  1190. langchain/tools/sql_database/prompt.py +0 -24
  1191. langchain/tools/sql_database/tool.py +0 -39
  1192. langchain/tools/stackexchange/__init__.py +0 -1
  1193. langchain/tools/stackexchange/tool.py +0 -23
  1194. langchain/tools/steam/__init__.py +0 -1
  1195. langchain/tools/steam/tool.py +0 -23
  1196. langchain/tools/steamship_image_generation/__init__.py +0 -25
  1197. langchain/tools/steamship_image_generation/tool.py +0 -28
  1198. langchain/tools/tavily_search/__init__.py +0 -32
  1199. langchain/tools/tavily_search/tool.py +0 -33
  1200. langchain/tools/vectorstore/__init__.py +0 -1
  1201. langchain/tools/vectorstore/tool.py +0 -30
  1202. langchain/tools/wikipedia/__init__.py +0 -1
  1203. langchain/tools/wikipedia/tool.py +0 -23
  1204. langchain/tools/wolfram_alpha/__init__.py +0 -25
  1205. langchain/tools/wolfram_alpha/tool.py +0 -23
  1206. langchain/tools/yahoo_finance_news.py +0 -23
  1207. langchain/tools/youtube/__init__.py +0 -0
  1208. langchain/tools/youtube/search.py +0 -23
  1209. langchain/tools/zapier/__init__.py +0 -29
  1210. langchain/tools/zapier/tool.py +0 -49
  1211. langchain/utilities/__init__.py +0 -168
  1212. langchain/utilities/alpha_vantage.py +0 -23
  1213. langchain/utilities/anthropic.py +0 -30
  1214. langchain/utilities/apify.py +0 -23
  1215. langchain/utilities/arcee.py +0 -45
  1216. langchain/utilities/arxiv.py +0 -23
  1217. langchain/utilities/asyncio.py +0 -11
  1218. langchain/utilities/awslambda.py +0 -23
  1219. langchain/utilities/bibtex.py +0 -23
  1220. langchain/utilities/bing_search.py +0 -23
  1221. langchain/utilities/brave_search.py +0 -23
  1222. langchain/utilities/clickup.py +0 -45
  1223. langchain/utilities/dalle_image_generator.py +0 -25
  1224. langchain/utilities/dataforseo_api_search.py +0 -25
  1225. langchain/utilities/duckduckgo_search.py +0 -23
  1226. langchain/utilities/github.py +0 -23
  1227. langchain/utilities/gitlab.py +0 -23
  1228. langchain/utilities/golden_query.py +0 -23
  1229. langchain/utilities/google_finance.py +0 -23
  1230. langchain/utilities/google_jobs.py +0 -23
  1231. langchain/utilities/google_lens.py +0 -23
  1232. langchain/utilities/google_places_api.py +0 -23
  1233. langchain/utilities/google_scholar.py +0 -23
  1234. langchain/utilities/google_search.py +0 -23
  1235. langchain/utilities/google_serper.py +0 -23
  1236. langchain/utilities/google_trends.py +0 -23
  1237. langchain/utilities/graphql.py +0 -23
  1238. langchain/utilities/jira.py +0 -23
  1239. langchain/utilities/loading.py +0 -4
  1240. langchain/utilities/max_compute.py +0 -23
  1241. langchain/utilities/merriam_webster.py +0 -23
  1242. langchain/utilities/metaphor_search.py +0 -23
  1243. langchain/utilities/nasa.py +0 -23
  1244. langchain/utilities/opaqueprompts.py +0 -27
  1245. langchain/utilities/openapi.py +0 -28
  1246. langchain/utilities/openweathermap.py +0 -23
  1247. langchain/utilities/outline.py +0 -23
  1248. langchain/utilities/portkey.py +0 -23
  1249. langchain/utilities/powerbi.py +0 -23
  1250. langchain/utilities/pubmed.py +0 -23
  1251. langchain/utilities/python.py +0 -19
  1252. langchain/utilities/reddit_search.py +0 -25
  1253. langchain/utilities/redis.py +0 -33
  1254. langchain/utilities/requests.py +0 -27
  1255. langchain/utilities/scenexplain.py +0 -23
  1256. langchain/utilities/searchapi.py +0 -23
  1257. langchain/utilities/searx_search.py +0 -28
  1258. langchain/utilities/serpapi.py +0 -28
  1259. langchain/utilities/spark_sql.py +0 -23
  1260. langchain/utilities/sql_database.py +0 -28
  1261. langchain/utilities/stackexchange.py +0 -23
  1262. langchain/utilities/steam.py +0 -23
  1263. langchain/utilities/tavily_search.py +0 -25
  1264. langchain/utilities/tensorflow_datasets.py +0 -23
  1265. langchain/utilities/twilio.py +0 -23
  1266. langchain/utilities/vertexai.py +0 -36
  1267. langchain/utilities/wikipedia.py +0 -23
  1268. langchain/utilities/wolfram_alpha.py +0 -23
  1269. langchain/utilities/zapier.py +0 -23
  1270. langchain/utils/__init__.py +0 -77
  1271. langchain/utils/aiter.py +0 -3
  1272. langchain/utils/env.py +0 -3
  1273. langchain/utils/ernie_functions.py +0 -36
  1274. langchain/utils/formatting.py +0 -3
  1275. langchain/utils/html.py +0 -19
  1276. langchain/utils/input.py +0 -8
  1277. langchain/utils/iter.py +0 -3
  1278. langchain/utils/json_schema.py +0 -11
  1279. langchain/utils/loading.py +0 -3
  1280. langchain/utils/math.py +0 -32
  1281. langchain/utils/openai.py +0 -23
  1282. langchain/utils/openai_functions.py +0 -13
  1283. langchain/utils/pydantic.py +0 -3
  1284. langchain/utils/strings.py +0 -3
  1285. langchain/utils/utils.py +0 -21
  1286. langchain/vectorstores/__init__.py +0 -262
  1287. langchain/vectorstores/alibabacloud_opensearch.py +0 -30
  1288. langchain/vectorstores/analyticdb.py +0 -23
  1289. langchain/vectorstores/annoy.py +0 -23
  1290. langchain/vectorstores/astradb.py +0 -23
  1291. langchain/vectorstores/atlas.py +0 -23
  1292. langchain/vectorstores/awadb.py +0 -23
  1293. langchain/vectorstores/azure_cosmos_db.py +0 -28
  1294. langchain/vectorstores/azuresearch.py +0 -30
  1295. langchain/vectorstores/bageldb.py +0 -23
  1296. langchain/vectorstores/baiducloud_vector_search.py +0 -23
  1297. langchain/vectorstores/base.py +0 -3
  1298. langchain/vectorstores/cassandra.py +0 -23
  1299. langchain/vectorstores/chroma.py +0 -23
  1300. langchain/vectorstores/clarifai.py +0 -23
  1301. langchain/vectorstores/clickhouse.py +0 -27
  1302. langchain/vectorstores/dashvector.py +0 -23
  1303. langchain/vectorstores/databricks_vector_search.py +0 -23
  1304. langchain/vectorstores/deeplake.py +0 -23
  1305. langchain/vectorstores/dingo.py +0 -23
  1306. langchain/vectorstores/docarray/__init__.py +0 -30
  1307. langchain/vectorstores/docarray/base.py +0 -23
  1308. langchain/vectorstores/docarray/hnsw.py +0 -23
  1309. langchain/vectorstores/docarray/in_memory.py +0 -23
  1310. langchain/vectorstores/elastic_vector_search.py +0 -27
  1311. langchain/vectorstores/elasticsearch.py +0 -39
  1312. langchain/vectorstores/epsilla.py +0 -23
  1313. langchain/vectorstores/faiss.py +0 -23
  1314. langchain/vectorstores/hippo.py +0 -23
  1315. langchain/vectorstores/hologres.py +0 -23
  1316. langchain/vectorstores/lancedb.py +0 -23
  1317. langchain/vectorstores/llm_rails.py +0 -28
  1318. langchain/vectorstores/marqo.py +0 -23
  1319. langchain/vectorstores/matching_engine.py +0 -23
  1320. langchain/vectorstores/meilisearch.py +0 -23
  1321. langchain/vectorstores/milvus.py +0 -23
  1322. langchain/vectorstores/momento_vector_index.py +0 -23
  1323. langchain/vectorstores/mongodb_atlas.py +0 -23
  1324. langchain/vectorstores/myscale.py +0 -30
  1325. langchain/vectorstores/neo4j_vector.py +0 -28
  1326. langchain/vectorstores/nucliadb.py +0 -23
  1327. langchain/vectorstores/opensearch_vector_search.py +0 -23
  1328. langchain/vectorstores/pgembedding.py +0 -36
  1329. langchain/vectorstores/pgvecto_rs.py +0 -23
  1330. langchain/vectorstores/pgvector.py +0 -28
  1331. langchain/vectorstores/pinecone.py +0 -23
  1332. langchain/vectorstores/qdrant.py +0 -28
  1333. langchain/vectorstores/redis/__init__.py +0 -42
  1334. langchain/vectorstores/redis/base.py +0 -33
  1335. langchain/vectorstores/redis/filters.py +0 -48
  1336. langchain/vectorstores/redis/schema.py +0 -54
  1337. langchain/vectorstores/rocksetdb.py +0 -23
  1338. langchain/vectorstores/scann.py +0 -23
  1339. langchain/vectorstores/semadb.py +0 -23
  1340. langchain/vectorstores/singlestoredb.py +0 -23
  1341. langchain/vectorstores/sklearn.py +0 -42
  1342. langchain/vectorstores/sqlitevss.py +0 -23
  1343. langchain/vectorstores/starrocks.py +0 -28
  1344. langchain/vectorstores/supabase.py +0 -23
  1345. langchain/vectorstores/tair.py +0 -23
  1346. langchain/vectorstores/tencentvectordb.py +0 -33
  1347. langchain/vectorstores/tigris.py +0 -23
  1348. langchain/vectorstores/tiledb.py +0 -23
  1349. langchain/vectorstores/timescalevector.py +0 -23
  1350. langchain/vectorstores/typesense.py +0 -23
  1351. langchain/vectorstores/usearch.py +0 -23
  1352. langchain/vectorstores/utils.py +0 -33
  1353. langchain/vectorstores/vald.py +0 -23
  1354. langchain/vectorstores/vearch.py +0 -23
  1355. langchain/vectorstores/vectara.py +0 -28
  1356. langchain/vectorstores/vespa.py +0 -23
  1357. langchain/vectorstores/weaviate.py +0 -23
  1358. langchain/vectorstores/xata.py +0 -23
  1359. langchain/vectorstores/yellowbrick.py +0 -23
  1360. langchain/vectorstores/zep.py +0 -28
  1361. langchain/vectorstores/zilliz.py +0 -23
  1362. langchain-0.3.27.dist-info/METADATA +0 -144
  1363. langchain-0.3.27.dist-info/RECORD +0 -1342
  1364. langchain-0.3.27.dist-info/entry_points.txt +0 -4
  1365. {langchain-0.3.27.dist-info → langchain-1.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,1582 @@
1
+ """Agent factory for creating agents with middleware support."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import itertools
6
+ from typing import (
7
+ TYPE_CHECKING,
8
+ Annotated,
9
+ Any,
10
+ cast,
11
+ get_args,
12
+ get_origin,
13
+ get_type_hints,
14
+ )
15
+
16
+ from langchain_core.language_models.chat_models import BaseChatModel
17
+ from langchain_core.messages import AIMessage, AnyMessage, SystemMessage, ToolMessage
18
+ from langchain_core.tools import BaseTool
19
+ from langgraph._internal._runnable import RunnableCallable
20
+ from langgraph.constants import END, START
21
+ from langgraph.graph.state import StateGraph
22
+ from langgraph.runtime import Runtime # noqa: TC002
23
+ from langgraph.types import Command, Send
24
+ from langgraph.typing import ContextT # noqa: TC002
25
+ from typing_extensions import NotRequired, Required, TypedDict, TypeVar
26
+
27
+ from langchain.agents.middleware.types import (
28
+ AgentMiddleware,
29
+ AgentState,
30
+ JumpTo,
31
+ ModelRequest,
32
+ ModelResponse,
33
+ OmitFromSchema,
34
+ _InputAgentState,
35
+ _OutputAgentState,
36
+ )
37
+ from langchain.agents.structured_output import (
38
+ AutoStrategy,
39
+ MultipleStructuredOutputsError,
40
+ OutputToolBinding,
41
+ ProviderStrategy,
42
+ ProviderStrategyBinding,
43
+ ResponseFormat,
44
+ StructuredOutputValidationError,
45
+ ToolStrategy,
46
+ )
47
+ from langchain.chat_models import init_chat_model
48
+ from langchain.tools.tool_node import ToolCallWithContext, _ToolNode
49
+
50
+ if TYPE_CHECKING:
51
+ from collections.abc import Awaitable, Callable, Sequence
52
+
53
+ from langchain_core.runnables import Runnable
54
+ from langgraph.cache.base import BaseCache
55
+ from langgraph.graph.state import CompiledStateGraph
56
+ from langgraph.store.base import BaseStore
57
+ from langgraph.types import Checkpointer
58
+
59
+ from langchain.tools.tool_node import ToolCallRequest, ToolCallWrapper
60
+
61
+ STRUCTURED_OUTPUT_ERROR_TEMPLATE = "Error: {error}\n Please fix your mistakes."
62
+
63
+ ResponseT = TypeVar("ResponseT")
64
+
65
+
66
+ def _normalize_to_model_response(result: ModelResponse | AIMessage) -> ModelResponse:
67
+ """Normalize middleware return value to ModelResponse."""
68
+ if isinstance(result, AIMessage):
69
+ return ModelResponse(result=[result], structured_response=None)
70
+ return result
71
+
72
+
73
+ def _chain_model_call_handlers(
74
+ handlers: Sequence[
75
+ Callable[
76
+ [ModelRequest, Callable[[ModelRequest], ModelResponse]],
77
+ ModelResponse | AIMessage,
78
+ ]
79
+ ],
80
+ ) -> (
81
+ Callable[
82
+ [ModelRequest, Callable[[ModelRequest], ModelResponse]],
83
+ ModelResponse,
84
+ ]
85
+ | None
86
+ ):
87
+ """Compose multiple wrap_model_call handlers into single middleware stack.
88
+
89
+ Composes handlers so first in list becomes outermost layer. Each handler
90
+ receives a handler callback to execute inner layers.
91
+
92
+ Args:
93
+ handlers: List of handlers. First handler wraps all others.
94
+
95
+ Returns:
96
+ Composed handler, or `None` if handlers empty.
97
+
98
+ Example:
99
+ ```python
100
+ # handlers=[auth, retry] means: auth wraps retry
101
+ # Flow: auth calls retry, retry calls base handler
102
+ def auth(req, state, runtime, handler):
103
+ try:
104
+ return handler(req)
105
+ except UnauthorizedError:
106
+ refresh_token()
107
+ return handler(req)
108
+
109
+
110
+ def retry(req, state, runtime, handler):
111
+ for attempt in range(3):
112
+ try:
113
+ return handler(req)
114
+ except Exception:
115
+ if attempt == 2:
116
+ raise
117
+
118
+
119
+ handler = _chain_model_call_handlers([auth, retry])
120
+ ```
121
+ """
122
+ if not handlers:
123
+ return None
124
+
125
+ if len(handlers) == 1:
126
+ # Single handler - wrap to normalize output
127
+ single_handler = handlers[0]
128
+
129
+ def normalized_single(
130
+ request: ModelRequest,
131
+ handler: Callable[[ModelRequest], ModelResponse],
132
+ ) -> ModelResponse:
133
+ result = single_handler(request, handler)
134
+ return _normalize_to_model_response(result)
135
+
136
+ return normalized_single
137
+
138
+ def compose_two(
139
+ outer: Callable[
140
+ [ModelRequest, Callable[[ModelRequest], ModelResponse]],
141
+ ModelResponse | AIMessage,
142
+ ],
143
+ inner: Callable[
144
+ [ModelRequest, Callable[[ModelRequest], ModelResponse]],
145
+ ModelResponse | AIMessage,
146
+ ],
147
+ ) -> Callable[
148
+ [ModelRequest, Callable[[ModelRequest], ModelResponse]],
149
+ ModelResponse,
150
+ ]:
151
+ """Compose two handlers where outer wraps inner."""
152
+
153
+ def composed(
154
+ request: ModelRequest,
155
+ handler: Callable[[ModelRequest], ModelResponse],
156
+ ) -> ModelResponse:
157
+ # Create a wrapper that calls inner with the base handler and normalizes
158
+ def inner_handler(req: ModelRequest) -> ModelResponse:
159
+ inner_result = inner(req, handler)
160
+ return _normalize_to_model_response(inner_result)
161
+
162
+ # Call outer with the wrapped inner as its handler and normalize
163
+ outer_result = outer(request, inner_handler)
164
+ return _normalize_to_model_response(outer_result)
165
+
166
+ return composed
167
+
168
+ # Compose right-to-left: outer(inner(innermost(handler)))
169
+ result = handlers[-1]
170
+ for handler in reversed(handlers[:-1]):
171
+ result = compose_two(handler, result)
172
+
173
+ # Wrap to ensure final return type is exactly ModelResponse
174
+ def final_normalized(
175
+ request: ModelRequest,
176
+ handler: Callable[[ModelRequest], ModelResponse],
177
+ ) -> ModelResponse:
178
+ # result here is typed as returning ModelResponse | AIMessage but compose_two normalizes
179
+ final_result = result(request, handler)
180
+ return _normalize_to_model_response(final_result)
181
+
182
+ return final_normalized
183
+
184
+
185
+ def _chain_async_model_call_handlers(
186
+ handlers: Sequence[
187
+ Callable[
188
+ [ModelRequest, Callable[[ModelRequest], Awaitable[ModelResponse]]],
189
+ Awaitable[ModelResponse | AIMessage],
190
+ ]
191
+ ],
192
+ ) -> (
193
+ Callable[
194
+ [ModelRequest, Callable[[ModelRequest], Awaitable[ModelResponse]]],
195
+ Awaitable[ModelResponse],
196
+ ]
197
+ | None
198
+ ):
199
+ """Compose multiple async `wrap_model_call` handlers into single middleware stack.
200
+
201
+ Args:
202
+ handlers: List of async handlers. First handler wraps all others.
203
+
204
+ Returns:
205
+ Composed async handler, or `None` if handlers empty.
206
+ """
207
+ if not handlers:
208
+ return None
209
+
210
+ if len(handlers) == 1:
211
+ # Single handler - wrap to normalize output
212
+ single_handler = handlers[0]
213
+
214
+ async def normalized_single(
215
+ request: ModelRequest,
216
+ handler: Callable[[ModelRequest], Awaitable[ModelResponse]],
217
+ ) -> ModelResponse:
218
+ result = await single_handler(request, handler)
219
+ return _normalize_to_model_response(result)
220
+
221
+ return normalized_single
222
+
223
+ def compose_two(
224
+ outer: Callable[
225
+ [ModelRequest, Callable[[ModelRequest], Awaitable[ModelResponse]]],
226
+ Awaitable[ModelResponse | AIMessage],
227
+ ],
228
+ inner: Callable[
229
+ [ModelRequest, Callable[[ModelRequest], Awaitable[ModelResponse]]],
230
+ Awaitable[ModelResponse | AIMessage],
231
+ ],
232
+ ) -> Callable[
233
+ [ModelRequest, Callable[[ModelRequest], Awaitable[ModelResponse]]],
234
+ Awaitable[ModelResponse],
235
+ ]:
236
+ """Compose two async handlers where outer wraps inner."""
237
+
238
+ async def composed(
239
+ request: ModelRequest,
240
+ handler: Callable[[ModelRequest], Awaitable[ModelResponse]],
241
+ ) -> ModelResponse:
242
+ # Create a wrapper that calls inner with the base handler and normalizes
243
+ async def inner_handler(req: ModelRequest) -> ModelResponse:
244
+ inner_result = await inner(req, handler)
245
+ return _normalize_to_model_response(inner_result)
246
+
247
+ # Call outer with the wrapped inner as its handler and normalize
248
+ outer_result = await outer(request, inner_handler)
249
+ return _normalize_to_model_response(outer_result)
250
+
251
+ return composed
252
+
253
+ # Compose right-to-left: outer(inner(innermost(handler)))
254
+ result = handlers[-1]
255
+ for handler in reversed(handlers[:-1]):
256
+ result = compose_two(handler, result)
257
+
258
+ # Wrap to ensure final return type is exactly ModelResponse
259
+ async def final_normalized(
260
+ request: ModelRequest,
261
+ handler: Callable[[ModelRequest], Awaitable[ModelResponse]],
262
+ ) -> ModelResponse:
263
+ # result here is typed as returning ModelResponse | AIMessage but compose_two normalizes
264
+ final_result = await result(request, handler)
265
+ return _normalize_to_model_response(final_result)
266
+
267
+ return final_normalized
268
+
269
+
270
+ def _resolve_schema(schemas: set[type], schema_name: str, omit_flag: str | None = None) -> type:
271
+ """Resolve schema by merging schemas and optionally respecting `OmitFromSchema` annotations.
272
+
273
+ Args:
274
+ schemas: List of schema types to merge
275
+ schema_name: Name for the generated `TypedDict`
276
+ omit_flag: If specified, omit fields with this flag set (`'input'` or
277
+ `'output'`)
278
+ """
279
+ all_annotations = {}
280
+
281
+ for schema in schemas:
282
+ hints = get_type_hints(schema, include_extras=True)
283
+
284
+ for field_name, field_type in hints.items():
285
+ should_omit = False
286
+
287
+ if omit_flag:
288
+ # Check for omission in the annotation metadata
289
+ metadata = _extract_metadata(field_type)
290
+ for meta in metadata:
291
+ if isinstance(meta, OmitFromSchema) and getattr(meta, omit_flag) is True:
292
+ should_omit = True
293
+ break
294
+
295
+ if not should_omit:
296
+ all_annotations[field_name] = field_type
297
+
298
+ return TypedDict(schema_name, all_annotations) # type: ignore[operator]
299
+
300
+
301
+ def _extract_metadata(type_: type) -> list:
302
+ """Extract metadata from a field type, handling Required/NotRequired and Annotated wrappers."""
303
+ # Handle Required[Annotated[...]] or NotRequired[Annotated[...]]
304
+ if get_origin(type_) in (Required, NotRequired):
305
+ inner_type = get_args(type_)[0]
306
+ if get_origin(inner_type) is Annotated:
307
+ return list(get_args(inner_type)[1:])
308
+
309
+ # Handle direct Annotated[...]
310
+ elif get_origin(type_) is Annotated:
311
+ return list(get_args(type_)[1:])
312
+
313
+ return []
314
+
315
+
316
+ def _get_can_jump_to(middleware: AgentMiddleware[Any, Any], hook_name: str) -> list[JumpTo]:
317
+ """Get the `can_jump_to` list from either sync or async hook methods.
318
+
319
+ Args:
320
+ middleware: The middleware instance to inspect.
321
+ hook_name: The name of the hook (`'before_model'` or `'after_model'`).
322
+
323
+ Returns:
324
+ List of jump destinations, or empty list if not configured.
325
+ """
326
+ # Get the base class method for comparison
327
+ base_sync_method = getattr(AgentMiddleware, hook_name, None)
328
+ base_async_method = getattr(AgentMiddleware, f"a{hook_name}", None)
329
+
330
+ # Try sync method first - only if it's overridden from base class
331
+ sync_method = getattr(middleware.__class__, hook_name, None)
332
+ if (
333
+ sync_method
334
+ and sync_method is not base_sync_method
335
+ and hasattr(sync_method, "__can_jump_to__")
336
+ ):
337
+ return sync_method.__can_jump_to__
338
+
339
+ # Try async method - only if it's overridden from base class
340
+ async_method = getattr(middleware.__class__, f"a{hook_name}", None)
341
+ if (
342
+ async_method
343
+ and async_method is not base_async_method
344
+ and hasattr(async_method, "__can_jump_to__")
345
+ ):
346
+ return async_method.__can_jump_to__
347
+
348
+ return []
349
+
350
+
351
+ def _supports_provider_strategy(model: str | BaseChatModel) -> bool:
352
+ """Check if a model supports provider-specific structured output.
353
+
354
+ Args:
355
+ model: Model name string or `BaseChatModel` instance.
356
+
357
+ Returns:
358
+ `True` if the model supports provider-specific structured output, `False` otherwise.
359
+ """
360
+ model_name: str | None = None
361
+ if isinstance(model, str):
362
+ model_name = model
363
+ elif isinstance(model, BaseChatModel):
364
+ model_name = getattr(model, "model_name", None)
365
+
366
+ return (
367
+ "grok" in model_name.lower()
368
+ or any(part in model_name for part in ["gpt-5", "gpt-4.1", "gpt-oss", "o3-pro", "o3-mini"])
369
+ if model_name
370
+ else False
371
+ )
372
+
373
+
374
+ def _handle_structured_output_error(
375
+ exception: Exception,
376
+ response_format: ResponseFormat,
377
+ ) -> tuple[bool, str]:
378
+ """Handle structured output error. Returns `(should_retry, retry_tool_message)`."""
379
+ if not isinstance(response_format, ToolStrategy):
380
+ return False, ""
381
+
382
+ handle_errors = response_format.handle_errors
383
+
384
+ if handle_errors is False:
385
+ return False, ""
386
+ if handle_errors is True:
387
+ return True, STRUCTURED_OUTPUT_ERROR_TEMPLATE.format(error=str(exception))
388
+ if isinstance(handle_errors, str):
389
+ return True, handle_errors
390
+ if isinstance(handle_errors, type) and issubclass(handle_errors, Exception):
391
+ if isinstance(exception, handle_errors):
392
+ return True, STRUCTURED_OUTPUT_ERROR_TEMPLATE.format(error=str(exception))
393
+ return False, ""
394
+ if isinstance(handle_errors, tuple):
395
+ if any(isinstance(exception, exc_type) for exc_type in handle_errors):
396
+ return True, STRUCTURED_OUTPUT_ERROR_TEMPLATE.format(error=str(exception))
397
+ return False, ""
398
+ if callable(handle_errors):
399
+ # type narrowing not working appropriately w/ callable check, can fix later
400
+ return True, handle_errors(exception) # type: ignore[return-value,call-arg]
401
+ return False, ""
402
+
403
+
404
+ def _chain_tool_call_wrappers(
405
+ wrappers: Sequence[ToolCallWrapper],
406
+ ) -> ToolCallWrapper | None:
407
+ """Compose wrappers into middleware stack (first = outermost).
408
+
409
+ Args:
410
+ wrappers: Wrappers in middleware order.
411
+
412
+ Returns:
413
+ Composed wrapper, or `None` if empty.
414
+
415
+ Example:
416
+ wrapper = _chain_tool_call_wrappers([auth, cache, retry])
417
+ # Request flows: auth -> cache -> retry -> tool
418
+ # Response flows: tool -> retry -> cache -> auth
419
+ """
420
+ if not wrappers:
421
+ return None
422
+
423
+ if len(wrappers) == 1:
424
+ return wrappers[0]
425
+
426
+ def compose_two(outer: ToolCallWrapper, inner: ToolCallWrapper) -> ToolCallWrapper:
427
+ """Compose two wrappers where outer wraps inner."""
428
+
429
+ def composed(
430
+ request: ToolCallRequest,
431
+ execute: Callable[[ToolCallRequest], ToolMessage | Command],
432
+ ) -> ToolMessage | Command:
433
+ # Create a callable that invokes inner with the original execute
434
+ def call_inner(req: ToolCallRequest) -> ToolMessage | Command:
435
+ return inner(req, execute)
436
+
437
+ # Outer can call call_inner multiple times
438
+ return outer(request, call_inner)
439
+
440
+ return composed
441
+
442
+ # Chain all wrappers: first -> second -> ... -> last
443
+ result = wrappers[-1]
444
+ for wrapper in reversed(wrappers[:-1]):
445
+ result = compose_two(wrapper, result)
446
+
447
+ return result
448
+
449
+
450
+ def _chain_async_tool_call_wrappers(
451
+ wrappers: Sequence[
452
+ Callable[
453
+ [ToolCallRequest, Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]]],
454
+ Awaitable[ToolMessage | Command],
455
+ ]
456
+ ],
457
+ ) -> (
458
+ Callable[
459
+ [ToolCallRequest, Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]]],
460
+ Awaitable[ToolMessage | Command],
461
+ ]
462
+ | None
463
+ ):
464
+ """Compose async wrappers into middleware stack (first = outermost).
465
+
466
+ Args:
467
+ wrappers: Async wrappers in middleware order.
468
+
469
+ Returns:
470
+ Composed async wrapper, or `None` if empty.
471
+ """
472
+ if not wrappers:
473
+ return None
474
+
475
+ if len(wrappers) == 1:
476
+ return wrappers[0]
477
+
478
+ def compose_two(
479
+ outer: Callable[
480
+ [ToolCallRequest, Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]]],
481
+ Awaitable[ToolMessage | Command],
482
+ ],
483
+ inner: Callable[
484
+ [ToolCallRequest, Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]]],
485
+ Awaitable[ToolMessage | Command],
486
+ ],
487
+ ) -> Callable[
488
+ [ToolCallRequest, Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]]],
489
+ Awaitable[ToolMessage | Command],
490
+ ]:
491
+ """Compose two async wrappers where outer wraps inner."""
492
+
493
+ async def composed(
494
+ request: ToolCallRequest,
495
+ execute: Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]],
496
+ ) -> ToolMessage | Command:
497
+ # Create an async callable that invokes inner with the original execute
498
+ async def call_inner(req: ToolCallRequest) -> ToolMessage | Command:
499
+ return await inner(req, execute)
500
+
501
+ # Outer can call call_inner multiple times
502
+ return await outer(request, call_inner)
503
+
504
+ return composed
505
+
506
+ # Chain all wrappers: first -> second -> ... -> last
507
+ result = wrappers[-1]
508
+ for wrapper in reversed(wrappers[:-1]):
509
+ result = compose_two(wrapper, result)
510
+
511
+ return result
512
+
513
+
514
+ def create_agent( # noqa: PLR0915
515
+ model: str | BaseChatModel,
516
+ tools: Sequence[BaseTool | Callable | dict[str, Any]] | None = None,
517
+ *,
518
+ system_prompt: str | None = None,
519
+ middleware: Sequence[AgentMiddleware[AgentState[ResponseT], ContextT]] = (),
520
+ response_format: ResponseFormat[ResponseT] | type[ResponseT] | None = None,
521
+ state_schema: type[AgentState[ResponseT]] | None = None,
522
+ context_schema: type[ContextT] | None = None,
523
+ checkpointer: Checkpointer | None = None,
524
+ store: BaseStore | None = None,
525
+ interrupt_before: list[str] | None = None,
526
+ interrupt_after: list[str] | None = None,
527
+ debug: bool = False,
528
+ name: str | None = None,
529
+ cache: BaseCache | None = None,
530
+ ) -> CompiledStateGraph[
531
+ AgentState[ResponseT], ContextT, _InputAgentState, _OutputAgentState[ResponseT]
532
+ ]:
533
+ """Creates an agent graph that calls tools in a loop until a stopping condition is met.
534
+
535
+ For more details on using `create_agent`,
536
+ visit [Agents](https://docs.langchain.com/oss/python/langchain/agents) documentation.
537
+
538
+ Args:
539
+ model: The language model for the agent. Can be a string identifier
540
+ (e.g., `"openai:gpt-4"`) or a chat model instance (e.g., `ChatOpenAI()`).
541
+ For a full list of supported model strings, see
542
+ [`init_chat_model`][langchain.chat_models.init_chat_model(model_provider)].
543
+ tools: A list of tools, `dicts`, or `Callable`. If `None` or an empty list,
544
+ the agent will consist of a model node without a tool calling loop.
545
+ system_prompt: An optional system prompt for the LLM. Prompts are converted to a
546
+ `SystemMessage` and added to the beginning of the message list.
547
+ middleware: A sequence of middleware instances to apply to the agent.
548
+ Middleware can intercept and modify agent behavior at various stages.
549
+ response_format: An optional configuration for structured responses.
550
+ Can be a `ToolStrategy`, `ProviderStrategy`, or a Pydantic model class.
551
+ If provided, the agent will handle structured output during the
552
+ conversation flow. Raw schemas will be wrapped in an appropriate strategy
553
+ based on model capabilities.
554
+ state_schema: An optional `TypedDict` schema that extends `AgentState`.
555
+ When provided, this schema is used instead of `AgentState` as the base
556
+ schema for merging with middleware state schemas. This allows users to
557
+ add custom state fields without needing to create custom middleware.
558
+ Generally, it's recommended to use state_schema extensions via middleware
559
+ to keep relevant extensions scoped to corresponding hooks / tools.
560
+ The schema must be a subclass of `AgentState[ResponseT]`.
561
+ context_schema: An optional schema for runtime context.
562
+ checkpointer: An optional checkpoint saver object. This is used for persisting
563
+ the state of the graph (e.g., as chat memory) for a single thread
564
+ (e.g., a single conversation).
565
+ store: An optional store object. This is used for persisting data
566
+ across multiple threads (e.g., multiple conversations / users).
567
+ interrupt_before: An optional list of node names to interrupt before.
568
+ Useful if you want to add a user confirmation or other interrupt
569
+ before taking an action.
570
+ interrupt_after: An optional list of node names to interrupt after.
571
+ Useful if you want to return directly or run additional processing
572
+ on an output.
573
+ debug: Whether to enable verbose logging for graph execution. When enabled,
574
+ prints detailed information about each node execution, state updates,
575
+ and transitions during agent runtime. Useful for debugging middleware
576
+ behavior and understanding agent execution flow.
577
+ name: An optional name for the `CompiledStateGraph`.
578
+ This name will be automatically used when adding the agent graph to
579
+ another graph as a subgraph node - particularly useful for building
580
+ multi-agent systems.
581
+ cache: An optional `BaseCache` instance to enable caching of graph execution.
582
+
583
+ Returns:
584
+ A compiled `StateGraph` that can be used for chat interactions.
585
+
586
+ The agent node calls the language model with the messages list (after applying
587
+ the system prompt). If the resulting `AIMessage` contains `tool_calls`, the graph
588
+ will then call the tools. The tools node executes the tools and adds the responses
589
+ to the messages list as `ToolMessage` objects. The agent node then calls the
590
+ language model again. The process repeats until no more `tool_calls` are
591
+ present in the response. The agent then returns the full list of messages.
592
+
593
+ Example:
594
+ ```python
595
+ from langchain.agents import create_agent
596
+
597
+
598
+ def check_weather(location: str) -> str:
599
+ '''Return the weather forecast for the specified location.'''
600
+ return f"It's always sunny in {location}"
601
+
602
+
603
+ graph = create_agent(
604
+ model="anthropic:claude-sonnet-4-5-20250929",
605
+ tools=[check_weather],
606
+ system_prompt="You are a helpful assistant",
607
+ )
608
+ inputs = {"messages": [{"role": "user", "content": "what is the weather in sf"}]}
609
+ for chunk in graph.stream(inputs, stream_mode="updates"):
610
+ print(chunk)
611
+ ```
612
+ """
613
+ # init chat model
614
+ if isinstance(model, str):
615
+ model = init_chat_model(model)
616
+
617
+ # Handle tools being None or empty
618
+ if tools is None:
619
+ tools = []
620
+
621
+ # Convert response format and setup structured output tools
622
+ # Raw schemas are wrapped in AutoStrategy to preserve auto-detection intent.
623
+ # AutoStrategy is converted to ToolStrategy upfront to calculate tools during agent creation,
624
+ # but may be replaced with ProviderStrategy later based on model capabilities.
625
+ initial_response_format: ToolStrategy | ProviderStrategy | AutoStrategy | None
626
+ if response_format is None:
627
+ initial_response_format = None
628
+ elif isinstance(response_format, (ToolStrategy, ProviderStrategy)):
629
+ # Preserve explicitly requested strategies
630
+ initial_response_format = response_format
631
+ elif isinstance(response_format, AutoStrategy):
632
+ # AutoStrategy provided - preserve it for later auto-detection
633
+ initial_response_format = response_format
634
+ else:
635
+ # Raw schema - wrap in AutoStrategy to enable auto-detection
636
+ initial_response_format = AutoStrategy(schema=response_format)
637
+
638
+ # For AutoStrategy, convert to ToolStrategy to setup tools upfront
639
+ # (may be replaced with ProviderStrategy later based on model)
640
+ tool_strategy_for_setup: ToolStrategy | None = None
641
+ if isinstance(initial_response_format, AutoStrategy):
642
+ tool_strategy_for_setup = ToolStrategy(schema=initial_response_format.schema)
643
+ elif isinstance(initial_response_format, ToolStrategy):
644
+ tool_strategy_for_setup = initial_response_format
645
+
646
+ structured_output_tools: dict[str, OutputToolBinding] = {}
647
+ if tool_strategy_for_setup:
648
+ for response_schema in tool_strategy_for_setup.schema_specs:
649
+ structured_tool_info = OutputToolBinding.from_schema_spec(response_schema)
650
+ structured_output_tools[structured_tool_info.tool.name] = structured_tool_info
651
+ middleware_tools = [t for m in middleware for t in getattr(m, "tools", [])]
652
+
653
+ # Collect middleware with wrap_tool_call or awrap_tool_call hooks
654
+ # Include middleware with either implementation to ensure NotImplementedError is raised
655
+ # when middleware doesn't support the execution path
656
+ middleware_w_wrap_tool_call = [
657
+ m
658
+ for m in middleware
659
+ if m.__class__.wrap_tool_call is not AgentMiddleware.wrap_tool_call
660
+ or m.__class__.awrap_tool_call is not AgentMiddleware.awrap_tool_call
661
+ ]
662
+
663
+ # Chain all wrap_tool_call handlers into a single composed handler
664
+ wrap_tool_call_wrapper = None
665
+ if middleware_w_wrap_tool_call:
666
+ wrappers = [m.wrap_tool_call for m in middleware_w_wrap_tool_call]
667
+ wrap_tool_call_wrapper = _chain_tool_call_wrappers(wrappers)
668
+
669
+ # Collect middleware with awrap_tool_call or wrap_tool_call hooks
670
+ # Include middleware with either implementation to ensure NotImplementedError is raised
671
+ # when middleware doesn't support the execution path
672
+ middleware_w_awrap_tool_call = [
673
+ m
674
+ for m in middleware
675
+ if m.__class__.awrap_tool_call is not AgentMiddleware.awrap_tool_call
676
+ or m.__class__.wrap_tool_call is not AgentMiddleware.wrap_tool_call
677
+ ]
678
+
679
+ # Chain all awrap_tool_call handlers into a single composed async handler
680
+ awrap_tool_call_wrapper = None
681
+ if middleware_w_awrap_tool_call:
682
+ async_wrappers = [m.awrap_tool_call for m in middleware_w_awrap_tool_call]
683
+ awrap_tool_call_wrapper = _chain_async_tool_call_wrappers(async_wrappers)
684
+
685
+ # Setup tools
686
+ tool_node: _ToolNode | None = None
687
+ # Extract built-in provider tools (dict format) and regular tools (BaseTool/callables)
688
+ built_in_tools = [t for t in tools if isinstance(t, dict)]
689
+ regular_tools = [t for t in tools if not isinstance(t, dict)]
690
+
691
+ # Tools that require client-side execution (must be in ToolNode)
692
+ available_tools = middleware_tools + regular_tools
693
+
694
+ # Only create ToolNode if we have client-side tools
695
+ tool_node = (
696
+ _ToolNode(
697
+ tools=available_tools,
698
+ wrap_tool_call=wrap_tool_call_wrapper,
699
+ awrap_tool_call=awrap_tool_call_wrapper,
700
+ )
701
+ if available_tools
702
+ else None
703
+ )
704
+
705
+ # Default tools for ModelRequest initialization
706
+ # Use converted BaseTool instances from ToolNode (not raw callables)
707
+ # Include built-ins and converted tools (can be changed dynamically by middleware)
708
+ # Structured tools are NOT included - they're added dynamically based on response_format
709
+ if tool_node:
710
+ default_tools = list(tool_node.tools_by_name.values()) + built_in_tools
711
+ else:
712
+ default_tools = list(built_in_tools)
713
+
714
+ # validate middleware
715
+ assert len({m.name for m in middleware}) == len(middleware), ( # noqa: S101
716
+ "Please remove duplicate middleware instances."
717
+ )
718
+ middleware_w_before_agent = [
719
+ m
720
+ for m in middleware
721
+ if m.__class__.before_agent is not AgentMiddleware.before_agent
722
+ or m.__class__.abefore_agent is not AgentMiddleware.abefore_agent
723
+ ]
724
+ middleware_w_before_model = [
725
+ m
726
+ for m in middleware
727
+ if m.__class__.before_model is not AgentMiddleware.before_model
728
+ or m.__class__.abefore_model is not AgentMiddleware.abefore_model
729
+ ]
730
+ middleware_w_after_model = [
731
+ m
732
+ for m in middleware
733
+ if m.__class__.after_model is not AgentMiddleware.after_model
734
+ or m.__class__.aafter_model is not AgentMiddleware.aafter_model
735
+ ]
736
+ middleware_w_after_agent = [
737
+ m
738
+ for m in middleware
739
+ if m.__class__.after_agent is not AgentMiddleware.after_agent
740
+ or m.__class__.aafter_agent is not AgentMiddleware.aafter_agent
741
+ ]
742
+ # Collect middleware with wrap_model_call or awrap_model_call hooks
743
+ # Include middleware with either implementation to ensure NotImplementedError is raised
744
+ # when middleware doesn't support the execution path
745
+ middleware_w_wrap_model_call = [
746
+ m
747
+ for m in middleware
748
+ if m.__class__.wrap_model_call is not AgentMiddleware.wrap_model_call
749
+ or m.__class__.awrap_model_call is not AgentMiddleware.awrap_model_call
750
+ ]
751
+ # Collect middleware with awrap_model_call or wrap_model_call hooks
752
+ # Include middleware with either implementation to ensure NotImplementedError is raised
753
+ # when middleware doesn't support the execution path
754
+ middleware_w_awrap_model_call = [
755
+ m
756
+ for m in middleware
757
+ if m.__class__.awrap_model_call is not AgentMiddleware.awrap_model_call
758
+ or m.__class__.wrap_model_call is not AgentMiddleware.wrap_model_call
759
+ ]
760
+
761
+ # Compose wrap_model_call handlers into a single middleware stack (sync)
762
+ wrap_model_call_handler = None
763
+ if middleware_w_wrap_model_call:
764
+ sync_handlers = [m.wrap_model_call for m in middleware_w_wrap_model_call]
765
+ wrap_model_call_handler = _chain_model_call_handlers(sync_handlers)
766
+
767
+ # Compose awrap_model_call handlers into a single middleware stack (async)
768
+ awrap_model_call_handler = None
769
+ if middleware_w_awrap_model_call:
770
+ async_handlers = [m.awrap_model_call for m in middleware_w_awrap_model_call]
771
+ awrap_model_call_handler = _chain_async_model_call_handlers(async_handlers)
772
+
773
+ state_schemas = {m.state_schema for m in middleware}
774
+ # Use provided state_schema if available, otherwise use base AgentState
775
+ base_state = state_schema if state_schema is not None else AgentState
776
+ state_schemas.add(base_state)
777
+
778
+ resolved_state_schema = _resolve_schema(state_schemas, "StateSchema", None)
779
+ input_schema = _resolve_schema(state_schemas, "InputSchema", "input")
780
+ output_schema = _resolve_schema(state_schemas, "OutputSchema", "output")
781
+
782
+ # create graph, add nodes
783
+ graph: StateGraph[
784
+ AgentState[ResponseT], ContextT, _InputAgentState, _OutputAgentState[ResponseT]
785
+ ] = StateGraph(
786
+ state_schema=resolved_state_schema,
787
+ input_schema=input_schema,
788
+ output_schema=output_schema,
789
+ context_schema=context_schema,
790
+ )
791
+
792
+ def _handle_model_output(
793
+ output: AIMessage, effective_response_format: ResponseFormat | None
794
+ ) -> dict[str, Any]:
795
+ """Handle model output including structured responses.
796
+
797
+ Args:
798
+ output: The AI message output from the model.
799
+ effective_response_format: The actual strategy used
800
+ (may differ from initial if auto-detected).
801
+ """
802
+ # Handle structured output with provider strategy
803
+ if isinstance(effective_response_format, ProviderStrategy):
804
+ if not output.tool_calls:
805
+ provider_strategy_binding = ProviderStrategyBinding.from_schema_spec(
806
+ effective_response_format.schema_spec
807
+ )
808
+ structured_response = provider_strategy_binding.parse(output)
809
+ return {"messages": [output], "structured_response": structured_response}
810
+ return {"messages": [output]}
811
+
812
+ # Handle structured output with tool strategy
813
+ if (
814
+ isinstance(effective_response_format, ToolStrategy)
815
+ and isinstance(output, AIMessage)
816
+ and output.tool_calls
817
+ ):
818
+ structured_tool_calls = [
819
+ tc for tc in output.tool_calls if tc["name"] in structured_output_tools
820
+ ]
821
+
822
+ if structured_tool_calls:
823
+ exception: Exception | None = None
824
+ if len(structured_tool_calls) > 1:
825
+ # Handle multiple structured outputs error
826
+ tool_names = [tc["name"] for tc in structured_tool_calls]
827
+ exception = MultipleStructuredOutputsError(tool_names)
828
+ should_retry, error_message = _handle_structured_output_error(
829
+ exception, effective_response_format
830
+ )
831
+ if not should_retry:
832
+ raise exception
833
+
834
+ # Add error messages and retry
835
+ tool_messages = [
836
+ ToolMessage(
837
+ content=error_message,
838
+ tool_call_id=tc["id"],
839
+ name=tc["name"],
840
+ )
841
+ for tc in structured_tool_calls
842
+ ]
843
+ return {"messages": [output, *tool_messages]}
844
+
845
+ # Handle single structured output
846
+ tool_call = structured_tool_calls[0]
847
+ try:
848
+ structured_tool_binding = structured_output_tools[tool_call["name"]]
849
+ structured_response = structured_tool_binding.parse(tool_call["args"])
850
+
851
+ tool_message_content = (
852
+ effective_response_format.tool_message_content
853
+ if effective_response_format.tool_message_content
854
+ else f"Returning structured response: {structured_response}"
855
+ )
856
+
857
+ return {
858
+ "messages": [
859
+ output,
860
+ ToolMessage(
861
+ content=tool_message_content,
862
+ tool_call_id=tool_call["id"],
863
+ name=tool_call["name"],
864
+ ),
865
+ ],
866
+ "structured_response": structured_response,
867
+ }
868
+ except Exception as exc: # noqa: BLE001
869
+ exception = StructuredOutputValidationError(tool_call["name"], exc)
870
+ should_retry, error_message = _handle_structured_output_error(
871
+ exception, effective_response_format
872
+ )
873
+ if not should_retry:
874
+ raise exception
875
+
876
+ return {
877
+ "messages": [
878
+ output,
879
+ ToolMessage(
880
+ content=error_message,
881
+ tool_call_id=tool_call["id"],
882
+ name=tool_call["name"],
883
+ ),
884
+ ],
885
+ }
886
+
887
+ return {"messages": [output]}
888
+
889
+ def _get_bound_model(request: ModelRequest) -> tuple[Runnable, ResponseFormat | None]:
890
+ """Get the model with appropriate tool bindings.
891
+
892
+ Performs auto-detection of strategy if needed based on model capabilities.
893
+
894
+ Args:
895
+ request: The model request containing model, tools, and response format.
896
+
897
+ Returns:
898
+ Tuple of `(bound_model, effective_response_format)` where
899
+ `effective_response_format` is the actual strategy used (may differ from
900
+ initial if auto-detected).
901
+ """
902
+ # Validate ONLY client-side tools that need to exist in tool_node
903
+ # Build map of available client-side tools from the ToolNode
904
+ # (which has already converted callables)
905
+ available_tools_by_name = {}
906
+ if tool_node:
907
+ available_tools_by_name = tool_node.tools_by_name.copy()
908
+
909
+ # Check if any requested tools are unknown CLIENT-SIDE tools
910
+ unknown_tool_names = []
911
+ for t in request.tools:
912
+ # Only validate BaseTool instances (skip built-in dict tools)
913
+ if isinstance(t, dict):
914
+ continue
915
+ if isinstance(t, BaseTool) and t.name not in available_tools_by_name:
916
+ unknown_tool_names.append(t.name)
917
+
918
+ if unknown_tool_names:
919
+ available_tool_names = sorted(available_tools_by_name.keys())
920
+ msg = (
921
+ f"Middleware returned unknown tool names: {unknown_tool_names}\n\n"
922
+ f"Available client-side tools: {available_tool_names}\n\n"
923
+ "To fix this issue:\n"
924
+ "1. Ensure the tools are passed to create_agent() via "
925
+ "the 'tools' parameter\n"
926
+ "2. If using custom middleware with tools, ensure "
927
+ "they're registered via middleware.tools attribute\n"
928
+ "3. Verify that tool names in ModelRequest.tools match "
929
+ "the actual tool.name values\n"
930
+ "Note: Built-in provider tools (dict format) can be added dynamically."
931
+ )
932
+ raise ValueError(msg)
933
+
934
+ # Determine effective response format (auto-detect if needed)
935
+ effective_response_format: ResponseFormat | None
936
+ if isinstance(request.response_format, AutoStrategy):
937
+ # User provided raw schema via AutoStrategy - auto-detect best strategy based on model
938
+ if _supports_provider_strategy(request.model):
939
+ # Model supports provider strategy - use it
940
+ effective_response_format = ProviderStrategy(schema=request.response_format.schema)
941
+ else:
942
+ # Model doesn't support provider strategy - use ToolStrategy
943
+ effective_response_format = ToolStrategy(schema=request.response_format.schema)
944
+ else:
945
+ # User explicitly specified a strategy - preserve it
946
+ effective_response_format = request.response_format
947
+
948
+ # Build final tools list including structured output tools
949
+ # request.tools now only contains BaseTool instances (converted from callables)
950
+ # and dicts (built-ins)
951
+ final_tools = list(request.tools)
952
+ if isinstance(effective_response_format, ToolStrategy):
953
+ # Add structured output tools to final tools list
954
+ structured_tools = [info.tool for info in structured_output_tools.values()]
955
+ final_tools.extend(structured_tools)
956
+
957
+ # Bind model based on effective response format
958
+ if isinstance(effective_response_format, ProviderStrategy):
959
+ # Use provider-specific structured output
960
+ kwargs = effective_response_format.to_model_kwargs()
961
+ return (
962
+ request.model.bind_tools(
963
+ final_tools, strict=True, **kwargs, **request.model_settings
964
+ ),
965
+ effective_response_format,
966
+ )
967
+
968
+ if isinstance(effective_response_format, ToolStrategy):
969
+ # Current implementation requires that tools used for structured output
970
+ # have to be declared upfront when creating the agent as part of the
971
+ # response format. Middleware is allowed to change the response format
972
+ # to a subset of the original structured tools when using ToolStrategy,
973
+ # but not to add new structured tools that weren't declared upfront.
974
+ # Compute output binding
975
+ for tc in effective_response_format.schema_specs:
976
+ if tc.name not in structured_output_tools:
977
+ msg = (
978
+ f"ToolStrategy specifies tool '{tc.name}' "
979
+ "which wasn't declared in the original "
980
+ "response format when creating the agent."
981
+ )
982
+ raise ValueError(msg)
983
+
984
+ # Force tool use if we have structured output tools
985
+ tool_choice = "any" if structured_output_tools else request.tool_choice
986
+ return (
987
+ request.model.bind_tools(
988
+ final_tools, tool_choice=tool_choice, **request.model_settings
989
+ ),
990
+ effective_response_format,
991
+ )
992
+
993
+ # No structured output - standard model binding
994
+ if final_tools:
995
+ return (
996
+ request.model.bind_tools(
997
+ final_tools, tool_choice=request.tool_choice, **request.model_settings
998
+ ),
999
+ None,
1000
+ )
1001
+ return request.model.bind(**request.model_settings), None
1002
+
1003
+ def _execute_model_sync(request: ModelRequest) -> ModelResponse:
1004
+ """Execute model and return response.
1005
+
1006
+ This is the core model execution logic wrapped by `wrap_model_call` handlers.
1007
+ Raises any exceptions that occur during model invocation.
1008
+ """
1009
+ # Get the bound model (with auto-detection if needed)
1010
+ model_, effective_response_format = _get_bound_model(request)
1011
+ messages = request.messages
1012
+ if request.system_prompt:
1013
+ messages = [SystemMessage(request.system_prompt), *messages]
1014
+
1015
+ output = model_.invoke(messages)
1016
+
1017
+ # Handle model output to get messages and structured_response
1018
+ handled_output = _handle_model_output(output, effective_response_format)
1019
+ messages_list = handled_output["messages"]
1020
+ structured_response = handled_output.get("structured_response")
1021
+
1022
+ return ModelResponse(
1023
+ result=messages_list,
1024
+ structured_response=structured_response,
1025
+ )
1026
+
1027
+ def model_node(state: AgentState, runtime: Runtime[ContextT]) -> dict[str, Any]:
1028
+ """Sync model request handler with sequential middleware processing."""
1029
+ request = ModelRequest(
1030
+ model=model,
1031
+ tools=default_tools,
1032
+ system_prompt=system_prompt,
1033
+ response_format=initial_response_format,
1034
+ messages=state["messages"],
1035
+ tool_choice=None,
1036
+ state=state,
1037
+ runtime=runtime,
1038
+ )
1039
+
1040
+ if wrap_model_call_handler is None:
1041
+ # No handlers - execute directly
1042
+ response = _execute_model_sync(request)
1043
+ else:
1044
+ # Call composed handler with base handler
1045
+ response = wrap_model_call_handler(request, _execute_model_sync)
1046
+
1047
+ # Extract state updates from ModelResponse
1048
+ state_updates = {"messages": response.result}
1049
+ if response.structured_response is not None:
1050
+ state_updates["structured_response"] = response.structured_response
1051
+
1052
+ return state_updates
1053
+
1054
+ async def _execute_model_async(request: ModelRequest) -> ModelResponse:
1055
+ """Execute model asynchronously and return response.
1056
+
1057
+ This is the core async model execution logic wrapped by `wrap_model_call`
1058
+ handlers.
1059
+
1060
+ Raises any exceptions that occur during model invocation.
1061
+ """
1062
+ # Get the bound model (with auto-detection if needed)
1063
+ model_, effective_response_format = _get_bound_model(request)
1064
+ messages = request.messages
1065
+ if request.system_prompt:
1066
+ messages = [SystemMessage(request.system_prompt), *messages]
1067
+
1068
+ output = await model_.ainvoke(messages)
1069
+
1070
+ # Handle model output to get messages and structured_response
1071
+ handled_output = _handle_model_output(output, effective_response_format)
1072
+ messages_list = handled_output["messages"]
1073
+ structured_response = handled_output.get("structured_response")
1074
+
1075
+ return ModelResponse(
1076
+ result=messages_list,
1077
+ structured_response=structured_response,
1078
+ )
1079
+
1080
+ async def amodel_node(state: AgentState, runtime: Runtime[ContextT]) -> dict[str, Any]:
1081
+ """Async model request handler with sequential middleware processing."""
1082
+ request = ModelRequest(
1083
+ model=model,
1084
+ tools=default_tools,
1085
+ system_prompt=system_prompt,
1086
+ response_format=initial_response_format,
1087
+ messages=state["messages"],
1088
+ tool_choice=None,
1089
+ state=state,
1090
+ runtime=runtime,
1091
+ )
1092
+
1093
+ if awrap_model_call_handler is None:
1094
+ # No async handlers - execute directly
1095
+ response = await _execute_model_async(request)
1096
+ else:
1097
+ # Call composed async handler with base handler
1098
+ response = await awrap_model_call_handler(request, _execute_model_async)
1099
+
1100
+ # Extract state updates from ModelResponse
1101
+ state_updates = {"messages": response.result}
1102
+ if response.structured_response is not None:
1103
+ state_updates["structured_response"] = response.structured_response
1104
+
1105
+ return state_updates
1106
+
1107
+ # Use sync or async based on model capabilities
1108
+ graph.add_node("model", RunnableCallable(model_node, amodel_node, trace=False))
1109
+
1110
+ # Only add tools node if we have tools
1111
+ if tool_node is not None:
1112
+ graph.add_node("tools", tool_node)
1113
+
1114
+ # Add middleware nodes
1115
+ for m in middleware:
1116
+ if (
1117
+ m.__class__.before_agent is not AgentMiddleware.before_agent
1118
+ or m.__class__.abefore_agent is not AgentMiddleware.abefore_agent
1119
+ ):
1120
+ # Use RunnableCallable to support both sync and async
1121
+ # Pass None for sync if not overridden to avoid signature conflicts
1122
+ sync_before_agent = (
1123
+ m.before_agent
1124
+ if m.__class__.before_agent is not AgentMiddleware.before_agent
1125
+ else None
1126
+ )
1127
+ async_before_agent = (
1128
+ m.abefore_agent
1129
+ if m.__class__.abefore_agent is not AgentMiddleware.abefore_agent
1130
+ else None
1131
+ )
1132
+ before_agent_node = RunnableCallable(sync_before_agent, async_before_agent, trace=False)
1133
+ graph.add_node(
1134
+ f"{m.name}.before_agent", before_agent_node, input_schema=resolved_state_schema
1135
+ )
1136
+
1137
+ if (
1138
+ m.__class__.before_model is not AgentMiddleware.before_model
1139
+ or m.__class__.abefore_model is not AgentMiddleware.abefore_model
1140
+ ):
1141
+ # Use RunnableCallable to support both sync and async
1142
+ # Pass None for sync if not overridden to avoid signature conflicts
1143
+ sync_before = (
1144
+ m.before_model
1145
+ if m.__class__.before_model is not AgentMiddleware.before_model
1146
+ else None
1147
+ )
1148
+ async_before = (
1149
+ m.abefore_model
1150
+ if m.__class__.abefore_model is not AgentMiddleware.abefore_model
1151
+ else None
1152
+ )
1153
+ before_node = RunnableCallable(sync_before, async_before, trace=False)
1154
+ graph.add_node(
1155
+ f"{m.name}.before_model", before_node, input_schema=resolved_state_schema
1156
+ )
1157
+
1158
+ if (
1159
+ m.__class__.after_model is not AgentMiddleware.after_model
1160
+ or m.__class__.aafter_model is not AgentMiddleware.aafter_model
1161
+ ):
1162
+ # Use RunnableCallable to support both sync and async
1163
+ # Pass None for sync if not overridden to avoid signature conflicts
1164
+ sync_after = (
1165
+ m.after_model
1166
+ if m.__class__.after_model is not AgentMiddleware.after_model
1167
+ else None
1168
+ )
1169
+ async_after = (
1170
+ m.aafter_model
1171
+ if m.__class__.aafter_model is not AgentMiddleware.aafter_model
1172
+ else None
1173
+ )
1174
+ after_node = RunnableCallable(sync_after, async_after, trace=False)
1175
+ graph.add_node(f"{m.name}.after_model", after_node, input_schema=resolved_state_schema)
1176
+
1177
+ if (
1178
+ m.__class__.after_agent is not AgentMiddleware.after_agent
1179
+ or m.__class__.aafter_agent is not AgentMiddleware.aafter_agent
1180
+ ):
1181
+ # Use RunnableCallable to support both sync and async
1182
+ # Pass None for sync if not overridden to avoid signature conflicts
1183
+ sync_after_agent = (
1184
+ m.after_agent
1185
+ if m.__class__.after_agent is not AgentMiddleware.after_agent
1186
+ else None
1187
+ )
1188
+ async_after_agent = (
1189
+ m.aafter_agent
1190
+ if m.__class__.aafter_agent is not AgentMiddleware.aafter_agent
1191
+ else None
1192
+ )
1193
+ after_agent_node = RunnableCallable(sync_after_agent, async_after_agent, trace=False)
1194
+ graph.add_node(
1195
+ f"{m.name}.after_agent", after_agent_node, input_schema=resolved_state_schema
1196
+ )
1197
+
1198
+ # Determine the entry node (runs once at start): before_agent -> before_model -> model
1199
+ if middleware_w_before_agent:
1200
+ entry_node = f"{middleware_w_before_agent[0].name}.before_agent"
1201
+ elif middleware_w_before_model:
1202
+ entry_node = f"{middleware_w_before_model[0].name}.before_model"
1203
+ else:
1204
+ entry_node = "model"
1205
+
1206
+ # Determine the loop entry node (beginning of agent loop, excludes before_agent)
1207
+ # This is where tools will loop back to for the next iteration
1208
+ if middleware_w_before_model:
1209
+ loop_entry_node = f"{middleware_w_before_model[0].name}.before_model"
1210
+ else:
1211
+ loop_entry_node = "model"
1212
+
1213
+ # Determine the loop exit node (end of each iteration, can run multiple times)
1214
+ # This is after_model or model, but NOT after_agent
1215
+ if middleware_w_after_model:
1216
+ loop_exit_node = f"{middleware_w_after_model[0].name}.after_model"
1217
+ else:
1218
+ loop_exit_node = "model"
1219
+
1220
+ # Determine the exit node (runs once at end): after_agent or END
1221
+ if middleware_w_after_agent:
1222
+ exit_node = f"{middleware_w_after_agent[-1].name}.after_agent"
1223
+ else:
1224
+ exit_node = END
1225
+
1226
+ graph.add_edge(START, entry_node)
1227
+ # add conditional edges only if tools exist
1228
+ if tool_node is not None:
1229
+ # Only include exit_node in destinations if any tool has return_direct=True
1230
+ # or if there are structured output tools
1231
+ tools_to_model_destinations = [loop_entry_node]
1232
+ if (
1233
+ any(tool.return_direct for tool in tool_node.tools_by_name.values())
1234
+ or structured_output_tools
1235
+ ):
1236
+ tools_to_model_destinations.append(exit_node)
1237
+
1238
+ graph.add_conditional_edges(
1239
+ "tools",
1240
+ _make_tools_to_model_edge(
1241
+ tool_node=tool_node,
1242
+ model_destination=loop_entry_node,
1243
+ structured_output_tools=structured_output_tools,
1244
+ end_destination=exit_node,
1245
+ ),
1246
+ tools_to_model_destinations,
1247
+ )
1248
+
1249
+ # base destinations are tools and exit_node
1250
+ # we add the loop_entry node to edge destinations if:
1251
+ # - there is an after model hook(s) -- allows jump_to to model
1252
+ # potentially artificially injected tool messages, ex HITL
1253
+ # - there is a response format -- to allow for jumping to model to handle
1254
+ # regenerating structured output tool calls
1255
+ model_to_tools_destinations = ["tools", exit_node]
1256
+ if response_format or loop_exit_node != "model":
1257
+ model_to_tools_destinations.append(loop_entry_node)
1258
+
1259
+ graph.add_conditional_edges(
1260
+ loop_exit_node,
1261
+ _make_model_to_tools_edge(
1262
+ model_destination=loop_entry_node,
1263
+ structured_output_tools=structured_output_tools,
1264
+ end_destination=exit_node,
1265
+ ),
1266
+ model_to_tools_destinations,
1267
+ )
1268
+ elif len(structured_output_tools) > 0:
1269
+ graph.add_conditional_edges(
1270
+ loop_exit_node,
1271
+ _make_model_to_model_edge(
1272
+ model_destination=loop_entry_node,
1273
+ end_destination=exit_node,
1274
+ ),
1275
+ [loop_entry_node, exit_node],
1276
+ )
1277
+ elif loop_exit_node == "model":
1278
+ # If no tools and no after_model, go directly to exit_node
1279
+ graph.add_edge(loop_exit_node, exit_node)
1280
+ # No tools but we have after_model - connect after_model to exit_node
1281
+ else:
1282
+ _add_middleware_edge(
1283
+ graph,
1284
+ name=f"{middleware_w_after_model[0].name}.after_model",
1285
+ default_destination=exit_node,
1286
+ model_destination=loop_entry_node,
1287
+ end_destination=exit_node,
1288
+ can_jump_to=_get_can_jump_to(middleware_w_after_model[0], "after_model"),
1289
+ )
1290
+
1291
+ # Add before_agent middleware edges
1292
+ if middleware_w_before_agent:
1293
+ for m1, m2 in itertools.pairwise(middleware_w_before_agent):
1294
+ _add_middleware_edge(
1295
+ graph,
1296
+ name=f"{m1.name}.before_agent",
1297
+ default_destination=f"{m2.name}.before_agent",
1298
+ model_destination=loop_entry_node,
1299
+ end_destination=exit_node,
1300
+ can_jump_to=_get_can_jump_to(m1, "before_agent"),
1301
+ )
1302
+ # Connect last before_agent to loop_entry_node (before_model or model)
1303
+ _add_middleware_edge(
1304
+ graph,
1305
+ name=f"{middleware_w_before_agent[-1].name}.before_agent",
1306
+ default_destination=loop_entry_node,
1307
+ model_destination=loop_entry_node,
1308
+ end_destination=exit_node,
1309
+ can_jump_to=_get_can_jump_to(middleware_w_before_agent[-1], "before_agent"),
1310
+ )
1311
+
1312
+ # Add before_model middleware edges
1313
+ if middleware_w_before_model:
1314
+ for m1, m2 in itertools.pairwise(middleware_w_before_model):
1315
+ _add_middleware_edge(
1316
+ graph,
1317
+ name=f"{m1.name}.before_model",
1318
+ default_destination=f"{m2.name}.before_model",
1319
+ model_destination=loop_entry_node,
1320
+ end_destination=exit_node,
1321
+ can_jump_to=_get_can_jump_to(m1, "before_model"),
1322
+ )
1323
+ # Go directly to model after the last before_model
1324
+ _add_middleware_edge(
1325
+ graph,
1326
+ name=f"{middleware_w_before_model[-1].name}.before_model",
1327
+ default_destination="model",
1328
+ model_destination=loop_entry_node,
1329
+ end_destination=exit_node,
1330
+ can_jump_to=_get_can_jump_to(middleware_w_before_model[-1], "before_model"),
1331
+ )
1332
+
1333
+ # Add after_model middleware edges
1334
+ if middleware_w_after_model:
1335
+ graph.add_edge("model", f"{middleware_w_after_model[-1].name}.after_model")
1336
+ for idx in range(len(middleware_w_after_model) - 1, 0, -1):
1337
+ m1 = middleware_w_after_model[idx]
1338
+ m2 = middleware_w_after_model[idx - 1]
1339
+ _add_middleware_edge(
1340
+ graph,
1341
+ name=f"{m1.name}.after_model",
1342
+ default_destination=f"{m2.name}.after_model",
1343
+ model_destination=loop_entry_node,
1344
+ end_destination=exit_node,
1345
+ can_jump_to=_get_can_jump_to(m1, "after_model"),
1346
+ )
1347
+ # Note: Connection from after_model to after_agent/END is handled above
1348
+ # in the conditional edges section
1349
+
1350
+ # Add after_agent middleware edges
1351
+ if middleware_w_after_agent:
1352
+ # Chain after_agent middleware (runs once at the very end, before END)
1353
+ for idx in range(len(middleware_w_after_agent) - 1, 0, -1):
1354
+ m1 = middleware_w_after_agent[idx]
1355
+ m2 = middleware_w_after_agent[idx - 1]
1356
+ _add_middleware_edge(
1357
+ graph,
1358
+ name=f"{m1.name}.after_agent",
1359
+ default_destination=f"{m2.name}.after_agent",
1360
+ model_destination=loop_entry_node,
1361
+ end_destination=exit_node,
1362
+ can_jump_to=_get_can_jump_to(m1, "after_agent"),
1363
+ )
1364
+
1365
+ # Connect the last after_agent to END
1366
+ _add_middleware_edge(
1367
+ graph,
1368
+ name=f"{middleware_w_after_agent[0].name}.after_agent",
1369
+ default_destination=END,
1370
+ model_destination=loop_entry_node,
1371
+ end_destination=exit_node,
1372
+ can_jump_to=_get_can_jump_to(middleware_w_after_agent[0], "after_agent"),
1373
+ )
1374
+
1375
+ return graph.compile(
1376
+ checkpointer=checkpointer,
1377
+ store=store,
1378
+ interrupt_before=interrupt_before,
1379
+ interrupt_after=interrupt_after,
1380
+ debug=debug,
1381
+ name=name,
1382
+ cache=cache,
1383
+ )
1384
+
1385
+
1386
+ def _resolve_jump(
1387
+ jump_to: JumpTo | None,
1388
+ *,
1389
+ model_destination: str,
1390
+ end_destination: str,
1391
+ ) -> str | None:
1392
+ if jump_to == "model":
1393
+ return model_destination
1394
+ if jump_to == "end":
1395
+ return end_destination
1396
+ if jump_to == "tools":
1397
+ return "tools"
1398
+ return None
1399
+
1400
+
1401
+ def _fetch_last_ai_and_tool_messages(
1402
+ messages: list[AnyMessage],
1403
+ ) -> tuple[AIMessage, list[ToolMessage]]:
1404
+ last_ai_index: int
1405
+ last_ai_message: AIMessage
1406
+
1407
+ for i in range(len(messages) - 1, -1, -1):
1408
+ if isinstance(messages[i], AIMessage):
1409
+ last_ai_index = i
1410
+ last_ai_message = cast("AIMessage", messages[i])
1411
+ break
1412
+
1413
+ tool_messages = [m for m in messages[last_ai_index + 1 :] if isinstance(m, ToolMessage)]
1414
+ return last_ai_message, tool_messages
1415
+
1416
+
1417
+ def _make_model_to_tools_edge(
1418
+ *,
1419
+ model_destination: str,
1420
+ structured_output_tools: dict[str, OutputToolBinding],
1421
+ end_destination: str,
1422
+ ) -> Callable[[dict[str, Any]], str | list[Send] | None]:
1423
+ def model_to_tools(
1424
+ state: dict[str, Any],
1425
+ ) -> str | list[Send] | None:
1426
+ # 1. if there's an explicit jump_to in the state, use it
1427
+ if jump_to := state.get("jump_to"):
1428
+ return _resolve_jump(
1429
+ jump_to,
1430
+ model_destination=model_destination,
1431
+ end_destination=end_destination,
1432
+ )
1433
+
1434
+ last_ai_message, tool_messages = _fetch_last_ai_and_tool_messages(state["messages"])
1435
+ tool_message_ids = [m.tool_call_id for m in tool_messages]
1436
+
1437
+ # 2. if the model hasn't called any tools, exit the loop
1438
+ # this is the classic exit condition for an agent loop
1439
+ if len(last_ai_message.tool_calls) == 0:
1440
+ return end_destination
1441
+
1442
+ pending_tool_calls = [
1443
+ c
1444
+ for c in last_ai_message.tool_calls
1445
+ if c["id"] not in tool_message_ids and c["name"] not in structured_output_tools
1446
+ ]
1447
+
1448
+ # 3. if there are pending tool calls, jump to the tool node
1449
+ if pending_tool_calls:
1450
+ return [
1451
+ Send(
1452
+ "tools",
1453
+ ToolCallWithContext(
1454
+ __type="tool_call_with_context",
1455
+ tool_call=tool_call,
1456
+ state=state,
1457
+ ),
1458
+ )
1459
+ for tool_call in pending_tool_calls
1460
+ ]
1461
+
1462
+ # 4. if there is a structured response, exit the loop
1463
+ if "structured_response" in state:
1464
+ return end_destination
1465
+
1466
+ # 5. AIMessage has tool calls, but there are no pending tool calls
1467
+ # which suggests the injection of artificial tool messages. jump to the model node
1468
+ return model_destination
1469
+
1470
+ return model_to_tools
1471
+
1472
+
1473
+ def _make_model_to_model_edge(
1474
+ *,
1475
+ model_destination: str,
1476
+ end_destination: str,
1477
+ ) -> Callable[[dict[str, Any]], str | list[Send] | None]:
1478
+ def model_to_model(
1479
+ state: dict[str, Any],
1480
+ ) -> str | list[Send] | None:
1481
+ # 1. Priority: Check for explicit jump_to directive from middleware
1482
+ if jump_to := state.get("jump_to"):
1483
+ return _resolve_jump(
1484
+ jump_to,
1485
+ model_destination=model_destination,
1486
+ end_destination=end_destination,
1487
+ )
1488
+
1489
+ # 2. Exit condition: A structured response was generated
1490
+ if "structured_response" in state:
1491
+ return end_destination
1492
+
1493
+ # 3. Default: Continue the loop, there may have been an issue
1494
+ # with structured output generation, so we need to retry
1495
+ return model_destination
1496
+
1497
+ return model_to_model
1498
+
1499
+
1500
+ def _make_tools_to_model_edge(
1501
+ *,
1502
+ tool_node: _ToolNode,
1503
+ model_destination: str,
1504
+ structured_output_tools: dict[str, OutputToolBinding],
1505
+ end_destination: str,
1506
+ ) -> Callable[[dict[str, Any]], str | None]:
1507
+ def tools_to_model(state: dict[str, Any]) -> str | None:
1508
+ last_ai_message, tool_messages = _fetch_last_ai_and_tool_messages(state["messages"])
1509
+
1510
+ # 1. Exit condition: All executed tools have return_direct=True
1511
+ # Filter to only client-side tools (provider tools are not in tool_node)
1512
+ client_side_tool_calls = [
1513
+ c for c in last_ai_message.tool_calls if c["name"] in tool_node.tools_by_name
1514
+ ]
1515
+ if client_side_tool_calls and all(
1516
+ tool_node.tools_by_name[c["name"]].return_direct for c in client_side_tool_calls
1517
+ ):
1518
+ return end_destination
1519
+
1520
+ # 2. Exit condition: A structured output tool was executed
1521
+ if any(t.name in structured_output_tools for t in tool_messages):
1522
+ return end_destination
1523
+
1524
+ # 3. Default: Continue the loop
1525
+ # Tool execution completed successfully, route back to the model
1526
+ # so it can process the tool results and decide the next action.
1527
+ return model_destination
1528
+
1529
+ return tools_to_model
1530
+
1531
+
1532
+ def _add_middleware_edge(
1533
+ graph: StateGraph[
1534
+ AgentState[ResponseT], ContextT, _InputAgentState, _OutputAgentState[ResponseT]
1535
+ ],
1536
+ *,
1537
+ name: str,
1538
+ default_destination: str,
1539
+ model_destination: str,
1540
+ end_destination: str,
1541
+ can_jump_to: list[JumpTo] | None,
1542
+ ) -> None:
1543
+ """Add an edge to the graph for a middleware node.
1544
+
1545
+ Args:
1546
+ graph: The graph to add the edge to.
1547
+ name: The name of the middleware node.
1548
+ default_destination: The default destination for the edge.
1549
+ model_destination: The destination for the edge to the model.
1550
+ end_destination: The destination for the edge to the end.
1551
+ can_jump_to: The conditionally jumpable destinations for the edge.
1552
+ """
1553
+ if can_jump_to:
1554
+
1555
+ def jump_edge(state: dict[str, Any]) -> str:
1556
+ return (
1557
+ _resolve_jump(
1558
+ state.get("jump_to"),
1559
+ model_destination=model_destination,
1560
+ end_destination=end_destination,
1561
+ )
1562
+ or default_destination
1563
+ )
1564
+
1565
+ destinations = [default_destination]
1566
+
1567
+ if "end" in can_jump_to:
1568
+ destinations.append(end_destination)
1569
+ if "tools" in can_jump_to:
1570
+ destinations.append("tools")
1571
+ if "model" in can_jump_to and name != model_destination:
1572
+ destinations.append(model_destination)
1573
+
1574
+ graph.add_conditional_edges(name, jump_edge, destinations)
1575
+
1576
+ else:
1577
+ graph.add_edge(name, default_destination)
1578
+
1579
+
1580
+ __all__ = [
1581
+ "create_agent",
1582
+ ]