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.
- {langchain-1.0.2 → langchain-1.0.7}/.gitignore +2 -0
- {langchain-1.0.2 → langchain-1.0.7}/Makefile +1 -1
- {langchain-1.0.2 → langchain-1.0.7}/PKG-INFO +8 -4
- {langchain-1.0.2 → langchain-1.0.7}/README.md +1 -1
- {langchain-1.0.2 → langchain-1.0.7}/langchain/__init__.py +1 -1
- langchain-1.0.7/langchain/agents/__init__.py +9 -0
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/factory.py +125 -55
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/__init__.py +3 -7
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/_execution.py +21 -20
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/context_editing.py +15 -11
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/file_search.py +17 -12
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/human_in_the_loop.py +14 -6
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/model_call_limit.py +57 -14
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/model_fallback.py +3 -3
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/pii.py +72 -25
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/shell_tool.py +95 -90
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/summarization.py +2 -2
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/todo.py +6 -6
- langchain-1.0.7/langchain/agents/middleware/tool_call_limit.py +478 -0
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/tool_emulator.py +21 -20
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/tool_retry.py +42 -26
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/tool_selection.py +19 -12
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/types.py +199 -151
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/structured_output.py +8 -2
- langchain-1.0.7/langchain/chat_models/__init__.py +7 -0
- {langchain-1.0.2 → langchain-1.0.7}/langchain/chat_models/base.py +82 -52
- {langchain-1.0.2 → langchain-1.0.7}/langchain/embeddings/__init__.py +1 -6
- {langchain-1.0.2 → langchain-1.0.7}/langchain/embeddings/base.py +22 -16
- {langchain-1.0.2 → langchain-1.0.7}/langchain/messages/__init__.py +7 -6
- {langchain-1.0.2 → langchain-1.0.7}/langchain/tools/__init__.py +1 -7
- langchain-1.0.7/langchain/tools/tool_node.py +20 -0
- {langchain-1.0.2 → langchain-1.0.7}/pyproject.toml +11 -9
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/agents/middleware/test_shell_tool_integration.py +1 -1
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/agents/test_response_format.py +2 -2
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/chat_models/test_base.py +1 -1
- langchain-1.0.7/tests/unit_tests/agents/middleware/implementations/test_shell_tool.py +556 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_override_methods.py +1 -1
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_shell_tool.py +6 -6
- langchain-1.0.7/tests/unit_tests/agents/middleware/test_structured_output_retry.py +369 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_tool_emulator.py +1 -1
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_wrap_model_call_middleware.py +1 -2
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_wrap_tool_call_decorator.py +1 -1
- langchain-1.0.7/tests/unit_tests/agents/test_create_agent_tool_validation.py +370 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_middleware_tools.py +3 -3
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_on_tool_call_middleware.py +1 -1
- langchain-1.0.7/tests/unit_tests/agents/test_parallel_tool_call_limits.py +192 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_response_format.py +51 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_sync_async_tool_wrapper_composition.py +1 -1
- langchain-1.0.7/tests/unit_tests/agents/test_tool_call_limit.py +607 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/chat_models/test_chat_models.py +4 -4
- {langchain-1.0.2 → langchain-1.0.7}/uv.lock +363 -15
- langchain-1.0.2/langchain/agents/__init__.py +0 -15
- langchain-1.0.2/langchain/agents/middleware/tool_call_limit.py +0 -333
- langchain-1.0.2/langchain/chat_models/__init__.py +0 -13
- langchain-1.0.2/langchain/tools/tool_node.py +0 -1786
- langchain-1.0.2/tests/unit_tests/agents/test_tool_call_limit.py +0 -454
- langchain-1.0.2/tests/unit_tests/agents/test_tool_node.py +0 -1716
- langchain-1.0.2/tests/unit_tests/agents/test_tool_node_interceptor_unregistered.py +0 -571
- langchain-1.0.2/tests/unit_tests/agents/test_tool_node_validation_error_filtering.py +0 -678
- langchain-1.0.2/tests/unit_tests/tools/test_on_tool_call.py +0 -1287
- {langchain-1.0.2 → langchain-1.0.7}/LICENSE +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/extended_testing_deps.txt +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/langchain/agents/middleware/_redaction.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/langchain/py.typed +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/langchain/rate_limiters/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/scripts/check_imports.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/agents/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/agents/middleware/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/cache/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/cache/fake_embeddings.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/chat_models/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/conftest.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/embeddings/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/embeddings/test_base.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/integration_tests/test_compile.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/__snapshots__/test_middleware_agent.ambr +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/__snapshots__/test_middleware_decorators.ambr +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/__snapshots__/test_return_direct_graph.ambr +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/any_str.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/compose-postgres.yml +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/compose-redis.yml +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/conftest.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/conftest_checkpointer.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/conftest_store.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/memory_assert.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/messages.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_before_after_agent.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_file_search.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_llm_tool_selection.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_shell_execution_policies.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_tool_retry.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/middleware/test_wrap_model_call_decorator.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/model.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/specifications/responses.json +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/specifications/return_direct.json +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_context_editing_middleware.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_handler_composition.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_injected_runtime_create_agent.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_middleware_agent.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_middleware_decorators.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_model_fallback_middleware.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_pii_middleware.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_react_agent.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_responses.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_responses_spec.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_return_direct_graph.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_return_direct_spec.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_state_schema.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/test_todo_middleware.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/agents/utils.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/chat_models/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/conftest.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/embeddings/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/embeddings/test_base.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/embeddings/test_imports.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/stubs.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/test_dependencies.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/test_imports.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/test_pytest_config.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/tools/__init__.py +0 -0
- {langchain-1.0.2 → langchain-1.0.7}/tests/unit_tests/tools/test_imports.py +0 -0
|
@@ -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.
|
|
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.
|
|
16
|
-
Requires-Dist: langgraph<1.1.0,>=1.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/
|
|
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/
|
|
29
|
+
For full documentation, see the [API reference](https://reference.langchain.com/python/langchain/langchain/).
|
|
30
30
|
|
|
31
31
|
## 📕 Releases & Versioning
|
|
32
32
|
|
|
@@ -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
|
|
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
|
|
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.
|
|
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[
|
|
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.
|
|
532
|
-
|
|
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
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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.
|
|
545
|
-
|
|
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
|
-
|
|
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.
|
|
555
|
-
|
|
556
|
-
(e.g.,
|
|
557
|
-
|
|
558
|
-
|
|
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.
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
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`
|
|
580
|
-
will then call the tools. The tools node executes
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
801
|
-
|
|
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:
|
|
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
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
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
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
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
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
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:
|
|
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 [
|
|
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
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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.
|
|
95
|
-
|
|
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
|
|
99
|
-
shell starts. On macOS, where
|
|
100
|
-
|
|
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
|
-
|
|
203
|
+
`RuntimeError`.
|
|
203
204
|
|
|
204
|
-
Configure sandbox
|
|
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
|
|
275
|
-
it refers to an existing non-temporary directory; ephemeral sessions run
|
|
276
|
-
mount to minimise host exposure. The container's network namespace is
|
|
277
|
-
default (
|
|
278
|
-
|
|
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
|
|
282
|
-
any additional volumes or capabilities passed through ``extra_run_args``. The
|
|
283
|
-
image is
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
with any LangChain
|
|
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
|
-
"""
|
|
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
|
-
|
|
188
|
-
|
|
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
|
-
"""
|
|
204
|
+
"""Initialize an instance of context editing middleware.
|
|
202
205
|
|
|
203
206
|
Args:
|
|
204
|
-
edits: Sequence of edit strategies to apply.
|
|
205
|
-
|
|
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).
|