langchain 1.0.2__tar.gz → 1.0.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. {langchain-1.0.2 → langchain-1.0.7}/.gitignore +2 -0
  2. {langchain-1.0.2 → langchain-1.0.7}/Makefile +1 -1
  3. {langchain-1.0.2 → langchain-1.0.7}/PKG-INFO +8 -4
  4. {langchain-1.0.2 → langchain-1.0.7}/README.md +1 -1
  5. {langchain-1.0.2 → langchain-1.0.7}/langchain/__init__.py +1 -1
  6. langchain-1.0.7/langchain/agents/__init__.py +9 -0
  7. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/factory.py +125 -55
  8. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/__init__.py +3 -7
  9. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/_execution.py +21 -20
  10. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/context_editing.py +15 -11
  11. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/file_search.py +17 -12
  12. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/human_in_the_loop.py +14 -6
  13. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/model_call_limit.py +57 -14
  14. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/model_fallback.py +3 -3
  15. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/pii.py +72 -25
  16. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/shell_tool.py +95 -90
  17. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/summarization.py +2 -2
  18. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/todo.py +6 -6
  19. langchain-1.0.7/langchain/agents/middleware/tool_call_limit.py +478 -0
  20. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/tool_emulator.py +21 -20
  21. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/tool_retry.py +42 -26
  22. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/tool_selection.py +19 -12
  23. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/types.py +199 -151
  24. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/structured_output.py +8 -2
  25. langchain-1.0.7/langchain/chat_models/__init__.py +7 -0
  26. {langchain-1.0.2 → langchain-1.0.7}/langchain/chat_models/base.py +82 -52
  27. {langchain-1.0.2 → langchain-1.0.7}/langchain/embeddings/__init__.py +1 -6
  28. {langchain-1.0.2 → langchain-1.0.7}/langchain/embeddings/base.py +22 -16
  29. {langchain-1.0.2 → langchain-1.0.7}/langchain/messages/__init__.py +7 -6
  30. {langchain-1.0.2 → langchain-1.0.7}/langchain/tools/__init__.py +1 -7
  31. langchain-1.0.7/langchain/tools/tool_node.py +20 -0
  32. {langchain-1.0.2 → langchain-1.0.7}/pyproject.toml +11 -9
  33. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/agents/middleware/test_shell_tool_integration.py +1 -1
  34. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/agents/test_response_format.py +2 -2
  35. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/chat_models/test_base.py +1 -1
  36. langchain-1.0.7/tests/unit_tests/agents/middleware/implementations/test_shell_tool.py +556 -0
  37. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_override_methods.py +1 -1
  38. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_shell_tool.py +6 -6
  39. langchain-1.0.7/tests/unit_tests/agents/middleware/test_structured_output_retry.py +369 -0
  40. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_tool_emulator.py +1 -1
  41. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_wrap_model_call_middleware.py +1 -2
  42. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_wrap_tool_call_decorator.py +1 -1
  43. langchain-1.0.7/tests/unit_tests/agents/test_create_agent_tool_validation.py +370 -0
  44. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_middleware_tools.py +3 -3
  45. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_on_tool_call_middleware.py +1 -1
  46. langchain-1.0.7/tests/unit_tests/agents/test_parallel_tool_call_limits.py +192 -0
  47. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_response_format.py +51 -0
  48. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_sync_async_tool_wrapper_composition.py +1 -1
  49. langchain-1.0.7/tests/unit_tests/agents/test_tool_call_limit.py +607 -0
  50. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/chat_models/test_chat_models.py +4 -4
  51. {langchain-1.0.2 → langchain-1.0.7}/uv.lock +363 -15
  52. langchain-1.0.2/langchain/agents/__init__.py +0 -15
  53. langchain-1.0.2/langchain/agents/middleware/tool_call_limit.py +0 -333
  54. langchain-1.0.2/langchain/chat_models/__init__.py +0 -13
  55. langchain-1.0.2/langchain/tools/tool_node.py +0 -1786
  56. langchain-1.0.2/tests/unit_tests/agents/test_tool_call_limit.py +0 -454
  57. langchain-1.0.2/tests/unit_tests/agents/test_tool_node.py +0 -1716
  58. langchain-1.0.2/tests/unit_tests/agents/test_tool_node_interceptor_unregistered.py +0 -571
  59. langchain-1.0.2/tests/unit_tests/agents/test_tool_node_validation_error_filtering.py +0 -678
  60. langchain-1.0.2/tests/unit_tests/tools/test_on_tool_call.py +0 -1287
  61. {langchain-1.0.2 → langchain-1.0.7}/LICENSE +0 -0
  62. {langchain-1.0.2 → langchain-1.0.7}/extended_testing_deps.txt +0 -0
  63. {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/_redaction.py +0 -0
  64. {langchain-1.0.2 → langchain-1.0.7}/langchain/py.typed +0 -0
  65. {langchain-1.0.2 → langchain-1.0.7}/langchain/rate_limiters/__init__.py +0 -0
  66. {langchain-1.0.2 → langchain-1.0.7}/scripts/check_imports.py +0 -0
  67. {langchain-1.0.2 → langchain-1.0.7}/tests/__init__.py +0 -0
  68. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/__init__.py +0 -0
  69. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/agents/__init__.py +0 -0
  70. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/agents/middleware/__init__.py +0 -0
  71. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/cache/__init__.py +0 -0
  72. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/cache/fake_embeddings.py +0 -0
  73. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/chat_models/__init__.py +0 -0
  74. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/conftest.py +0 -0
  75. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/embeddings/__init__.py +0 -0
  76. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/embeddings/test_base.py +0 -0
  77. {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/test_compile.py +0 -0
  78. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/__init__.py +0 -0
  79. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/__init__.py +0 -0
  80. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/__snapshots__/test_middleware_agent.ambr +0 -0
  81. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/__snapshots__/test_middleware_decorators.ambr +0 -0
  82. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/__snapshots__/test_return_direct_graph.ambr +0 -0
  83. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/any_str.py +0 -0
  84. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/compose-postgres.yml +0 -0
  85. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/compose-redis.yml +0 -0
  86. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/conftest.py +0 -0
  87. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/conftest_checkpointer.py +0 -0
  88. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/conftest_store.py +0 -0
  89. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/memory_assert.py +0 -0
  90. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/messages.py +0 -0
  91. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/__init__.py +0 -0
  92. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_before_after_agent.py +0 -0
  93. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_file_search.py +0 -0
  94. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_llm_tool_selection.py +0 -0
  95. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_shell_execution_policies.py +0 -0
  96. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_tool_retry.py +0 -0
  97. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_wrap_model_call_decorator.py +0 -0
  98. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/model.py +0 -0
  99. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/specifications/responses.json +0 -0
  100. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/specifications/return_direct.json +0 -0
  101. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_context_editing_middleware.py +0 -0
  102. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_handler_composition.py +0 -0
  103. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_injected_runtime_create_agent.py +0 -0
  104. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_middleware_agent.py +0 -0
  105. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_middleware_decorators.py +0 -0
  106. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_model_fallback_middleware.py +0 -0
  107. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_pii_middleware.py +0 -0
  108. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_react_agent.py +0 -0
  109. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_responses.py +0 -0
  110. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_responses_spec.py +0 -0
  111. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_return_direct_graph.py +0 -0
  112. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_return_direct_spec.py +0 -0
  113. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_state_schema.py +0 -0
  114. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_todo_middleware.py +0 -0
  115. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/utils.py +0 -0
  116. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/chat_models/__init__.py +0 -0
  117. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/conftest.py +0 -0
  118. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/embeddings/__init__.py +0 -0
  119. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/embeddings/test_base.py +0 -0
  120. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/embeddings/test_imports.py +0 -0
  121. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/stubs.py +0 -0
  122. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/test_dependencies.py +0 -0
  123. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/test_imports.py +0 -0
  124. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/test_pytest_config.py +0 -0
  125. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/tools/__init__.py +0 -0
  126. {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/tools/test_imports.py +0 -0
@@ -1,6 +1,8 @@
1
1
  .vs/
2
2
  .claude/
3
3
  .idea/
4
+ #Emacs backup
5
+ *~
4
6
  # Byte-compiled / optimized / DLL files
5
7
  __pycache__/
6
8
  *.py[cod]
@@ -28,7 +28,7 @@ coverage:
28
28
  $(TEST_FILE)
29
29
 
30
30
  test:
31
- make start_services && LANGGRAPH_TEST_FAST=0 uv run --group test pytest -n auto --disable-socket --allow-unix-socket $(TEST_FILE) --cov-report term-missing:skip-covered; \
31
+ make start_services && LANGGRAPH_TEST_FAST=0 uv run --no-sync --active --group test pytest -n auto --disable-socket --allow-unix-socket $(TEST_FILE) --cov-report term-missing:skip-covered; \
32
32
  EXIT_CODE=$$?; \
33
33
  make stop_services; \
34
34
  exit $$EXIT_CODE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langchain
3
- Version: 1.0.2
3
+ Version: 1.0.7
4
4
  Summary: Building applications with LLMs through composability
5
5
  Project-URL: Homepage, https://docs.langchain.com/
6
6
  Project-URL: Documentation, https://reference.langchain.com/python/langchain/langchain/
@@ -12,13 +12,15 @@ Project-URL: Reddit, https://www.reddit.com/r/LangChain/
12
12
  License: MIT
13
13
  License-File: LICENSE
14
14
  Requires-Python: <4.0.0,>=3.10.0
15
- Requires-Dist: langchain-core<2.0.0,>=1.0.0
16
- Requires-Dist: langgraph<1.1.0,>=1.0.0
15
+ Requires-Dist: langchain-core<2.0.0,>=1.0.4
16
+ Requires-Dist: langgraph<1.1.0,>=1.0.2
17
17
  Requires-Dist: pydantic<3.0.0,>=2.7.4
18
18
  Provides-Extra: anthropic
19
19
  Requires-Dist: langchain-anthropic; extra == 'anthropic'
20
20
  Provides-Extra: aws
21
21
  Requires-Dist: langchain-aws; extra == 'aws'
22
+ Provides-Extra: azure-ai
23
+ Requires-Dist: langchain-azure-ai; extra == 'azure-ai'
22
24
  Provides-Extra: community
23
25
  Requires-Dist: langchain-community; extra == 'community'
24
26
  Provides-Extra: deepseek
@@ -35,6 +37,8 @@ Provides-Extra: huggingface
35
37
  Requires-Dist: langchain-huggingface; extra == 'huggingface'
36
38
  Provides-Extra: mistralai
37
39
  Requires-Dist: langchain-mistralai; extra == 'mistralai'
40
+ Provides-Extra: model-profiles
41
+ Requires-Dist: langchain-model-profiles; extra == 'model-profiles'
38
42
  Provides-Extra: ollama
39
43
  Requires-Dist: langchain-ollama; extra == 'ollama'
40
44
  Provides-Extra: openai
@@ -75,7 +79,7 @@ LangChain [agents](https://docs.langchain.com/oss/python/langchain/agents) are b
75
79
 
76
80
  ## 📖 Documentation
77
81
 
78
- For full documentation, see the [API reference](https://reference.langchain.com/python/langchain_classic).
82
+ For full documentation, see the [API reference](https://reference.langchain.com/python/langchain/langchain/).
79
83
 
80
84
  ## 📕 Releases & Versioning
81
85
 
@@ -26,7 +26,7 @@ LangChain [agents](https://docs.langchain.com/oss/python/langchain/agents) are b
26
26
 
27
27
  ## 📖 Documentation
28
28
 
29
- For full documentation, see the [API reference](https://reference.langchain.com/python/langchain_classic).
29
+ For full documentation, see the [API reference](https://reference.langchain.com/python/langchain/langchain/).
30
30
 
31
31
  ## 📕 Releases & Versioning
32
32
 
@@ -1,3 +1,3 @@
1
1
  """Main entrypoint into LangChain."""
2
2
 
3
- __version__ = "1.0.1"
3
+ __version__ = "1.0.5"
@@ -0,0 +1,9 @@
1
+ """Entrypoint to building [Agents](https://docs.langchain.com/oss/python/langchain/agents) with LangChain.""" # noqa: E501
2
+
3
+ from langchain.agents.factory import create_agent
4
+ from langchain.agents.middleware.types import AgentState
5
+
6
+ __all__ = [
7
+ "AgentState",
8
+ "create_agent",
9
+ ]
@@ -3,7 +3,15 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import itertools
6
- from typing import TYPE_CHECKING, Annotated, Any, cast, get_args, get_origin, get_type_hints
6
+ from typing import (
7
+ TYPE_CHECKING,
8
+ Annotated,
9
+ Any,
10
+ cast,
11
+ get_args,
12
+ get_origin,
13
+ get_type_hints,
14
+ )
7
15
 
8
16
  from langchain_core.language_models.chat_models import BaseChatModel
9
17
  from langchain_core.messages import AIMessage, AnyMessage, SystemMessage, ToolMessage
@@ -11,10 +19,11 @@ from langchain_core.tools import BaseTool
11
19
  from langgraph._internal._runnable import RunnableCallable
12
20
  from langgraph.constants import END, START
13
21
  from langgraph.graph.state import StateGraph
22
+ from langgraph.prebuilt.tool_node import ToolCallWithContext, ToolNode
14
23
  from langgraph.runtime import Runtime # noqa: TC002
15
24
  from langgraph.types import Command, Send
16
25
  from langgraph.typing import ContextT # noqa: TC002
17
- from typing_extensions import NotRequired, Required, TypedDict, TypeVar
26
+ from typing_extensions import NotRequired, Required, TypedDict
18
27
 
19
28
  from langchain.agents.middleware.types import (
20
29
  AgentMiddleware,
@@ -23,6 +32,8 @@ from langchain.agents.middleware.types import (
23
32
  ModelRequest,
24
33
  ModelResponse,
25
34
  OmitFromSchema,
35
+ ResponseT,
36
+ StateT_co,
26
37
  _InputAgentState,
27
38
  _OutputAgentState,
28
39
  )
@@ -33,11 +44,11 @@ from langchain.agents.structured_output import (
33
44
  ProviderStrategy,
34
45
  ProviderStrategyBinding,
35
46
  ResponseFormat,
47
+ StructuredOutputError,
36
48
  StructuredOutputValidationError,
37
49
  ToolStrategy,
38
50
  )
39
51
  from langchain.chat_models import init_chat_model
40
- from langchain.tools.tool_node import ToolCallWithContext, _ToolNode
41
52
 
42
53
  if TYPE_CHECKING:
43
54
  from collections.abc import Awaitable, Callable, Sequence
@@ -48,12 +59,10 @@ if TYPE_CHECKING:
48
59
  from langgraph.store.base import BaseStore
49
60
  from langgraph.types import Checkpointer
50
61
 
51
- from langchain.tools.tool_node import ToolCallRequest, ToolCallWrapper
62
+ from langchain.agents.middleware.types import ToolCallRequest, ToolCallWrapper
52
63
 
53
64
  STRUCTURED_OUTPUT_ERROR_TEMPLATE = "Error: {error}\n Please fix your mistakes."
54
65
 
55
- ResponseT = TypeVar("ResponseT")
56
-
57
66
 
58
67
  def _normalize_to_model_response(result: ModelResponse | AIMessage) -> ModelResponse:
59
68
  """Normalize middleware return value to ModelResponse."""
@@ -508,7 +517,7 @@ def create_agent( # noqa: PLR0915
508
517
  tools: Sequence[BaseTool | Callable | dict[str, Any]] | None = None,
509
518
  *,
510
519
  system_prompt: str | None = None,
511
- middleware: Sequence[AgentMiddleware[AgentState[ResponseT], ContextT]] = (),
520
+ middleware: Sequence[AgentMiddleware[StateT_co, ContextT]] = (),
512
521
  response_format: ResponseFormat[ResponseT] | type[ResponseT] | None = None,
513
522
  state_schema: type[AgentState[ResponseT]] | None = None,
514
523
  context_schema: type[ContextT] | None = None,
@@ -528,45 +537,88 @@ def create_agent( # noqa: PLR0915
528
537
  visit the [Agents](https://docs.langchain.com/oss/python/langchain/agents) docs.
529
538
 
530
539
  Args:
531
- model: The language model for the agent. Can be a string identifier
532
- (e.g., `"openai:gpt-4"`) or a chat model instance (e.g., `ChatOpenAI()`).
540
+ model: The language model for the agent.
541
+
542
+ Can be a string identifier (e.g., `"openai:gpt-4"`) or a direct chat model
543
+ instance (e.g., [`ChatOpenAI`][langchain_openai.ChatOpenAI] or other another
544
+ [LangChain chat model](https://docs.langchain.com/oss/python/integrations/chat)).
545
+
533
546
  For a full list of supported model strings, see
534
547
  [`init_chat_model`][langchain.chat_models.init_chat_model(model_provider)].
535
- tools: A list of tools, `dicts`, or `Callable`. If `None` or an empty list,
536
- the agent will consist of a model node without a tool calling loop.
537
- system_prompt: An optional system prompt for the LLM. Prompts are converted to a
538
- `SystemMessage` and added to the beginning of the message list.
548
+
549
+ !!! tip ""
550
+
551
+ See the [Models](https://docs.langchain.com/oss/python/langchain/models)
552
+ docs for more information.
553
+ tools: A list of tools, `dict`, or `Callable`.
554
+
555
+ If `None` or an empty list, the agent will consist of a model node without a
556
+ tool calling loop.
557
+
558
+
559
+ !!! tip ""
560
+
561
+ See the [Tools](https://docs.langchain.com/oss/python/langchain/tools)
562
+ docs for more information.
563
+ system_prompt: An optional system prompt for the LLM.
564
+
565
+ Prompts are converted to a
566
+ [`SystemMessage`][langchain.messages.SystemMessage] and added to the
567
+ beginning of the message list.
539
568
  middleware: A sequence of middleware instances to apply to the agent.
569
+
540
570
  Middleware can intercept and modify agent behavior at various stages.
571
+
572
+ !!! tip ""
573
+
574
+ See the [Middleware](https://docs.langchain.com/oss/python/langchain/middleware)
575
+ docs for more information.
541
576
  response_format: An optional configuration for structured responses.
577
+
542
578
  Can be a `ToolStrategy`, `ProviderStrategy`, or a Pydantic model class.
579
+
543
580
  If provided, the agent will handle structured output during the
544
- conversation flow. Raw schemas will be wrapped in an appropriate strategy
545
- based on model capabilities.
581
+ conversation flow.
582
+
583
+ Raw schemas will be wrapped in an appropriate strategy based on model
584
+ capabilities.
585
+
586
+ !!! tip ""
587
+
588
+ See the [Structured output](https://docs.langchain.com/oss/python/langchain/structured-output)
589
+ docs for more information.
546
590
  state_schema: An optional `TypedDict` schema that extends `AgentState`.
591
+
547
592
  When provided, this schema is used instead of `AgentState` as the base
548
593
  schema for merging with middleware state schemas. This allows users to
549
594
  add custom state fields without needing to create custom middleware.
550
- Generally, it's recommended to use state_schema extensions via middleware
595
+
596
+ Generally, it's recommended to use `state_schema` extensions via middleware
551
597
  to keep relevant extensions scoped to corresponding hooks / tools.
552
- The schema must be a subclass of `AgentState[ResponseT]`.
553
598
  context_schema: An optional schema for runtime context.
554
- checkpointer: An optional checkpoint saver object. This is used for persisting
555
- the state of the graph (e.g., as chat memory) for a single thread
556
- (e.g., a single conversation).
557
- store: An optional store object. This is used for persisting data
558
- across multiple threads (e.g., multiple conversations / users).
599
+ checkpointer: An optional checkpoint saver object.
600
+
601
+ Used for persisting the state of the graph (e.g., as chat memory) for a
602
+ single thread (e.g., a single conversation).
603
+ store: An optional store object.
604
+
605
+ Used for persisting data across multiple threads (e.g., multiple
606
+ conversations / users).
559
607
  interrupt_before: An optional list of node names to interrupt before.
608
+
560
609
  Useful if you want to add a user confirmation or other interrupt
561
610
  before taking an action.
562
611
  interrupt_after: An optional list of node names to interrupt after.
612
+
563
613
  Useful if you want to return directly or run additional processing
564
614
  on an output.
565
- debug: Whether to enable verbose logging for graph execution. When enabled,
566
- prints detailed information about each node execution, state updates,
567
- and transitions during agent runtime. Useful for debugging middleware
568
- behavior and understanding agent execution flow.
615
+ debug: Whether to enable verbose logging for graph execution.
616
+
617
+ When enabled, prints detailed information about each node execution, state
618
+ updates, and transitions during agent runtime. Useful for debugging
619
+ middleware behavior and understanding agent execution flow.
569
620
  name: An optional name for the `CompiledStateGraph`.
621
+
570
622
  This name will be automatically used when adding the agent graph to
571
623
  another graph as a subgraph node - particularly useful for building
572
624
  multi-agent systems.
@@ -576,11 +628,12 @@ def create_agent( # noqa: PLR0915
576
628
  A compiled `StateGraph` that can be used for chat interactions.
577
629
 
578
630
  The agent node calls the language model with the messages list (after applying
579
- the system prompt). If the resulting `AIMessage` contains `tool_calls`, the graph
580
- will then call the tools. The tools node executes the tools and adds the responses
581
- to the messages list as `ToolMessage` objects. The agent node then calls the
582
- language model again. The process repeats until no more `tool_calls` are
583
- present in the response. The agent then returns the full list of messages.
631
+ the system prompt). If the resulting [`AIMessage`][langchain.messages.AIMessage]
632
+ contains `tool_calls`, the graph will then call the tools. The tools node executes
633
+ the tools and adds the responses to the messages list as
634
+ [`ToolMessage`][langchain.messages.ToolMessage] objects. The agent node then calls
635
+ the language model again. The process repeats until no more `tool_calls` are present
636
+ in the response. The agent then returns the full list of messages.
584
637
 
585
638
  Example:
586
639
  ```python
@@ -593,7 +646,7 @@ def create_agent( # noqa: PLR0915
593
646
 
594
647
 
595
648
  graph = create_agent(
596
- model="anthropic:claude-sonnet-4-5",
649
+ model="anthropic:claude-sonnet-4-5-20250929",
597
650
  tools=[check_weather],
598
651
  system_prompt="You are a helpful assistant",
599
652
  )
@@ -675,7 +728,7 @@ def create_agent( # noqa: PLR0915
675
728
  awrap_tool_call_wrapper = _chain_async_tool_call_wrappers(async_wrappers)
676
729
 
677
730
  # Setup tools
678
- tool_node: _ToolNode | None = None
731
+ tool_node: ToolNode | None = None
679
732
  # Extract built-in provider tools (dict format) and regular tools (BaseTool/callables)
680
733
  built_in_tools = [t for t in tools if isinstance(t, dict)]
681
734
  regular_tools = [t for t in tools if not isinstance(t, dict)]
@@ -685,7 +738,7 @@ def create_agent( # noqa: PLR0915
685
738
 
686
739
  # Only create ToolNode if we have client-side tools
687
740
  tool_node = (
688
- _ToolNode(
741
+ ToolNode(
689
742
  tools=available_tools,
690
743
  wrap_tool_call=wrap_tool_call_wrapper,
691
744
  awrap_tool_call=awrap_tool_call_wrapper,
@@ -762,7 +815,7 @@ def create_agent( # noqa: PLR0915
762
815
  async_handlers = [m.awrap_model_call for m in middleware_w_awrap_model_call]
763
816
  awrap_model_call_handler = _chain_async_model_call_handlers(async_handlers)
764
817
 
765
- state_schemas = {m.state_schema for m in middleware}
818
+ state_schemas: set[type] = {m.state_schema for m in middleware}
766
819
  # Use provided state_schema if available, otherwise use base AgentState
767
820
  base_state = state_schema if state_schema is not None else AgentState
768
821
  state_schemas.add(base_state)
@@ -797,8 +850,16 @@ def create_agent( # noqa: PLR0915
797
850
  provider_strategy_binding = ProviderStrategyBinding.from_schema_spec(
798
851
  effective_response_format.schema_spec
799
852
  )
800
- structured_response = provider_strategy_binding.parse(output)
801
- return {"messages": [output], "structured_response": structured_response}
853
+ try:
854
+ structured_response = provider_strategy_binding.parse(output)
855
+ except Exception as exc: # noqa: BLE001
856
+ schema_name = getattr(
857
+ effective_response_format.schema_spec.schema, "__name__", "response_format"
858
+ )
859
+ validation_error = StructuredOutputValidationError(schema_name, exc, output)
860
+ raise validation_error
861
+ else:
862
+ return {"messages": [output], "structured_response": structured_response}
802
863
  return {"messages": [output]}
803
864
 
804
865
  # Handle structured output with tool strategy
@@ -812,11 +873,11 @@ def create_agent( # noqa: PLR0915
812
873
  ]
813
874
 
814
875
  if structured_tool_calls:
815
- exception: Exception | None = None
876
+ exception: StructuredOutputError | None = None
816
877
  if len(structured_tool_calls) > 1:
817
878
  # Handle multiple structured outputs error
818
879
  tool_names = [tc["name"] for tc in structured_tool_calls]
819
- exception = MultipleStructuredOutputsError(tool_names)
880
+ exception = MultipleStructuredOutputsError(tool_names, output)
820
881
  should_retry, error_message = _handle_structured_output_error(
821
882
  exception, effective_response_format
822
883
  )
@@ -858,7 +919,7 @@ def create_agent( # noqa: PLR0915
858
919
  "structured_response": structured_response,
859
920
  }
860
921
  except Exception as exc: # noqa: BLE001
861
- exception = StructuredOutputValidationError(tool_call["name"], exc)
922
+ exception = StructuredOutputValidationError(tool_call["name"], exc, output)
862
923
  should_retry, error_message = _handle_structured_output_error(
863
924
  exception, effective_response_format
864
925
  )
@@ -1229,11 +1290,14 @@ def create_agent( # noqa: PLR0915
1229
1290
 
1230
1291
  graph.add_conditional_edges(
1231
1292
  "tools",
1232
- _make_tools_to_model_edge(
1233
- tool_node=tool_node,
1234
- model_destination=loop_entry_node,
1235
- structured_output_tools=structured_output_tools,
1236
- end_destination=exit_node,
1293
+ RunnableCallable(
1294
+ _make_tools_to_model_edge(
1295
+ tool_node=tool_node,
1296
+ model_destination=loop_entry_node,
1297
+ structured_output_tools=structured_output_tools,
1298
+ end_destination=exit_node,
1299
+ ),
1300
+ trace=False,
1237
1301
  ),
1238
1302
  tools_to_model_destinations,
1239
1303
  )
@@ -1250,19 +1314,25 @@ def create_agent( # noqa: PLR0915
1250
1314
 
1251
1315
  graph.add_conditional_edges(
1252
1316
  loop_exit_node,
1253
- _make_model_to_tools_edge(
1254
- model_destination=loop_entry_node,
1255
- structured_output_tools=structured_output_tools,
1256
- end_destination=exit_node,
1317
+ RunnableCallable(
1318
+ _make_model_to_tools_edge(
1319
+ model_destination=loop_entry_node,
1320
+ structured_output_tools=structured_output_tools,
1321
+ end_destination=exit_node,
1322
+ ),
1323
+ trace=False,
1257
1324
  ),
1258
1325
  model_to_tools_destinations,
1259
1326
  )
1260
1327
  elif len(structured_output_tools) > 0:
1261
1328
  graph.add_conditional_edges(
1262
1329
  loop_exit_node,
1263
- _make_model_to_model_edge(
1264
- model_destination=loop_entry_node,
1265
- end_destination=exit_node,
1330
+ RunnableCallable(
1331
+ _make_model_to_model_edge(
1332
+ model_destination=loop_entry_node,
1333
+ end_destination=exit_node,
1334
+ ),
1335
+ trace=False,
1266
1336
  ),
1267
1337
  [loop_entry_node, exit_node],
1268
1338
  )
@@ -1372,7 +1442,7 @@ def create_agent( # noqa: PLR0915
1372
1442
  debug=debug,
1373
1443
  name=name,
1374
1444
  cache=cache,
1375
- )
1445
+ ).with_config({"recursion_limit": 10_000})
1376
1446
 
1377
1447
 
1378
1448
  def _resolve_jump(
@@ -1491,7 +1561,7 @@ def _make_model_to_model_edge(
1491
1561
 
1492
1562
  def _make_tools_to_model_edge(
1493
1563
  *,
1494
- tool_node: _ToolNode,
1564
+ tool_node: ToolNode,
1495
1565
  model_destination: str,
1496
1566
  structured_output_tools: dict[str, OutputToolBinding],
1497
1567
  end_destination: str,
@@ -1563,7 +1633,7 @@ def _add_middleware_edge(
1563
1633
  if "model" in can_jump_to and name != model_destination:
1564
1634
  destinations.append(model_destination)
1565
1635
 
1566
- graph.add_conditional_edges(name, jump_edge, destinations)
1636
+ graph.add_conditional_edges(name, RunnableCallable(jump_edge, trace=False), destinations)
1567
1637
 
1568
1638
  else:
1569
1639
  graph.add_edge(name, default_destination)
@@ -1,15 +1,10 @@
1
- """Entrypoint to using [Middleware](https://docs.langchain.com/oss/python/langchain/middleware) plugins with [Agents](https://docs.langchain.com/oss/python/langchain/agents).
2
-
3
- !!! warning "Reference docs"
4
- This page contains **reference documentation** for Middleware. See
5
- [the docs](https://docs.langchain.com/oss/python/langchain/middleware) for conceptual
6
- guides, tutorials, and examples on using Middleware.
7
- """ # noqa: E501
1
+ """Entrypoint to using [middleware](https://docs.langchain.com/oss/python/langchain/middleware) plugins with [Agents](https://docs.langchain.com/oss/python/langchain/agents).""" # noqa: E501
8
2
 
9
3
  from .context_editing import (
10
4
  ClearToolUsesEdit,
11
5
  ContextEditingMiddleware,
12
6
  )
7
+ from .file_search import FilesystemFileSearchMiddleware
13
8
  from .human_in_the_loop import (
14
9
  HumanInTheLoopMiddleware,
15
10
  InterruptOnConfig,
@@ -52,6 +47,7 @@ __all__ = [
52
47
  "CodexSandboxExecutionPolicy",
53
48
  "ContextEditingMiddleware",
54
49
  "DockerExecutionPolicy",
50
+ "FilesystemFileSearchMiddleware",
55
51
  "HostExecutionPolicy",
56
52
  "HumanInTheLoopMiddleware",
57
53
  "InterruptOnConfig",
@@ -56,11 +56,12 @@ class BaseExecutionPolicy(abc.ABC):
56
56
  """Configuration contract for persistent shell sessions.
57
57
 
58
58
  Concrete subclasses encapsulate how a shell process is launched and constrained.
59
+
59
60
  Each policy documents its security guarantees and the operating environments in
60
- which it is appropriate. Use :class:`HostExecutionPolicy` for trusted, same-host
61
- execution; :class:`CodexSandboxExecutionPolicy` when the Codex CLI sandbox is
62
- available and you want additional syscall restrictions; and
63
- :class:`DockerExecutionPolicy` for container-level isolation using Docker.
61
+ which it is appropriate. Use `HostExecutionPolicy` for trusted, same-host execution;
62
+ `CodexSandboxExecutionPolicy` when the Codex CLI sandbox is available and you want
63
+ additional syscall restrictions; and `DockerExecutionPolicy` for container-level
64
+ isolation using Docker.
64
65
  """
65
66
 
66
67
  command_timeout: float = 30.0
@@ -91,13 +92,13 @@ class HostExecutionPolicy(BaseExecutionPolicy):
91
92
 
92
93
  This policy is best suited for trusted or single-tenant environments (CI jobs,
93
94
  developer workstations, pre-sandboxed containers) where the agent must access the
94
- host filesystem and tooling without additional isolation. It enforces optional CPU
95
- and memory limits to prevent runaway commands but offers **no** filesystem or network
95
+ host filesystem and tooling without additional isolation. Enforces optional CPU and
96
+ memory limits to prevent runaway commands but offers **no** filesystem or network
96
97
  sandboxing; commands can modify anything the process user can reach.
97
98
 
98
- On Linux platforms resource limits are applied with ``resource.prlimit`` after the
99
- shell starts. On macOS, where ``prlimit`` is unavailable, limits are set in a
100
- ``preexec_fn`` before ``exec``. In both cases the shell runs in its own process group
99
+ On Linux platforms resource limits are applied with `resource.prlimit` after the
100
+ shell starts. On macOS, where `prlimit` is unavailable, limits are set in a
101
+ `preexec_fn` before `exec`. In both cases the shell runs in its own process group
101
102
  so timeouts can terminate the full subtree.
102
103
  """
103
104
 
@@ -199,9 +200,9 @@ class CodexSandboxExecutionPolicy(BaseExecutionPolicy):
199
200
  (Linux) profiles. Commands still run on the host, but within the sandbox requested by
200
201
  the CLI. If the Codex binary is unavailable or the runtime lacks the required
201
202
  kernel features (e.g., Landlock inside some containers), process startup fails with a
202
- :class:`RuntimeError`.
203
+ `RuntimeError`.
203
204
 
204
- Configure sandbox behaviour via ``config_overrides`` to align with your Codex CLI
205
+ Configure sandbox behavior via `config_overrides` to align with your Codex CLI
205
206
  profile. This policy does not add its own resource limits; combine it with
206
207
  host-level guards (cgroups, container resource limits) as needed.
207
208
  """
@@ -271,17 +272,17 @@ class DockerExecutionPolicy(BaseExecutionPolicy):
271
272
  """Run the shell inside a dedicated Docker container.
272
273
 
273
274
  Choose this policy when commands originate from untrusted users or you require
274
- strong isolation between sessions. By default the workspace is bind-mounted only when
275
- it refers to an existing non-temporary directory; ephemeral sessions run without a
276
- mount to minimise host exposure. The container's network namespace is disabled by
277
- default (``--network none``) and you can enable further hardening via
278
- ``read_only_rootfs`` and ``user``.
275
+ strong isolation between sessions. By default the workspace is bind-mounted only
276
+ when it refers to an existing non-temporary directory; ephemeral sessions run
277
+ without a mount to minimise host exposure. The container's network namespace is
278
+ disabled by default (`--network none`) and you can enable further hardening via
279
+ `read_only_rootfs` and `user`.
279
280
 
280
281
  The security guarantees depend on your Docker daemon configuration. Run the agent on
281
- a host where Docker is locked down (rootless mode, AppArmor/SELinux, etc.) and review
282
- any additional volumes or capabilities passed through ``extra_run_args``. The default
283
- image is ``python:3.12-alpine3.19``; supply a custom image if you need preinstalled
284
- tooling.
282
+ a host where Docker is locked down (rootless mode, AppArmor/SELinux, etc.) and
283
+ review any additional volumes or capabilities passed through ``extra_run_args``. The
284
+ default image is `python:3.12-alpine3.19`; supply a custom image if you need
285
+ preinstalled tooling.
285
286
  """
286
287
 
287
288
  binary: str = "docker"
@@ -1,9 +1,10 @@
1
1
  """Context editing middleware.
2
2
 
3
- This middleware mirrors Anthropic's context editing capabilities by clearing
4
- older tool results once the conversation grows beyond a configurable token
5
- threshold. The implementation is intentionally model-agnostic so it can be used
6
- with any LangChain chat model.
3
+ Mirrors Anthropic's context editing capabilities by clearing older tool results once the
4
+ conversation grows beyond a configurable token threshold.
5
+
6
+ The implementation is intentionally model-agnostic so it can be used with any LangChain
7
+ chat model.
7
8
  """
8
9
 
9
10
  from __future__ import annotations
@@ -182,11 +183,13 @@ class ClearToolUsesEdit(ContextEdit):
182
183
 
183
184
 
184
185
  class ContextEditingMiddleware(AgentMiddleware):
185
- """Middleware that automatically prunes tool results to manage context size.
186
+ """Automatically prune tool results to manage context size.
187
+
188
+ The middleware applies a sequence of edits when the total input token count exceeds
189
+ configured thresholds.
186
190
 
187
- The middleware applies a sequence of edits when the total input token count
188
- exceeds configured thresholds. Currently the `ClearToolUsesEdit` strategy is
189
- supported, aligning with Anthropic's `clear_tool_uses_20250919` behaviour.
191
+ Currently the `ClearToolUsesEdit` strategy is supported, aligning with Anthropic's
192
+ `clear_tool_uses_20250919` behavior [(read more)](https://docs.claude.com/en/docs/agents-and-tools/tool-use/memory-tool).
190
193
  """
191
194
 
192
195
  edits: list[ContextEdit]
@@ -198,11 +201,12 @@ class ContextEditingMiddleware(AgentMiddleware):
198
201
  edits: Iterable[ContextEdit] | None = None,
199
202
  token_count_method: Literal["approximate", "model"] = "approximate", # noqa: S107
200
203
  ) -> None:
201
- """Initializes a context editing middleware instance.
204
+ """Initialize an instance of context editing middleware.
202
205
 
203
206
  Args:
204
- edits: Sequence of edit strategies to apply. Defaults to a single
205
- `ClearToolUsesEdit` mirroring Anthropic defaults.
207
+ edits: Sequence of edit strategies to apply.
208
+
209
+ Defaults to a single `ClearToolUsesEdit` mirroring Anthropic defaults.
206
210
  token_count_method: Whether to use approximate token counting
207
211
  (faster, less accurate) or exact counting implemented by the
208
212
  chat model (potentially slower, more accurate).