dex-agents-deepagents-cli 0.6.1__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.
- dex_agents_deepagents_cli-0.6.1/LICENSE +105 -0
- dex_agents_deepagents_cli-0.6.1/PKG-INFO +199 -0
- dex_agents_deepagents_cli-0.6.1/README.md +173 -0
- dex_agents_deepagents_cli-0.6.1/pyproject.toml +123 -0
- dex_agents_deepagents_cli-0.6.1/pyproject.toml.orig +93 -0
- dex_agents_deepagents_cli-0.6.1/src/dex_agents_deepagents_cli/__init__.py +112 -0
- dex_agents_deepagents_cli-0.6.1/src/dex_agents_deepagents_cli/__main__.py +14 -0
- dex_agents_deepagents_cli-0.6.1/src/dex_agents_deepagents_cli/connector_tool_names.py +138 -0
- dex_agents_deepagents_cli-0.6.1/src/dex_agents_deepagents_cli/harness.py +443 -0
- dex_agents_deepagents_cli-0.6.1/src/dex_agents_deepagents_cli/py.typed +0 -0
- dex_agents_deepagents_cli-0.6.1/src/dex_agents_deepagents_cli/workspace_backend.py +382 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Super Durable, Inc.
|
|
4
|
+
|
|
5
|
+
Portions of this software are licensed as follows:
|
|
6
|
+
|
|
7
|
+
- Legacy Materials remain under their original licenses as described in
|
|
8
|
+
`LEGACY_NOTICES.md`.
|
|
9
|
+
- Third-Party Materials remain under the licenses provided by their owners.
|
|
10
|
+
- The `docs/` and `examples/` directories are not licensed under the
|
|
11
|
+
Sustainable Use License and retain their existing licensing status.
|
|
12
|
+
- All other material owned or licensable by Super Durable, Inc. is available
|
|
13
|
+
under the Sustainable Use License below.
|
|
14
|
+
|
|
15
|
+
See `LEGACY_NOTICES.md` for the applicable legacy and third-party notices.
|
|
16
|
+
|
|
17
|
+
## Sustainable Use License
|
|
18
|
+
|
|
19
|
+
Version 1.0
|
|
20
|
+
|
|
21
|
+
### Acceptance
|
|
22
|
+
|
|
23
|
+
By using the software, you agree to all of the terms and conditions below.
|
|
24
|
+
|
|
25
|
+
### Copyright License
|
|
26
|
+
|
|
27
|
+
The licensor grants you a non-exclusive, royalty-free, worldwide,
|
|
28
|
+
non-sublicensable, non-transferable license to use, copy, distribute, make
|
|
29
|
+
available, and prepare derivative works of the software, in each case subject
|
|
30
|
+
to the limitations below.
|
|
31
|
+
|
|
32
|
+
### Limitations
|
|
33
|
+
|
|
34
|
+
You may use or modify the software only for your own internal business purposes
|
|
35
|
+
or for non-commercial or personal use. You may distribute the software or
|
|
36
|
+
provide it to others only if you do so free of charge for non-commercial
|
|
37
|
+
purposes. You may not alter, remove, or obscure any licensing, copyright, or
|
|
38
|
+
other notices of the licensor in the software. Any use of the licensor's
|
|
39
|
+
trademarks is subject to applicable law.
|
|
40
|
+
|
|
41
|
+
### Patents
|
|
42
|
+
|
|
43
|
+
The licensor grants you a license, under any patent claims the licensor can
|
|
44
|
+
license, or becomes able to license, to make, have made, use, sell, offer for
|
|
45
|
+
sale, import and have imported the software, in each case subject to the
|
|
46
|
+
limitations and conditions in this license. This license does not cover any
|
|
47
|
+
patent claims that you cause to be infringed by modifications or additions to
|
|
48
|
+
the software.
|
|
49
|
+
|
|
50
|
+
If you or your company make any written claim that the software infringes or
|
|
51
|
+
contributes to infringement of any patent, your patent license for the software
|
|
52
|
+
granted under these terms ends immediately. If your company makes such a claim,
|
|
53
|
+
your patent license ends immediately for work on behalf of your company.
|
|
54
|
+
|
|
55
|
+
### Notices
|
|
56
|
+
|
|
57
|
+
You must ensure that anyone who gets a copy of any part of the software from
|
|
58
|
+
you also gets a copy of these terms. If you modify the software, you must
|
|
59
|
+
include in any modified copies of the software a prominent notice stating that
|
|
60
|
+
you have modified the software.
|
|
61
|
+
|
|
62
|
+
### No Other Rights
|
|
63
|
+
|
|
64
|
+
These terms do not imply any licenses other than those expressly granted in
|
|
65
|
+
these terms.
|
|
66
|
+
|
|
67
|
+
### Termination
|
|
68
|
+
|
|
69
|
+
If you use the software in violation of these terms, such use is not licensed,
|
|
70
|
+
and your license will automatically terminate. If the licensor provides you
|
|
71
|
+
with a notice of your violation, and you cease all violation of this license no
|
|
72
|
+
later than 30 days after you receive that notice, your license will be
|
|
73
|
+
reinstated retroactively. However, if you violate these terms after such
|
|
74
|
+
reinstatement, any additional violation of these terms will cause your license
|
|
75
|
+
to terminate automatically and permanently.
|
|
76
|
+
|
|
77
|
+
### No Liability
|
|
78
|
+
|
|
79
|
+
As far as the law allows, the software comes as is, without any warranty or
|
|
80
|
+
condition, and the licensor will not be liable to you for any damages arising
|
|
81
|
+
out of these terms or the use or nature of the software, under any kind of
|
|
82
|
+
legal claim.
|
|
83
|
+
|
|
84
|
+
### Definitions
|
|
85
|
+
|
|
86
|
+
The "licensor" is the entity offering these terms.
|
|
87
|
+
|
|
88
|
+
The "software" is the software the licensor makes available under these terms,
|
|
89
|
+
including any portion of it.
|
|
90
|
+
|
|
91
|
+
"You" refers to the individual or entity agreeing to these terms.
|
|
92
|
+
|
|
93
|
+
"Your company" is any legal entity, sole proprietorship, or other kind of
|
|
94
|
+
organization that you work for, plus all organizations that have control over,
|
|
95
|
+
are under the control of, or are under common control with that organization.
|
|
96
|
+
Control means ownership of substantially all the assets of an entity, or the
|
|
97
|
+
power to direct its management and policies by vote, contract, or otherwise.
|
|
98
|
+
Control can be direct or indirect.
|
|
99
|
+
|
|
100
|
+
"Your license" is the license granted to you for the software under these
|
|
101
|
+
terms.
|
|
102
|
+
|
|
103
|
+
"Use" means anything you do with the software requiring your license.
|
|
104
|
+
|
|
105
|
+
"Trademark" means trademarks, service marks, and similar rights.
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dex-agents-deepagents-cli
|
|
3
|
+
Version: 0.6.1
|
|
4
|
+
Summary: The dex-agents-deepagents command: a durable Deep Agents agent in your terminal
|
|
5
|
+
Author: Super Durable
|
|
6
|
+
License-Expression: LicenseRef-Sustainable-Use-1.0
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Classifier: Typing :: Typed
|
|
12
|
+
Requires-Dist: deepagents>=0.7.32,<0.8
|
|
13
|
+
Requires-Dist: dex-agents==0.6.1
|
|
14
|
+
Requires-Dist: dex-agents-cli-core==0.6.1
|
|
15
|
+
Requires-Dist: dex-agents-langgraph==0.6.1
|
|
16
|
+
Requires-Dist: dex-python-sdk==1.45.0
|
|
17
|
+
Requires-Dist: langchain>=1.4.7,<2
|
|
18
|
+
Requires-Dist: langchain-core>=1.7.3,<1.8
|
|
19
|
+
Requires-Dist: langchain-openai>=1.0,<2
|
|
20
|
+
Requires-Dist: langgraph>=1.2.19,<1.3
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Project-URL: Homepage, https://github.com/superdurable/dex/tree/main/agents/cli/python/deepagents
|
|
23
|
+
Project-URL: Repository, https://github.com/superdurable/dex
|
|
24
|
+
Project-URL: Changelog, https://github.com/superdurable/dex/blob/main/agents/CHANGELOG.md
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# dex-agents-deepagents-cli
|
|
28
|
+
|
|
29
|
+
`dex-agents-deepagents-cli` provides the `dex-agents-deepagents` command. It
|
|
30
|
+
runs a [Deep Agents](https://github.com/langchain-ai/deepagents) agent as a
|
|
31
|
+
durable Dex agent session and chats with it in your terminal. The shared
|
|
32
|
+
CLI core, [`dex-agents-cli-core`](../core/README.md), starts or reuses
|
|
33
|
+
`dexcli dev`, connects the connectors MCP server, and runs the Worker. This
|
|
34
|
+
package only builds the agent with `create_deep_agent` and runs it on the
|
|
35
|
+
[LangGraph adapter](../../../python/langgraph/README.md).
|
|
36
|
+
|
|
37
|
+
## Running it
|
|
38
|
+
|
|
39
|
+
The command needs Python 3.11 or later and a key for the model's provider.
|
|
40
|
+
The default model is OpenAI's, so set `OPENAI_API_KEY`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
export OPENAI_API_KEY=sk-...
|
|
44
|
+
uvx --from dex-agents-deepagents-cli dex-agents-deepagents
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The first run asks the `init` questions and writes
|
|
48
|
+
`~/.dex/agents/deepagents.yaml`. Then type a message at the `>` prompt.
|
|
49
|
+
Approve or reject tool calls with `y` or `n`, and press Ctrl-D to exit. The
|
|
50
|
+
session stays in Dex, and the command prints the `--resume` line that
|
|
51
|
+
continues it. See the [CLI core README](../core/README.md#running-a-command)
|
|
52
|
+
for every subcommand and option, and [`agents/cli`](../../README.md) for the
|
|
53
|
+
configuration file.
|
|
54
|
+
|
|
55
|
+
The command never prints or stores provider keys. The chat model reads its
|
|
56
|
+
key from the provider's standard environment variable.
|
|
57
|
+
|
|
58
|
+
## Configuration
|
|
59
|
+
|
|
60
|
+
`model` is a LangChain `provider:model` ID, as `init_chat_model` takes it. It
|
|
61
|
+
defaults to `openai:gpt-5.2`; set `model` in the file or pass `--model` to
|
|
62
|
+
change it. An `openai:` model uses the Responses API, as Deep Agents does.
|
|
63
|
+
|
|
64
|
+
| Provider | Model example | Environment |
|
|
65
|
+
| --- | --- | --- |
|
|
66
|
+
| OpenAI | `openai:gpt-5.2` | `OPENAI_API_KEY`, optional `OPENAI_BASE_URL` |
|
|
67
|
+
| Anthropic | `anthropic:claude-opus-5-5` | `ANTHROPIC_API_KEY` |
|
|
68
|
+
| Google | `google_genai:gemini-2.5-flash` | `GOOGLE_API_KEY` |
|
|
69
|
+
|
|
70
|
+
Other providers need their LangChain integration package, such as
|
|
71
|
+
`uvx --from dex-agents-deepagents-cli --with langchain-mistralai dex-agents-deepagents`.
|
|
72
|
+
|
|
73
|
+
`system_prompt` replaces the default instructions. Session settings may
|
|
74
|
+
change the model and the instructions from the next turn on. The
|
|
75
|
+
`deepagents` section has no options yet, and any key in it is a configuration
|
|
76
|
+
error.
|
|
77
|
+
|
|
78
|
+
## Deep Agents' tools in Dex
|
|
79
|
+
|
|
80
|
+
The agent keeps Deep Agents' own tools and behavior. The CLI core adds the
|
|
81
|
+
connector, web fetch, and browser tools on top. The agent runs on the
|
|
82
|
+
LangGraph adapter, so every model call is a `RunModel` Step and every tool
|
|
83
|
+
call runs in its own tool Step, after approval when its policy asks for it.
|
|
84
|
+
|
|
85
|
+
| Deep Agents tool | In this command |
|
|
86
|
+
| --- | --- |
|
|
87
|
+
| `ls`, `read_file`, `glob`, `grep` | Reads of the real workspace files. They run at once. |
|
|
88
|
+
| `write_file`, `edit_file`, `delete` | Writes of the real workspace files. They run at once unless `approval.always` names the tool. |
|
|
89
|
+
| `execute` | Runs a command with `/bin/sh` in the workspace. It runs at once unless `approval.always` names it; `local_tools.shell.allow` has no effect. |
|
|
90
|
+
| `task` | Runs a subagent inside the call's tool Step. It runs at once unless `approval.always` names any Deep Agents tool, because the subagent may call it without its own approval. |
|
|
91
|
+
| `write_todos` | Updates the todo list in the agent's state. It runs at once. |
|
|
92
|
+
|
|
93
|
+
- Deep Agents asks for no approval unless `interrupt_on` names a tool, and
|
|
94
|
+
this command follows it: `approval.always` plays the role of
|
|
95
|
+
`interrupt_on`. Connector writes always wait for approval.
|
|
96
|
+
- The file tools use Deep Agents' `LocalShellBackend` on the host's paths,
|
|
97
|
+
rooted at the workspace, so a file tool and `execute` name a file the same
|
|
98
|
+
way. Paths are absolute. A path that resolves outside the workspace fails
|
|
99
|
+
with an error the model sees, and `ls`, `glob`, and `grep` leave out
|
|
100
|
+
entries whose real path is outside it, such as a link to a file elsewhere;
|
|
101
|
+
`grep` never opens such a file.
|
|
102
|
+
- That check is a guardrail against mistaken paths, not a sandbox.
|
|
103
|
+
`execute` runs any command with your permissions, without approval by
|
|
104
|
+
default. A link that changes during a call, or a hard link in the
|
|
105
|
+
workspace to a file elsewhere, is not detected. Use OS-level isolation,
|
|
106
|
+
such as a container, when the agent must not reach other files.
|
|
107
|
+
- `local_tools.files` and `local_tools.shell.enabled` switch the tools on and
|
|
108
|
+
off per turn. `task` needs both, because a subagent uses both.
|
|
109
|
+
- Each tool Step attempt runs Deep Agents' tool middleware around the tool,
|
|
110
|
+
such as `FilesystemMiddleware`'s eviction of a large result to a file. A
|
|
111
|
+
retried attempt runs it again. The
|
|
112
|
+
session Flow sets the adapter's `should_defer_tool_calls_before_middleware`
|
|
113
|
+
for that. Deep Agents writes evicted results and long user messages under
|
|
114
|
+
the paths `/large_tool_results/` and `/conversation_history/`, which its
|
|
115
|
+
file tools read. Each session keeps them in its own directory,
|
|
116
|
+
`~/.dex/agents/deepagents-artifacts/<SHA-256 of the session ID>/`, so two
|
|
117
|
+
sessions never see each other's files and a restarted Worker on the same
|
|
118
|
+
machine finds them. Before each file operation the command checks every
|
|
119
|
+
directory from `deepagents-artifacts` down: you own it, it is no link, and
|
|
120
|
+
a looser mode becomes 0700. `~/.dex` and `~/.dex/agents` keep their mode
|
|
121
|
+
but must not be another user's link. A failed check is an error result of
|
|
122
|
+
that tool call.
|
|
123
|
+
- When the command starts, it deletes the artifacts of every session whose
|
|
124
|
+
files changed more than 30 days ago. It never follows a link, and it logs
|
|
125
|
+
each directory it removes or cannot remove. A session resumed after that
|
|
126
|
+
can no longer read its earlier large results.
|
|
127
|
+
- `edit_file`, `execute`, and `task` calls are never retried, so a Worker that
|
|
128
|
+
dies during one records `outcome_unknown`. `write_file` and `delete` calls
|
|
129
|
+
may run again after a failure.
|
|
130
|
+
- `write_todos` is LangChain's `TodoListMiddleware` tool. It returns a graph
|
|
131
|
+
`Command` that the adapter records and applies. Each turn starts from the
|
|
132
|
+
stored messages, so the todo list lasts for one turn; the plan stays in the
|
|
133
|
+
conversation.
|
|
134
|
+
- `task` runs the subagent's model and tool calls inline, in one tool Step.
|
|
135
|
+
They have no Steps or approvals of their own, use the configuration file's
|
|
136
|
+
model even when session settings change it, and do not count in the
|
|
137
|
+
session's usage. Connector tools are not offered to a subagent.
|
|
138
|
+
- A connector tool whose name a Deep Agents tool has gets the prefix
|
|
139
|
+
`connector_`, such as `connector_read_file`. The other connector tools keep
|
|
140
|
+
their names.
|
|
141
|
+
- Every model call gets the turn's instructions, the workspace path, and the
|
|
142
|
+
turn's model through the adapter's `select_turn_chat_model`.
|
|
143
|
+
- Deep Agents' summarization is turned off for now. It would make an extra
|
|
144
|
+
model call with the configuration file's model inside a `RunModel` Step, so
|
|
145
|
+
a model from the session settings would not reach it. The session does not
|
|
146
|
+
compact either: Dex compaction needs
|
|
147
|
+
the model's context window, which the configuration does not set. A long
|
|
148
|
+
session ends when its input no longer fits the model's context window;
|
|
149
|
+
start a new session then.
|
|
150
|
+
|
|
151
|
+
## Images
|
|
152
|
+
|
|
153
|
+
`/image <path>` attaches an image file to the next message. The command gives
|
|
154
|
+
the LangChain adapter the media store of `media.store`, so the model sees the
|
|
155
|
+
image, and images that tools return go to the same store. See
|
|
156
|
+
[Images](../../README.md#images).
|
|
157
|
+
|
|
158
|
+
## Development
|
|
159
|
+
|
|
160
|
+
Develop with uv 0.12.2. The package resolves `dex-agents`, the LangGraph
|
|
161
|
+
adapter, the CLI core, and the test support package from this repository by
|
|
162
|
+
path. `ci.sh` installs the locked dependencies, checks that LangChain and
|
|
163
|
+
LangGraph match the adapter's lock, checks lint and types, and runs the tests
|
|
164
|
+
against a private `dexcli dev`:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
cd agents/cli/python/deepagents
|
|
168
|
+
DEXCLI=/path/to/dexcli ./ci.sh
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The tests run the command in a pseudo-terminal with a private home. The chat
|
|
172
|
+
model calls the scripted Responses API of
|
|
173
|
+
[`dex-agents-cli-testing`](../testing) on 127.0.0.1; a refused proxy stops
|
|
174
|
+
any other request, and no provider variable of the host reaches the command.
|
|
175
|
+
A fake connectors MCP server serves a connector read and write. The tests
|
|
176
|
+
cover a chat turn and `--resume`; `read_file`, `write_file`, and `edit_file` on
|
|
177
|
+
real workspace files without approval; `execute` in the workspace; a path
|
|
178
|
+
outside the workspace, which is refused; `write_file` waiting for approval
|
|
179
|
+
when `approval.always` names it, and rejected file and connector writes that
|
|
180
|
+
never run; a connector read and an approved connector write that runs once; a
|
|
181
|
+
connector tool named `read_file`, which the model sees as
|
|
182
|
+
`connector_connector_read_file` beside a connector tool named
|
|
183
|
+
`connector_read_file`; `write_todos`; a `task` subagent that writes a
|
|
184
|
+
workspace file inside one tool Step, and a `task` that waits for approval
|
|
185
|
+
when `approval.always` names `read_file`; and a large `execute` result that
|
|
186
|
+
lands in the session's own artifacts directory. Backend tests cover links to
|
|
187
|
+
files outside the workspace, which `ls`, `glob`, and `grep` leave out with
|
|
188
|
+
and without ripgrep, which the Python search never opens, and which reads and
|
|
189
|
+
writes refuse; two sessions that write the same large-result path without
|
|
190
|
+
seeing each other's file; a session directory that is a link, which is an
|
|
191
|
+
error result; looser artifact directories, which become 0700; and the
|
|
192
|
+
removal of a session's artifacts after 30 days, which never follows a link.
|
|
193
|
+
They also cover the offered tools, which are Deep Agents' own and none of
|
|
194
|
+
the CLI core's file and shell tools; switched-off file and shell tools, which
|
|
195
|
+
are not offered; a model change and a `system_prompt` in the session
|
|
196
|
+
settings, which reach the next model request; and a key in the `deepagents`
|
|
197
|
+
section. The command also checks that its graph has no summarization, that
|
|
198
|
+
its tool rules cover every tool of the graph, and that a model from the
|
|
199
|
+
session settings reaches every model call.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# dex-agents-deepagents-cli
|
|
2
|
+
|
|
3
|
+
`dex-agents-deepagents-cli` provides the `dex-agents-deepagents` command. It
|
|
4
|
+
runs a [Deep Agents](https://github.com/langchain-ai/deepagents) agent as a
|
|
5
|
+
durable Dex agent session and chats with it in your terminal. The shared
|
|
6
|
+
CLI core, [`dex-agents-cli-core`](../core/README.md), starts or reuses
|
|
7
|
+
`dexcli dev`, connects the connectors MCP server, and runs the Worker. This
|
|
8
|
+
package only builds the agent with `create_deep_agent` and runs it on the
|
|
9
|
+
[LangGraph adapter](../../../python/langgraph/README.md).
|
|
10
|
+
|
|
11
|
+
## Running it
|
|
12
|
+
|
|
13
|
+
The command needs Python 3.11 or later and a key for the model's provider.
|
|
14
|
+
The default model is OpenAI's, so set `OPENAI_API_KEY`:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
export OPENAI_API_KEY=sk-...
|
|
18
|
+
uvx --from dex-agents-deepagents-cli dex-agents-deepagents
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The first run asks the `init` questions and writes
|
|
22
|
+
`~/.dex/agents/deepagents.yaml`. Then type a message at the `>` prompt.
|
|
23
|
+
Approve or reject tool calls with `y` or `n`, and press Ctrl-D to exit. The
|
|
24
|
+
session stays in Dex, and the command prints the `--resume` line that
|
|
25
|
+
continues it. See the [CLI core README](../core/README.md#running-a-command)
|
|
26
|
+
for every subcommand and option, and [`agents/cli`](../../README.md) for the
|
|
27
|
+
configuration file.
|
|
28
|
+
|
|
29
|
+
The command never prints or stores provider keys. The chat model reads its
|
|
30
|
+
key from the provider's standard environment variable.
|
|
31
|
+
|
|
32
|
+
## Configuration
|
|
33
|
+
|
|
34
|
+
`model` is a LangChain `provider:model` ID, as `init_chat_model` takes it. It
|
|
35
|
+
defaults to `openai:gpt-5.2`; set `model` in the file or pass `--model` to
|
|
36
|
+
change it. An `openai:` model uses the Responses API, as Deep Agents does.
|
|
37
|
+
|
|
38
|
+
| Provider | Model example | Environment |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| OpenAI | `openai:gpt-5.2` | `OPENAI_API_KEY`, optional `OPENAI_BASE_URL` |
|
|
41
|
+
| Anthropic | `anthropic:claude-opus-5-5` | `ANTHROPIC_API_KEY` |
|
|
42
|
+
| Google | `google_genai:gemini-2.5-flash` | `GOOGLE_API_KEY` |
|
|
43
|
+
|
|
44
|
+
Other providers need their LangChain integration package, such as
|
|
45
|
+
`uvx --from dex-agents-deepagents-cli --with langchain-mistralai dex-agents-deepagents`.
|
|
46
|
+
|
|
47
|
+
`system_prompt` replaces the default instructions. Session settings may
|
|
48
|
+
change the model and the instructions from the next turn on. The
|
|
49
|
+
`deepagents` section has no options yet, and any key in it is a configuration
|
|
50
|
+
error.
|
|
51
|
+
|
|
52
|
+
## Deep Agents' tools in Dex
|
|
53
|
+
|
|
54
|
+
The agent keeps Deep Agents' own tools and behavior. The CLI core adds the
|
|
55
|
+
connector, web fetch, and browser tools on top. The agent runs on the
|
|
56
|
+
LangGraph adapter, so every model call is a `RunModel` Step and every tool
|
|
57
|
+
call runs in its own tool Step, after approval when its policy asks for it.
|
|
58
|
+
|
|
59
|
+
| Deep Agents tool | In this command |
|
|
60
|
+
| --- | --- |
|
|
61
|
+
| `ls`, `read_file`, `glob`, `grep` | Reads of the real workspace files. They run at once. |
|
|
62
|
+
| `write_file`, `edit_file`, `delete` | Writes of the real workspace files. They run at once unless `approval.always` names the tool. |
|
|
63
|
+
| `execute` | Runs a command with `/bin/sh` in the workspace. It runs at once unless `approval.always` names it; `local_tools.shell.allow` has no effect. |
|
|
64
|
+
| `task` | Runs a subagent inside the call's tool Step. It runs at once unless `approval.always` names any Deep Agents tool, because the subagent may call it without its own approval. |
|
|
65
|
+
| `write_todos` | Updates the todo list in the agent's state. It runs at once. |
|
|
66
|
+
|
|
67
|
+
- Deep Agents asks for no approval unless `interrupt_on` names a tool, and
|
|
68
|
+
this command follows it: `approval.always` plays the role of
|
|
69
|
+
`interrupt_on`. Connector writes always wait for approval.
|
|
70
|
+
- The file tools use Deep Agents' `LocalShellBackend` on the host's paths,
|
|
71
|
+
rooted at the workspace, so a file tool and `execute` name a file the same
|
|
72
|
+
way. Paths are absolute. A path that resolves outside the workspace fails
|
|
73
|
+
with an error the model sees, and `ls`, `glob`, and `grep` leave out
|
|
74
|
+
entries whose real path is outside it, such as a link to a file elsewhere;
|
|
75
|
+
`grep` never opens such a file.
|
|
76
|
+
- That check is a guardrail against mistaken paths, not a sandbox.
|
|
77
|
+
`execute` runs any command with your permissions, without approval by
|
|
78
|
+
default. A link that changes during a call, or a hard link in the
|
|
79
|
+
workspace to a file elsewhere, is not detected. Use OS-level isolation,
|
|
80
|
+
such as a container, when the agent must not reach other files.
|
|
81
|
+
- `local_tools.files` and `local_tools.shell.enabled` switch the tools on and
|
|
82
|
+
off per turn. `task` needs both, because a subagent uses both.
|
|
83
|
+
- Each tool Step attempt runs Deep Agents' tool middleware around the tool,
|
|
84
|
+
such as `FilesystemMiddleware`'s eviction of a large result to a file. A
|
|
85
|
+
retried attempt runs it again. The
|
|
86
|
+
session Flow sets the adapter's `should_defer_tool_calls_before_middleware`
|
|
87
|
+
for that. Deep Agents writes evicted results and long user messages under
|
|
88
|
+
the paths `/large_tool_results/` and `/conversation_history/`, which its
|
|
89
|
+
file tools read. Each session keeps them in its own directory,
|
|
90
|
+
`~/.dex/agents/deepagents-artifacts/<SHA-256 of the session ID>/`, so two
|
|
91
|
+
sessions never see each other's files and a restarted Worker on the same
|
|
92
|
+
machine finds them. Before each file operation the command checks every
|
|
93
|
+
directory from `deepagents-artifacts` down: you own it, it is no link, and
|
|
94
|
+
a looser mode becomes 0700. `~/.dex` and `~/.dex/agents` keep their mode
|
|
95
|
+
but must not be another user's link. A failed check is an error result of
|
|
96
|
+
that tool call.
|
|
97
|
+
- When the command starts, it deletes the artifacts of every session whose
|
|
98
|
+
files changed more than 30 days ago. It never follows a link, and it logs
|
|
99
|
+
each directory it removes or cannot remove. A session resumed after that
|
|
100
|
+
can no longer read its earlier large results.
|
|
101
|
+
- `edit_file`, `execute`, and `task` calls are never retried, so a Worker that
|
|
102
|
+
dies during one records `outcome_unknown`. `write_file` and `delete` calls
|
|
103
|
+
may run again after a failure.
|
|
104
|
+
- `write_todos` is LangChain's `TodoListMiddleware` tool. It returns a graph
|
|
105
|
+
`Command` that the adapter records and applies. Each turn starts from the
|
|
106
|
+
stored messages, so the todo list lasts for one turn; the plan stays in the
|
|
107
|
+
conversation.
|
|
108
|
+
- `task` runs the subagent's model and tool calls inline, in one tool Step.
|
|
109
|
+
They have no Steps or approvals of their own, use the configuration file's
|
|
110
|
+
model even when session settings change it, and do not count in the
|
|
111
|
+
session's usage. Connector tools are not offered to a subagent.
|
|
112
|
+
- A connector tool whose name a Deep Agents tool has gets the prefix
|
|
113
|
+
`connector_`, such as `connector_read_file`. The other connector tools keep
|
|
114
|
+
their names.
|
|
115
|
+
- Every model call gets the turn's instructions, the workspace path, and the
|
|
116
|
+
turn's model through the adapter's `select_turn_chat_model`.
|
|
117
|
+
- Deep Agents' summarization is turned off for now. It would make an extra
|
|
118
|
+
model call with the configuration file's model inside a `RunModel` Step, so
|
|
119
|
+
a model from the session settings would not reach it. The session does not
|
|
120
|
+
compact either: Dex compaction needs
|
|
121
|
+
the model's context window, which the configuration does not set. A long
|
|
122
|
+
session ends when its input no longer fits the model's context window;
|
|
123
|
+
start a new session then.
|
|
124
|
+
|
|
125
|
+
## Images
|
|
126
|
+
|
|
127
|
+
`/image <path>` attaches an image file to the next message. The command gives
|
|
128
|
+
the LangChain adapter the media store of `media.store`, so the model sees the
|
|
129
|
+
image, and images that tools return go to the same store. See
|
|
130
|
+
[Images](../../README.md#images).
|
|
131
|
+
|
|
132
|
+
## Development
|
|
133
|
+
|
|
134
|
+
Develop with uv 0.12.2. The package resolves `dex-agents`, the LangGraph
|
|
135
|
+
adapter, the CLI core, and the test support package from this repository by
|
|
136
|
+
path. `ci.sh` installs the locked dependencies, checks that LangChain and
|
|
137
|
+
LangGraph match the adapter's lock, checks lint and types, and runs the tests
|
|
138
|
+
against a private `dexcli dev`:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
cd agents/cli/python/deepagents
|
|
142
|
+
DEXCLI=/path/to/dexcli ./ci.sh
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The tests run the command in a pseudo-terminal with a private home. The chat
|
|
146
|
+
model calls the scripted Responses API of
|
|
147
|
+
[`dex-agents-cli-testing`](../testing) on 127.0.0.1; a refused proxy stops
|
|
148
|
+
any other request, and no provider variable of the host reaches the command.
|
|
149
|
+
A fake connectors MCP server serves a connector read and write. The tests
|
|
150
|
+
cover a chat turn and `--resume`; `read_file`, `write_file`, and `edit_file` on
|
|
151
|
+
real workspace files without approval; `execute` in the workspace; a path
|
|
152
|
+
outside the workspace, which is refused; `write_file` waiting for approval
|
|
153
|
+
when `approval.always` names it, and rejected file and connector writes that
|
|
154
|
+
never run; a connector read and an approved connector write that runs once; a
|
|
155
|
+
connector tool named `read_file`, which the model sees as
|
|
156
|
+
`connector_connector_read_file` beside a connector tool named
|
|
157
|
+
`connector_read_file`; `write_todos`; a `task` subagent that writes a
|
|
158
|
+
workspace file inside one tool Step, and a `task` that waits for approval
|
|
159
|
+
when `approval.always` names `read_file`; and a large `execute` result that
|
|
160
|
+
lands in the session's own artifacts directory. Backend tests cover links to
|
|
161
|
+
files outside the workspace, which `ls`, `glob`, and `grep` leave out with
|
|
162
|
+
and without ripgrep, which the Python search never opens, and which reads and
|
|
163
|
+
writes refuse; two sessions that write the same large-result path without
|
|
164
|
+
seeing each other's file; a session directory that is a link, which is an
|
|
165
|
+
error result; looser artifact directories, which become 0700; and the
|
|
166
|
+
removal of a session's artifacts after 30 days, which never follows a link.
|
|
167
|
+
They also cover the offered tools, which are Deep Agents' own and none of
|
|
168
|
+
the CLI core's file and shell tools; switched-off file and shell tools, which
|
|
169
|
+
are not offered; a model change and a `system_prompt` in the session
|
|
170
|
+
settings, which reach the next model request; and a key in the `deepagents`
|
|
171
|
+
section. The command also checks that its graph has no summarization, that
|
|
172
|
+
its tool rules cover every tool of the graph, and that a model from the
|
|
173
|
+
session settings reaches every model call.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dex-agents-deepagents-cli"
|
|
3
|
+
version = "0.6.1"
|
|
4
|
+
description = "The dex-agents-deepagents command: a durable Deep Agents agent in your terminal"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "LicenseRef-Sustainable-Use-1.0"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Development Status :: 3 - Alpha",
|
|
11
|
+
"Programming Language :: Python :: 3",
|
|
12
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
13
|
+
"Typing :: Typed",
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"deepagents>=0.7.32,<0.8",
|
|
17
|
+
"dex-agents==0.6.1",
|
|
18
|
+
"dex-agents-cli-core==0.6.1",
|
|
19
|
+
"dex-agents-langgraph==0.6.1",
|
|
20
|
+
"dex-python-sdk==1.45.0",
|
|
21
|
+
"langchain>=1.4.7,<2",
|
|
22
|
+
"langchain-core>=1.7.3,<1.8",
|
|
23
|
+
"langchain-openai>=1.0,<2",
|
|
24
|
+
"langgraph>=1.2.19,<1.3",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[[project.authors]]
|
|
28
|
+
name = "Super Durable"
|
|
29
|
+
|
|
30
|
+
[project.scripts]
|
|
31
|
+
dex-agents-deepagents = "dex_agents_deepagents_cli:run"
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/superdurable/dex/tree/main/agents/cli/python/deepagents"
|
|
35
|
+
Repository = "https://github.com/superdurable/dex"
|
|
36
|
+
Changelog = "https://github.com/superdurable/dex/blob/main/agents/CHANGELOG.md"
|
|
37
|
+
|
|
38
|
+
[dependency-groups]
|
|
39
|
+
dev = [
|
|
40
|
+
"dex-agents-cli-testing",
|
|
41
|
+
"mypy>=1.15,<2",
|
|
42
|
+
"pexpect>=4.9,<5",
|
|
43
|
+
"pytest>=8.3,<9",
|
|
44
|
+
"pytest-asyncio>=0.26,<2",
|
|
45
|
+
"ruff>=0.8,<0.9",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[build-system]
|
|
49
|
+
requires = ["uv_build>=0.12.2,<0.13"]
|
|
50
|
+
build-backend = "uv_build"
|
|
51
|
+
|
|
52
|
+
[tool.uv]
|
|
53
|
+
required-version = "==0.12.2"
|
|
54
|
+
|
|
55
|
+
[tool.uv.sources.dex-agents]
|
|
56
|
+
path = "../../../python/core"
|
|
57
|
+
editable = true
|
|
58
|
+
|
|
59
|
+
[tool.uv.sources.dex-agents-cli-core]
|
|
60
|
+
path = "../core"
|
|
61
|
+
editable = true
|
|
62
|
+
|
|
63
|
+
[tool.uv.sources.dex-agents-cli-testing]
|
|
64
|
+
path = "../testing"
|
|
65
|
+
editable = true
|
|
66
|
+
|
|
67
|
+
[tool.uv.sources.dex-agents-langgraph]
|
|
68
|
+
path = "../../../python/langgraph"
|
|
69
|
+
editable = true
|
|
70
|
+
|
|
71
|
+
[tool.ruff]
|
|
72
|
+
target-version = "py311"
|
|
73
|
+
line-length = 100
|
|
74
|
+
|
|
75
|
+
[tool.ruff.lint]
|
|
76
|
+
select = [
|
|
77
|
+
"E",
|
|
78
|
+
"F",
|
|
79
|
+
"W",
|
|
80
|
+
"I",
|
|
81
|
+
"B",
|
|
82
|
+
"UP",
|
|
83
|
+
"ASYNC",
|
|
84
|
+
"RUF",
|
|
85
|
+
]
|
|
86
|
+
ignore = [
|
|
87
|
+
"ASYNC109",
|
|
88
|
+
"ASYNC110",
|
|
89
|
+
"ASYNC220",
|
|
90
|
+
"ASYNC221",
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
[tool.ruff.lint.isort]
|
|
94
|
+
known-first-party = [
|
|
95
|
+
"dex_agents",
|
|
96
|
+
"dex_agents_cli_core",
|
|
97
|
+
"dex_agents_cli_testing",
|
|
98
|
+
"dex_agents_deepagents_cli",
|
|
99
|
+
"dex_agents_langgraph",
|
|
100
|
+
"tests",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
[tool.mypy]
|
|
104
|
+
python_version = "3.11"
|
|
105
|
+
strict = true
|
|
106
|
+
files = [
|
|
107
|
+
"src",
|
|
108
|
+
"tests",
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
[[tool.mypy.overrides]]
|
|
112
|
+
module = [
|
|
113
|
+
"pexpect",
|
|
114
|
+
"pexpect.*",
|
|
115
|
+
]
|
|
116
|
+
ignore_missing_imports = true
|
|
117
|
+
|
|
118
|
+
[tool.pytest.ini_options]
|
|
119
|
+
testpaths = ["tests"]
|
|
120
|
+
pythonpath = ["."]
|
|
121
|
+
asyncio_mode = "auto"
|
|
122
|
+
asyncio_default_fixture_loop_scope = "session"
|
|
123
|
+
asyncio_default_test_loop_scope = "session"
|