deepagents 0.3.6__py3-none-any.whl → 0.3.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- deepagents/backends/filesystem.py +148 -22
- deepagents/backends/sandbox.py +1 -1
- deepagents/backends/store.py +85 -0
- deepagents/backends/utils.py +1 -1
- deepagents/graph.py +46 -12
- deepagents/middleware/__init__.py +3 -1
- deepagents/middleware/_utils.py +23 -0
- deepagents/middleware/filesystem.py +205 -84
- deepagents/middleware/memory.py +17 -15
- deepagents/middleware/skills.py +10 -9
- deepagents/middleware/subagents.py +51 -24
- deepagents/middleware/summarization.py +758 -0
- {deepagents-0.3.6.dist-info → deepagents-0.3.7.dist-info}/METADATA +5 -3
- deepagents-0.3.7.dist-info/RECORD +22 -0
- {deepagents-0.3.6.dist-info → deepagents-0.3.7.dist-info}/WHEEL +1 -1
- deepagents-0.3.6.dist-info/RECORD +0 -20
- {deepagents-0.3.6.dist-info → deepagents-0.3.7.dist-info}/top_level.txt +0 -0
deepagents/middleware/skills.py
CHANGED
|
@@ -114,6 +114,8 @@ from langchain_core.runnables import RunnableConfig
|
|
|
114
114
|
from langgraph.prebuilt import ToolRuntime
|
|
115
115
|
from langgraph.runtime import Runtime
|
|
116
116
|
|
|
117
|
+
from deepagents.middleware._utils import append_to_system_message
|
|
118
|
+
|
|
117
119
|
logger = logging.getLogger(__name__)
|
|
118
120
|
|
|
119
121
|
# Security: Maximum size for SKILL.md files to prevent DoS attacks (10MB)
|
|
@@ -558,18 +560,20 @@ class SkillsMiddleware(AgentMiddleware):
|
|
|
558
560
|
lines = []
|
|
559
561
|
for skill in skills:
|
|
560
562
|
lines.append(f"- **{skill['name']}**: {skill['description']}")
|
|
563
|
+
if skill["allowed_tools"]:
|
|
564
|
+
lines.append(f" -> Allowed tools: {', '.join(skill['allowed_tools'])}")
|
|
561
565
|
lines.append(f" -> Read `{skill['path']}` for full instructions")
|
|
562
566
|
|
|
563
567
|
return "\n".join(lines)
|
|
564
568
|
|
|
565
569
|
def modify_request(self, request: ModelRequest) -> ModelRequest:
|
|
566
|
-
"""Inject skills documentation into a model request's system
|
|
570
|
+
"""Inject skills documentation into a model request's system message.
|
|
567
571
|
|
|
568
572
|
Args:
|
|
569
573
|
request: Model request to modify
|
|
570
574
|
|
|
571
575
|
Returns:
|
|
572
|
-
New model request with skills documentation injected into system
|
|
576
|
+
New model request with skills documentation injected into system message
|
|
573
577
|
"""
|
|
574
578
|
skills_metadata = request.state.get("skills_metadata", [])
|
|
575
579
|
skills_locations = self._format_skills_locations()
|
|
@@ -580,12 +584,9 @@ class SkillsMiddleware(AgentMiddleware):
|
|
|
580
584
|
skills_list=skills_list,
|
|
581
585
|
)
|
|
582
586
|
|
|
583
|
-
|
|
584
|
-
system_prompt = request.system_prompt + "\n\n" + skills_section
|
|
585
|
-
else:
|
|
586
|
-
system_prompt = skills_section
|
|
587
|
+
new_system_message = append_to_system_message(request.system_message, skills_section)
|
|
587
588
|
|
|
588
|
-
return request.override(
|
|
589
|
+
return request.override(system_message=new_system_message)
|
|
589
590
|
|
|
590
591
|
def before_agent(self, state: SkillsState, runtime: Runtime, config: RunnableConfig) -> SkillsStateUpdate | None:
|
|
591
592
|
"""Load skills metadata before agent execution (synchronous).
|
|
@@ -602,7 +603,7 @@ class SkillsMiddleware(AgentMiddleware):
|
|
|
602
603
|
config: Runnable config.
|
|
603
604
|
|
|
604
605
|
Returns:
|
|
605
|
-
State update with skills_metadata populated, or None if already present
|
|
606
|
+
State update with `skills_metadata` populated, or `None` if already present
|
|
606
607
|
"""
|
|
607
608
|
# Skip if skills_metadata is already present in state (even if empty)
|
|
608
609
|
if "skills_metadata" in state:
|
|
@@ -637,7 +638,7 @@ class SkillsMiddleware(AgentMiddleware):
|
|
|
637
638
|
config: Runnable config.
|
|
638
639
|
|
|
639
640
|
Returns:
|
|
640
|
-
State update with skills_metadata populated, or None if already present
|
|
641
|
+
State update with `skills_metadata` populated, or `None` if already present
|
|
641
642
|
"""
|
|
642
643
|
# Skip if skills_metadata is already present in state (even if empty)
|
|
643
644
|
if "skills_metadata" in state:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Middleware for providing subagents to an agent via a `task` tool."""
|
|
2
2
|
|
|
3
3
|
from collections.abc import Awaitable, Callable, Sequence
|
|
4
|
-
from typing import Any, NotRequired, TypedDict, cast
|
|
4
|
+
from typing import Annotated, Any, NotRequired, TypedDict, cast
|
|
5
5
|
|
|
6
6
|
from langchain.agents import create_agent
|
|
7
7
|
from langchain.agents.middleware import HumanInTheLoopMiddleware, InterruptOnConfig
|
|
@@ -13,6 +13,8 @@ from langchain_core.runnables import Runnable
|
|
|
13
13
|
from langchain_core.tools import StructuredTool
|
|
14
14
|
from langgraph.types import Command
|
|
15
15
|
|
|
16
|
+
from deepagents.middleware._utils import append_to_system_message
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
class SubAgent(TypedDict):
|
|
18
20
|
"""Specification for an agent.
|
|
@@ -71,10 +73,14 @@ class SubAgent(TypedDict):
|
|
|
71
73
|
class CompiledSubAgent(TypedDict):
|
|
72
74
|
"""A pre-compiled agent spec.
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
!!! note
|
|
77
|
+
|
|
78
|
+
The runnable's state schema must include a 'messages' key.
|
|
79
|
+
|
|
80
|
+
This is required for the subagent to communicate results back to the main agent.
|
|
81
|
+
|
|
76
82
|
When the subagent completes, the final message in the 'messages' list will be
|
|
77
|
-
extracted and returned as a ToolMessage to the parent agent.
|
|
83
|
+
extracted and returned as a `ToolMessage` to the parent agent.
|
|
78
84
|
"""
|
|
79
85
|
|
|
80
86
|
name: str
|
|
@@ -84,7 +90,16 @@ class CompiledSubAgent(TypedDict):
|
|
|
84
90
|
"""What this subagent does."""
|
|
85
91
|
|
|
86
92
|
runnable: Runnable
|
|
87
|
-
"""
|
|
93
|
+
"""A custom agent implementation.
|
|
94
|
+
|
|
95
|
+
Create a custom agent using either:
|
|
96
|
+
|
|
97
|
+
1. LangChain's [`create_agent()`](https://docs.langchain.com/oss/python/langchain/quickstart)
|
|
98
|
+
2. A custom graph using [`langgraph`](https://docs.langchain.com/oss/python/langgraph/quickstart)
|
|
99
|
+
|
|
100
|
+
If you're creating a custom graph, make sure the state schema includes a 'messages' key.
|
|
101
|
+
This is required for the subagent to communicate results back to the main agent.
|
|
102
|
+
"""
|
|
88
103
|
|
|
89
104
|
|
|
90
105
|
DEFAULT_SUBAGENT_PROMPT = "In order to complete the objective that the user asks of you, you have access to a number of standard tools."
|
|
@@ -384,8 +399,11 @@ def _create_task_tool(
|
|
|
384
399
|
task_description = task_description.format(available_agents=subagent_description_str)
|
|
385
400
|
|
|
386
401
|
def task(
|
|
387
|
-
description:
|
|
388
|
-
|
|
402
|
+
description: Annotated[
|
|
403
|
+
str,
|
|
404
|
+
"A detailed description of the task for the subagent to perform autonomously. Include all necessary context and specify the expected output format.", # noqa: E501
|
|
405
|
+
],
|
|
406
|
+
subagent_type: Annotated[str, "The type of subagent to use. Must be one of the available agent types listed in the tool description."],
|
|
389
407
|
runtime: ToolRuntime,
|
|
390
408
|
) -> str | Command:
|
|
391
409
|
if subagent_type not in subagent_graphs:
|
|
@@ -399,8 +417,11 @@ def _create_task_tool(
|
|
|
399
417
|
return _return_command_with_state_update(result, runtime.tool_call_id)
|
|
400
418
|
|
|
401
419
|
async def atask(
|
|
402
|
-
description:
|
|
403
|
-
|
|
420
|
+
description: Annotated[
|
|
421
|
+
str,
|
|
422
|
+
"A detailed description of the task for the subagent to perform autonomously. Include all necessary context and specify the expected output format.", # noqa: E501
|
|
423
|
+
],
|
|
424
|
+
subagent_type: Annotated[str, "The type of subagent to use. Must be one of the available agent types listed in the tool description."],
|
|
404
425
|
runtime: ToolRuntime,
|
|
405
426
|
) -> str | Command:
|
|
406
427
|
if subagent_type not in subagent_graphs:
|
|
@@ -439,18 +460,24 @@ class SubAgentMiddleware(AgentMiddleware):
|
|
|
439
460
|
|
|
440
461
|
Args:
|
|
441
462
|
default_model: The model to use for subagents.
|
|
442
|
-
|
|
463
|
+
|
|
464
|
+
Can be a `LanguageModelLike` or a dict for `init_chat_model`.
|
|
443
465
|
default_tools: The tools to use for the default general-purpose subagent.
|
|
444
|
-
default_middleware: Default middleware to apply to all subagents.
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
466
|
+
default_middleware: Default middleware to apply to all subagents.
|
|
467
|
+
|
|
468
|
+
If `None`, no default middleware is applied.
|
|
469
|
+
|
|
470
|
+
Pass a list to specify custom middleware.
|
|
471
|
+
default_interrupt_on: The tool configs to use for the default general-purpose subagent.
|
|
472
|
+
|
|
473
|
+
These are also the fallback for any subagents that don't specify their own tool configs.
|
|
448
474
|
subagents: A list of additional subagents to provide to the agent.
|
|
449
475
|
system_prompt: Full system prompt override. When provided, completely replaces
|
|
450
476
|
the agent's system prompt.
|
|
451
|
-
general_purpose_agent: Whether to include the general-purpose agent.
|
|
452
|
-
task_description: Custom description for the task tool.
|
|
453
|
-
|
|
477
|
+
general_purpose_agent: Whether to include the general-purpose agent.
|
|
478
|
+
task_description: Custom description for the task tool.
|
|
479
|
+
|
|
480
|
+
If `None`, uses the default description template.
|
|
454
481
|
|
|
455
482
|
Example:
|
|
456
483
|
```python
|
|
@@ -494,7 +521,7 @@ class SubAgentMiddleware(AgentMiddleware):
|
|
|
494
521
|
general_purpose_agent: bool = True,
|
|
495
522
|
task_description: str | None = None,
|
|
496
523
|
) -> None:
|
|
497
|
-
"""Initialize the SubAgentMiddleware
|
|
524
|
+
"""Initialize the `SubAgentMiddleware`."""
|
|
498
525
|
super().__init__()
|
|
499
526
|
self.system_prompt = system_prompt
|
|
500
527
|
task_tool = _create_task_tool(
|
|
@@ -513,10 +540,10 @@ class SubAgentMiddleware(AgentMiddleware):
|
|
|
513
540
|
request: ModelRequest,
|
|
514
541
|
handler: Callable[[ModelRequest], ModelResponse],
|
|
515
542
|
) -> ModelResponse:
|
|
516
|
-
"""Update the system
|
|
543
|
+
"""Update the system message to include instructions on using subagents."""
|
|
517
544
|
if self.system_prompt is not None:
|
|
518
|
-
|
|
519
|
-
return handler(request.override(
|
|
545
|
+
new_system_message = append_to_system_message(request.system_message, self.system_prompt)
|
|
546
|
+
return handler(request.override(system_message=new_system_message))
|
|
520
547
|
return handler(request)
|
|
521
548
|
|
|
522
549
|
async def awrap_model_call(
|
|
@@ -524,8 +551,8 @@ class SubAgentMiddleware(AgentMiddleware):
|
|
|
524
551
|
request: ModelRequest,
|
|
525
552
|
handler: Callable[[ModelRequest], Awaitable[ModelResponse]],
|
|
526
553
|
) -> ModelResponse:
|
|
527
|
-
"""(async) Update the system
|
|
554
|
+
"""(async) Update the system message to include instructions on using subagents."""
|
|
528
555
|
if self.system_prompt is not None:
|
|
529
|
-
|
|
530
|
-
return await handler(request.override(
|
|
556
|
+
new_system_message = append_to_system_message(request.system_message, self.system_prompt)
|
|
557
|
+
return await handler(request.override(system_message=new_system_message))
|
|
531
558
|
return await handler(request)
|