langchain-dev-utils 1.4.2__tar.gz → 1.4.4__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 (72) hide show
  1. langchain_dev_utils-1.4.4/AGENTS.md +285 -0
  2. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/PKG-INFO +5 -2
  3. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/README.md +4 -1
  4. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/pyproject.toml +2 -2
  5. langchain_dev_utils-1.4.4/src/langchain_dev_utils/__init__.py +1 -0
  6. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/factory.py +17 -4
  7. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/middleware/handoffs.py +23 -22
  8. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/chat_models/base.py +3 -4
  9. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/chat_models/types.py +2 -1
  10. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/embeddings/base.py +4 -6
  11. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/tool_calling/human_in_the_loop.py +2 -1
  12. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_handoffs_middleware.py +0 -4
  13. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/uv.lock +987 -977
  14. langchain_dev_utils-1.4.2/AGENTS.md +0 -173
  15. langchain_dev_utils-1.4.2/src/langchain_dev_utils/__init__.py +0 -1
  16. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/.gitignore +0 -0
  17. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/.python-version +0 -0
  18. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/.vscode/settings.json +0 -0
  19. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/LICENSE +0 -0
  20. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/README_cn.md +0 -0
  21. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/_utils.py +0 -0
  22. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/__init__.py +0 -0
  23. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/middleware/__init__.py +0 -0
  24. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/middleware/format_prompt.py +0 -0
  25. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/middleware/model_fallback.py +0 -0
  26. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/middleware/model_router.py +0 -0
  27. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/middleware/plan.py +0 -0
  28. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/middleware/summarization.py +0 -0
  29. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/middleware/tool_call_repair.py +0 -0
  30. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/middleware/tool_emulator.py +0 -0
  31. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/middleware/tool_selection.py +0 -0
  32. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/agents/wrap.py +0 -0
  33. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/chat_models/__init__.py +0 -0
  34. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/chat_models/adapters/__init__.py +0 -0
  35. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/chat_models/adapters/create_utils.py +0 -0
  36. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/chat_models/adapters/openai_compatible.py +0 -0
  37. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/chat_models/adapters/register_profiles.py +0 -0
  38. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/embeddings/__init__.py +0 -0
  39. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/embeddings/adapters/__init__.py +0 -0
  40. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/embeddings/adapters/create_utils.py +0 -0
  41. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/embeddings/adapters/openai_compatible.py +0 -0
  42. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/graph/__init__.py +0 -0
  43. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/graph/parallel.py +0 -0
  44. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/graph/sequential.py +0 -0
  45. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/graph/types.py +0 -0
  46. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/message_convert/__init__.py +0 -0
  47. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/message_convert/content.py +0 -0
  48. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/message_convert/format.py +0 -0
  49. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/pipeline/__init__.py +0 -0
  50. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/pipeline/parallel.py +0 -0
  51. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/pipeline/sequential.py +0 -0
  52. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/pipeline/types.py +0 -0
  53. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/py.typed +0 -0
  54. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/tool_calling/__init__.py +0 -0
  55. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/src/langchain_dev_utils/tool_calling/utils.py +0 -0
  56. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/__init__.py +0 -0
  57. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_agent.py +0 -0
  58. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_chat_models.py +0 -0
  59. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_embedding.py +0 -0
  60. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_graph.py +0 -0
  61. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_human_in_the_loop.py +0 -0
  62. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_load_embbeding.py +0 -0
  63. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_load_model.py +0 -0
  64. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_messages.py +0 -0
  65. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_model_tool_emulator.py +0 -0
  66. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_plan_middleware.py +0 -0
  67. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_router_model.py +0 -0
  68. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_tool_call_repair.py +0 -0
  69. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_tool_calling.py +0 -0
  70. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/test_wrap_agent.py +0 -0
  71. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/utils/__init__.py +0 -0
  72. {langchain_dev_utils-1.4.2 → langchain_dev_utils-1.4.4}/tests/utils/register.py +0 -0
@@ -0,0 +1,285 @@
1
+ # Agentic Coding Guidelines for langchain-dev-utils
2
+
3
+ This file provides guidelines for AI agents working in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ A Python utility library for LangChain and LangGraph development. Uses hatchling build system, uv for package management, ruff for linting, and pytest for testing.
8
+
9
+ **Current Version:** 1.4.4
10
+
11
+ ---
12
+
13
+ ## Build/Lint/Test Commands
14
+
15
+ ### Package Management (uv)
16
+ ```bash
17
+ # Install dependencies
18
+ uv sync
19
+
20
+ # Install with optional dependencies
21
+ uv sync --extra standard
22
+
23
+ # Install dev dependencies
24
+ uv sync --group dev
25
+
26
+ # Install test dependencies
27
+ uv sync --group tests
28
+
29
+ # Install docs dependencies
30
+ uv sync --group docs
31
+ ```
32
+
33
+ ### Linting & Formatting (ruff)
34
+ ```bash
35
+ # Check linting
36
+ uv run ruff check .
37
+
38
+ # Check specific file
39
+ uv run ruff check src/langchain_dev_utils/path/to/file.py
40
+
41
+ # Fix auto-fixable issues
42
+ uv run ruff check --fix .
43
+
44
+ # Format code
45
+ uv run ruff format .
46
+
47
+ # Format specific file
48
+ uv run ruff format src/langchain_dev_utils/path/to/file.py
49
+ ```
50
+
51
+ ### Testing (pytest)
52
+ ```bash
53
+ # Run all tests
54
+ uv run pytest
55
+
56
+ # Run with verbose output
57
+ uv run pytest -v
58
+
59
+ # Run specific test file
60
+ uv run pytest tests/test_agent.py
61
+
62
+ # Run specific test function
63
+ uv run pytest tests/test_agent.py::test_prebuilt_agent
64
+
65
+ # Run specific test class
66
+ uv run pytest tests/test_chat_models.py::TestImageProcessing
67
+
68
+ # Run with asyncio support (automatically configured)
69
+ uv run pytest -s
70
+
71
+ # Run tests matching pattern
72
+ uv run pytest -k "test_load"
73
+ ```
74
+
75
+ ### Build
76
+ ```bash
77
+ # Build package
78
+ uv build
79
+
80
+ # Build wheel only
81
+ uv build --wheel
82
+ ```
83
+
84
+ ### Documentation
85
+ ```bash
86
+ # Serve docs locally
87
+ mkdocs serve
88
+
89
+ # Build docs
90
+ mkdocs build
91
+
92
+ # Deploy docs
93
+ mkdocs gh-deploy
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Code Style Guidelines
99
+
100
+ ### Imports
101
+ - Use absolute imports for external packages
102
+ - Use relative imports within the package (e.g., `from ..chat_models import ...`)
103
+ - Group imports: stdlib → third-party → local
104
+ - Ruff handles import sorting automatically
105
+
106
+ ### Type Hints
107
+ - Use type hints for all function parameters and return types
108
+ - Use `Optional[Type]` or `Type | None` for nullable types (both acceptable)
109
+ - Use `Any` sparingly and only when necessary
110
+ - Use `Sequence`, `Mapping` for generic collections
111
+ - Use generics with TypeVars where appropriate
112
+
113
+ ### Naming Conventions
114
+ - `snake_case` for functions, methods, variables
115
+ - `PascalCase` for classes
116
+ - `UPPER_CASE` for constants
117
+ - `_leading_underscore` for private/internal functions
118
+ - Leading double underscore for name mangling when needed
119
+
120
+ ### Docstrings
121
+ - Use Google-style docstrings
122
+ - Include Args, Returns, Raises sections for public functions
123
+ - Include Examples section for complex functions
124
+ - Keep docstrings under 100 characters per line when possible
125
+
126
+ ### Code Structure
127
+ - Maximum line length: 88 characters (ruff enforces, E501 ignored)
128
+ - Use trailing commas in multi-line structures
129
+ - Two blank lines between top-level functions/classes
130
+ - One blank line between methods
131
+
132
+ ### Error Handling
133
+ - Use specific exception types, not bare `except:`
134
+ - Provide descriptive error messages with f-strings
135
+ - Use `raise ValueError(msg)` pattern with descriptive messages
136
+ - Avoid bare `raise` statements
137
+
138
+ ### Async Code
139
+ - Use `pytest.mark.asyncio` for async test functions
140
+ - Use `async`/`await` consistently
141
+ - Prefer `asyncio` primitives from standard library
142
+
143
+ ### Ruff Configuration
144
+ - Enabled rules: E, F, I, PGH003, T201
145
+ - Import sorting (I) is enforced
146
+ - No print statements in production code (T201)
147
+
148
+ ---
149
+
150
+ ## Testing Guidelines
151
+
152
+ - Tests live in `tests/` directory
153
+ - Test files named `test_*.py`
154
+ - Test functions named `test_*`
155
+ - Use pytest fixtures for setup/teardown
156
+ - Use `pytest.mark.asyncio` for async tests
157
+ - Mock external API calls in unit tests
158
+ - Integration tests use actual APIs (marked implicitly by test names)
159
+ - Tests use `langchain-tests` for standard integration test suites
160
+
161
+ ---
162
+
163
+ ## Project Structure
164
+
165
+ ```
166
+ langchain-dev-utils/
167
+ ├── src/langchain_dev_utils/ # Source code
168
+ │ ├── agents/ # Agent utilities
169
+ │ │ ├── factory.py # Agent creation functions
170
+ │ │ ├── wrap.py # Agent wrapping utilities
171
+ │ │ └── middleware/ # Agent middleware components
172
+ │ │ ├── format_prompt.py # Format prompt middleware
173
+ │ │ ├── handoffs.py # Multi-agent handoff middleware
174
+ │ │ ├── model_fallback.py # Model fallback middleware
175
+ │ │ ├── model_router.py # Model routing middleware
176
+ │ │ ├── plan.py # Planning middleware
177
+ │ │ ├── summarization.py # Message summarization middleware
178
+ │ │ ├── tool_call_repair.py # Tool call repair middleware
179
+ │ │ ├── tool_emulator.py # LLM tool emulator middleware
180
+ │ │ └── tool_selection.py # LLM tool selector middleware
181
+ │ ├── chat_models/ # Chat model utilities
182
+ │ │ ├── base.py # Base chat model classes
183
+ │ │ ├── types.py # Type definitions
184
+ │ │ └── adapters/ # Model provider adapters
185
+ │ ├── embeddings/ # Embedding utilities
186
+ │ │ ├── base.py # Base embedding classes
187
+ │ │ └── adapters/ # Embedding provider adapters
188
+ │ ├── graph/ # Graph utilities
189
+ │ │ ├── parallel.py # Parallel graph construction
190
+ │ │ ├── sequential.py # Sequential graph construction
191
+ │ │ └── types.py # Graph type definitions
192
+ │ ├── message_convert/ # Message conversion utilities
193
+ │ │ ├── content.py # Content conversion
194
+ │ │ └── format.py # Message formatting
195
+ │ ├── pipeline/ # Pipeline utilities (deprecated since v1.4.0, will be removed in v1.5.0)
196
+ │ │ ├── parallel.py
197
+ │ │ ├── sequential.py
198
+ │ │ └── types.py
199
+ │ └── tool_calling/ # Tool calling utilities
200
+ │ ├── human_in_the_loop.py # Human review functionality
201
+ │ └── utils.py # Tool calling utilities
202
+ ├── tests/ # Test files
203
+ ├── docs/ # Documentation (MkDocs)
204
+ │ ├── en/ # English documentation
205
+ │ └── zh/ # Chinese documentation
206
+ ├── pyproject.toml # Project configuration
207
+ ├── uv.lock # Dependency lock file
208
+ └── mkdocs.yml # MkDocs configuration
209
+ ```
210
+
211
+ ---
212
+
213
+ ## Middleware Components
214
+
215
+ The `agents.middleware` module provides reusable middleware components for agent enhancement:
216
+
217
+ | Middleware | Purpose |
218
+ |------------|---------|
219
+ | `SummarizationMiddleware` | Summarizes long message histories |
220
+ | `LLMToolSelectorMiddleware` | Uses LLM to select appropriate tools |
221
+ | `PlanMiddleware` | Adds planning capabilities to agents |
222
+ | `ModelFallbackMiddleware` | Provides fallback to alternative models |
223
+ | `LLMToolEmulator` | Emulates tool calling for models without native support |
224
+ | `ModelRouterMiddleware` | Routes requests to different models based on criteria |
225
+ | `ToolCallRepairMiddleware` | Repairs malformed tool calls |
226
+ | `FormatPromptMiddleware` | Formats prompts with templates |
227
+ | `HandoffAgentMiddleware` | Enables multi-agent handoff workflows |
228
+
229
+ ---
230
+
231
+ ## Dependencies
232
+
233
+ ### Core Dependencies
234
+ - `langchain>=1.2.0` - LangChain framework
235
+ - `langchain-core>=1.2.5` - Core LangChain components
236
+ - `langgraph>=1.0.0` - LangGraph for graph-based workflows
237
+
238
+ ### Optional Dependencies (standard)
239
+ - `jinja2>=3.1.6` - Template engine for prompt formatting
240
+ - `json-repair>=0.53.1` - JSON repair utilities
241
+ - `langchain-openai` - OpenAI integration
242
+
243
+ ### Dev Dependencies
244
+ - `langchain-model-profiles>=0.0.5` - Model profile management
245
+ - `ruff>=0.14.5` - Linting and formatting
246
+
247
+ ### Docs Dependencies
248
+ - `jupyter>=1.1.1` - Jupyter notebook support
249
+ - `mkdocs-material>=9.7.0` - Material theme for MkDocs
250
+ - `mkdocs-static-i18n>=1.3.0` - Internationalization support
251
+
252
+ ### Test Dependencies
253
+ - `python-dotenv>=1.1.1` - Environment variable management
254
+ - `langchain-tests>=1.0.0` - Standard LangChain test suite
255
+ - `langchain-deepseek>=1.0.0` - DeepSeek model integration
256
+ - `langchain-qwq>=0.3.0` - QwQ model integration
257
+ - `langchain-ollama>=1.0.0` - Ollama integration
258
+ - `langchain-community>=0.4.1` - Community model integrations
259
+ - `dashscope>=1.25.12` - Alibaba DashScope integration
260
+
261
+ **Python version:** >=3.11
262
+
263
+ ---
264
+
265
+ ## Documentation
266
+
267
+ - Documentation is built with MkDocs using the Material theme
268
+ - Supports internationalization (English and Chinese)
269
+ - Hosted at: https://tbice123123.github.io/langchain-dev-utils/
270
+ - Source files located in `docs/en/` and `docs/zh/`
271
+
272
+ ---
273
+
274
+ ## Release Checklist
275
+
276
+ When preparing a new release:
277
+
278
+ 1. Update version in `src/langchain_dev_utils/__init__.py`
279
+ 2. Update version in `pyproject.toml` if needed
280
+ 3. Run full test suite: `uv run pytest`
281
+ 4. Run linting: `uv run ruff check .`
282
+ 5. Run formatting: `uv run ruff format .`
283
+ 6. Build package: `uv build`
284
+ 7. Update documentation if needed
285
+ 8. Tag release in git
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langchain-dev-utils
3
- Version: 1.4.2
3
+ Version: 1.4.4
4
4
  Summary: A practical utility library for LangChain and LangGraph development
5
5
  Project-URL: Source Code, https://github.com/TBice123123/langchain-dev-utils
6
6
  Project-URL: repository, https://github.com/TBice123123/langchain-dev-utils
@@ -102,4 +102,7 @@ Visit the [GitHub repository](https://github.com/TBice123123/langchain-dev-utils
102
102
  <div align="center">
103
103
  <p>Developed with ❤️ and ☕</p>
104
104
  <p>If this project helps you, please give us a ⭐️</p>
105
- </div>
105
+ </div>
106
+
107
+
108
+
@@ -83,4 +83,7 @@ Visit the [GitHub repository](https://github.com/TBice123123/langchain-dev-utils
83
83
  <div align="center">
84
84
  <p>Developed with ❤️ and ☕</p>
85
85
  <p>If this project helps you, please give us a ⭐️</p>
86
- </div>
86
+ </div>
87
+
88
+
89
+
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "langchain-dev-utils"
3
- version = "1.4.2"
3
+ version = "1.4.4"
4
4
  description = "A practical utility library for LangChain and LangGraph development"
5
5
  readme = "README.md"
6
6
  authors = [{ name = "tiebingice", email = "tiebingice123@outlook.com" }]
@@ -39,7 +39,6 @@ python_functions = ["test_*"]
39
39
 
40
40
  [dependency-groups]
41
41
  dev = [
42
- "dashscope>=1.25.9",
43
42
  "langchain-model-profiles>=0.0.5",
44
43
  "ruff>=0.14.5",
45
44
  ]
@@ -55,6 +54,7 @@ tests = [
55
54
  "langchain-qwq>=0.3.0",
56
55
  "langchain-ollama>=1.0.0",
57
56
  "langchain-community>=0.4.1",
57
+ "dashscope>=1.25.12",
58
58
  ]
59
59
 
60
60
 
@@ -0,0 +1 @@
1
+ __version__ = "1.4.4"
@@ -1,4 +1,4 @@
1
- from typing import Any, Callable, Sequence
1
+ from typing import Annotated, Any, Callable, Generic, Sequence
2
2
 
3
3
  from langchain.agents import create_agent as _create_agent
4
4
  from langchain.agents.middleware.types import (
@@ -6,21 +6,34 @@ from langchain.agents.middleware.types import (
6
6
  AgentState,
7
7
  ResponseT,
8
8
  StateT_co,
9
- _InputAgentState,
10
- _OutputAgentState,
11
9
  )
12
10
  from langchain.agents.structured_output import ResponseFormat
13
- from langchain_core.messages import SystemMessage
11
+ from langchain_core.messages import AnyMessage, SystemMessage
14
12
  from langchain_core.tools import BaseTool
15
13
  from langgraph.cache.base import BaseCache
14
+ from langgraph.graph.message import add_messages
16
15
  from langgraph.graph.state import CompiledStateGraph
17
16
  from langgraph.store.base import BaseStore
18
17
  from langgraph.types import Checkpointer
19
18
  from langgraph.typing import ContextT
19
+ from typing_extensions import NotRequired, Required, TypedDict
20
20
 
21
21
  from ..chat_models import load_chat_model
22
22
 
23
23
 
24
+ class _InputAgentState(TypedDict): # noqa: PYI049
25
+ """Input state schema for the agent."""
26
+
27
+ messages: Required[Annotated[list[AnyMessage | dict[str, Any]], add_messages]]
28
+
29
+
30
+ class _OutputAgentState(TypedDict, Generic[ResponseT]): # noqa: PYI049
31
+ """Output state schema for the agent."""
32
+
33
+ messages: Required[Annotated[list[AnyMessage], add_messages]]
34
+ structured_response: NotRequired[ResponseT]
35
+
36
+
24
37
  def create_agent( # noqa: PLR0915
25
38
  model: str,
26
39
  tools: Sequence[BaseTool | Callable | dict[str, Any]] | None = None,
@@ -25,14 +25,16 @@ class AgentConfig(TypedDict):
25
25
  handoffs: list[str] | Literal["all"]
26
26
 
27
27
 
28
- def _create_handoffs_tool(agent_name: str, tool_description: Optional[str] = None):
28
+ def _create_handoffs_tool(
29
+ agent_name: str, tool_description: Optional[str] = None
30
+ ) -> BaseTool:
29
31
  """Create a tool for handoffs to a specified agent.
30
32
 
31
33
  Args:
32
34
  agent_name (str): The name of the agent to transfer to.
33
35
 
34
36
  Returns:
35
- BaseTool: A tool instance for handoffs to the specified agent.
37
+ BaseTool: The tool instance for handoffs to the specified agent.
36
38
  """
37
39
 
38
40
  tool_name = f"transfer_to_{agent_name}"
@@ -67,13 +69,13 @@ def _get_default_active_agent(state: dict[str, AgentConfig]) -> Optional[str]:
67
69
 
68
70
  def _transform_agent_config(
69
71
  config: dict[str, AgentConfig],
70
- handoffs_tools: list[BaseTool],
72
+ handoffs_tool_map: dict[str, BaseTool],
71
73
  ) -> dict[str, AgentConfig]:
72
74
  """Transform the agent config to add handoffs tools.
73
75
 
74
76
  Args:
75
77
  config (dict[str, AgentConfig]): The agent config.
76
- handoffs_tools (list[BaseTool]): The list of handoffs tools.
78
+ handoffs_tool_map (dict[str, BaseTool]): The dict of {agent name: handoffs tool}.
77
79
 
78
80
  Returns:
79
81
  dict[str, AgentConfig]: The transformed agent config.
@@ -96,8 +98,8 @@ def _transform_agent_config(
96
98
  if handoffs == "all":
97
99
  handoff_tools = [
98
100
  handoff_tool
99
- for handoff_tool in handoffs_tools
100
- if handoff_tool.name != f"transfer_to_{agent_name}"
101
+ for transfer_to_agent, handoff_tool in handoffs_tool_map.items()
102
+ if transfer_to_agent != agent_name
101
103
  ]
102
104
  else:
103
105
  if not isinstance(handoffs, list):
@@ -105,14 +107,13 @@ def _transform_agent_config(
105
107
  f"handoffs for agent {agent_name} must be a list of agent names or 'all'"
106
108
  )
107
109
 
110
+ if agent_name in handoffs:
111
+ raise ValueError(f"agent {agent_name} cannot handoff to itself")
112
+
108
113
  handoff_tools = [
109
114
  handoff_tool
110
- for handoff_tool in handoffs_tools
111
- if handoff_tool.name
112
- in [
113
- f"transfer_to_{_handoff_agent_name}"
114
- for _handoff_agent_name in handoffs
115
- ]
115
+ for transfer_to_agent, handoff_tool in handoffs_tool_map.items()
116
+ if transfer_to_agent in handoffs
116
117
  ]
117
118
 
118
119
  new_config[agent_name]["tools"] = [
@@ -158,28 +159,28 @@ class HandoffAgentMiddleware(AgentMiddleware):
158
159
  if handoffs_tool_overrides is None:
159
160
  handoffs_tool_overrides = {}
160
161
 
161
- handoffs_tools = []
162
+ handoffs_tool_map = {}
163
+
162
164
  for agent_name in agents_config.keys():
163
165
  if not handoffs_tool_overrides.get(agent_name):
164
- handoffs_tools.append(
165
- _create_handoffs_tool(
166
- agent_name,
167
- custom_handoffs_tool_descriptions.get(agent_name),
168
- )
166
+ handoffs_tool_map[agent_name] = _create_handoffs_tool(
167
+ agent_name,
168
+ custom_handoffs_tool_descriptions.get(agent_name),
169
169
  )
170
+
170
171
  else:
171
- handoffs_tools.append(
172
- cast(BaseTool, handoffs_tool_overrides.get(agent_name))
172
+ handoffs_tool_map[agent_name] = cast(
173
+ BaseTool, handoffs_tool_overrides.get(agent_name)
173
174
  )
174
175
 
175
176
  self.default_agent_name = default_agent_name
176
177
  self.agents_config = _transform_agent_config(
177
178
  agents_config,
178
- handoffs_tools,
179
+ handoffs_tool_map,
179
180
  )
180
181
 
181
182
  all_tools = [
182
- *handoffs_tools,
183
+ *handoffs_tool_map.values(),
183
184
  ]
184
185
 
185
186
  for agent_name in agents_config:
@@ -1,6 +1,6 @@
1
1
  from typing import Any, Optional, cast
2
2
 
3
- from langchain.chat_models.base import _SUPPORTED_PROVIDERS, _init_chat_model_helper
3
+ from langchain.chat_models import init_chat_model
4
4
  from langchain_core.language_models.chat_models import BaseChatModel
5
5
  from langchain_core.utils import from_env
6
6
 
@@ -28,8 +28,7 @@ def _parse_model(model: str, model_provider: Optional[str]) -> tuple[str, str]:
28
28
  Raises:
29
29
  ValueError: If unable to infer model provider
30
30
  """
31
- support_providers = list(_MODEL_PROVIDERS_DICT.keys()) + list(_SUPPORTED_PROVIDERS)
32
- if not model_provider and ":" in model and model.split(":")[0] in support_providers:
31
+ if not model_provider and ":" in model:
33
32
  model_provider = model.split(":")[0]
34
33
  model = ":".join(model.split(":")[1:])
35
34
  if not model_provider:
@@ -71,7 +70,7 @@ def _load_chat_model_helper(
71
70
  kwargs.update({"profile": model_profiles[model]})
72
71
  return chat_model(model=model, **kwargs)
73
72
 
74
- return _init_chat_model_helper(model, model_provider=model_provider, **kwargs)
73
+ return init_chat_model(model, model_provider=model_provider, **kwargs)
75
74
 
76
75
 
77
76
  def register_model_provider(
@@ -1,6 +1,7 @@
1
- from typing import Any, Literal, NotRequired, TypedDict, Union
1
+ from typing import Any, Literal, Union
2
2
 
3
3
  from langchain_core.language_models.chat_models import BaseChatModel
4
+ from typing_extensions import NotRequired, TypedDict
4
5
 
5
6
  ChatModelType = Union[type[BaseChatModel], Literal["openai-compatible"]]
6
7
 
@@ -1,7 +1,8 @@
1
- from typing import Any, Literal, NotRequired, Optional, TypedDict, Union
1
+ from typing import Any, Literal, Optional, Union
2
2
 
3
- from langchain.embeddings.base import _SUPPORTED_PROVIDERS, Embeddings, init_embeddings
3
+ from langchain.embeddings.base import Embeddings, init_embeddings
4
4
  from langchain_core.utils import from_env
5
+ from typing_extensions import NotRequired, TypedDict
5
6
 
6
7
  from langchain_dev_utils._utils import (
7
8
  _check_pkg_install,
@@ -11,6 +12,7 @@ from langchain_dev_utils._utils import (
11
12
 
12
13
  _EMBEDDINGS_PROVIDERS_DICT = {}
13
14
 
15
+
14
16
  EmbeddingsType = Union[type[Embeddings], Literal["openai-compatible"]]
15
17
 
16
18
 
@@ -218,10 +220,6 @@ def load_embeddings(
218
220
  """
219
221
  if provider is None:
220
222
  provider, model = _parse_model_string(model)
221
- if provider not in list(_EMBEDDINGS_PROVIDERS_DICT.keys()) + list(
222
- _SUPPORTED_PROVIDERS
223
- ):
224
- raise ValueError(f"Provider {provider} not registered")
225
223
 
226
224
  if provider in _EMBEDDINGS_PROVIDERS_DICT:
227
225
  embeddings = _EMBEDDINGS_PROVIDERS_DICT[provider]["embeddings_model"]
@@ -1,8 +1,9 @@
1
- from typing import Any, Callable, Optional, TypedDict, Union, overload
1
+ from typing import Any, Callable, Optional, Union, overload
2
2
 
3
3
  from langchain_core.tools import BaseTool
4
4
  from langchain_core.tools import tool as create_tool
5
5
  from langgraph.types import interrupt
6
+ from typing_extensions import TypedDict
6
7
 
7
8
 
8
9
  class InterruptParams(TypedDict):
@@ -136,10 +136,6 @@ async def test_handoffs_middleware_async():
136
136
  handoffs_tool_overrides=handoffs_tool_map,
137
137
  )
138
138
  ],
139
- tools=[
140
- get_current_time,
141
- run_code,
142
- ],
143
139
  checkpointer=InMemorySaver(),
144
140
  )
145
141