#5742·deepagents

dcode local custom tool subagents

Author: gr3enarr0wCreated Aug 22, 2026Updated Sep 17, 2026
Labelstype:featureorg:externalpriority:backlogpackage:dcode

Submission checklist

  • This is a feature request, not a bug report.
  • I searched existing issues and didn't find this feature.
  • I checked the docs and README for existing functionality.
  • This request applies to this repo (deepagents) and not an external package.

Area (Required)

  • deepagents (SDK)
  • dcode
  • talon
  • acp
  • evals
  • harbor
  • daytona
  • modal
  • quickjs
  • runloop
  • vercel
  • langsmith-sandbox
  • Other / not sure / general

Feature description

dcode's filesystem-based subagent loader (deepagents_code/subagents.py, .deepagents/agents/{name}/AGENTS.md) only accepts name, description, model, and a system-prompt body (_parse_subagent_file). There's no way to give a locally-defined subagent its own tools — it inherits whatever filesystem-restricted toolset the main agent has (_inject_fs_tools_into_subagents in agent.py), nothing more. A subagent that needs a capability the main agent doesn't have — a custom API client, a specialized search tool, anything built as a real Python tool — can't be defined through this config surface at all.

This is a real gap, not a hypothetical: the SDK itself already has a type that would solve it. deepagents.middleware.subagents.CompiledSubAgent (identified by a "runnable" key) lets a subagent be a fully custom compiled LangGraph graph — its own tools, its own state, anything. agent.py's _inject_fs_tools_into_subagents already type-checks for it (raises ValueError if one shows up, since it can't safely inject filesystem middleware into an opaque compiled graph) — the SDK-level plumbing exists. dcode's own loader just never constructs one; _load_subagents_from_dir only ever produces plain markdown-sourced SubAgent dicts.

Concretely, this blocks a common pattern: I have a separate deepagents-built agent (a research assistant with a custom research_web tool wired to real search providers, citation screening, source authority tiering) that I'd like to delegate to as a subagent from dcode, in-process, no second server. Today there's no config surface for that — the only two paths are (1) markdown subagents, which can't carry tools, or (2) [async_subagents] (AsyncSubAgentMiddleware), which requires running the agent as a separate Agent-Protocol-compliant server process (self-hosted is fine, no LangGraph Platform/cloud dependency — but it's still a second process and a different protocol shape than an in-process compiled graph).

This isn't unique to dcode — checked the closest peers: Claude Code's .claude/agents/*.md subagents (documented tools/disallowedTools frontmatter fields) and OpenCode's .opencode/agents/ (permission/tools fields) both let a subagent select or restrict which of the parent's existing tools it gets, but neither lets a local subagent bring a new tool implementation that doesn't already exist in the harness. Cursor's docs state subagents "inherit all tools from the parent" outright — same limitation, no scoping at all. So this specific capability doesn't exist as user-facing precedent in any comparable CLI I found.

Proposed solution (optional)

Why this specific mechanism, not just any mechanism: the deepagents SDK's own official docs (docs.langchain.com/oss/python/deepagents/subagents) already document and sanction exactly this pattern — build a custom agent with create_agent(model=..., tools=[...], system_prompt=...), then wrap it as CompiledSubAgent(name=..., description=..., runnable=custom_graph). This isn't a new abstraction being proposed; it's dcode's config loader not exposing a pattern the SDK already ships, documents, and endorses as first-class. agent.py's _inject_fs_tools_into_subagents already type-checks for CompiledSubAgent and defensively declines to touch it — the plumbing already assumes this type will show up.

Extend the .deepagents/agents/{name}/ convention to optionally load a compiled agent instead of (or alongside) an AGENTS.md prompt file — e.g. .deepagents/agents/{name}/agent.py exporting a graph (a compiled StateGraph/Runnable), picked up by _load_subagents_from_dir and passed through as a CompiledSubAgent entry rather than a raw SubAgent dict.

Why in-process rather than routing everything through async_subagents/A2A: Anthropic's own multi-agent research system write-up (anthropic.com/engineering/multi-agent-research-system) found a multi-agent architecture beat single-agent Claude Opus 4 by 90.2% on their internal research evals, but at ~15× the token cost of a single chat, with token usage alone explaining 80% of the performance variance — the isolation (a subagent with its own scoped context) is where the value comes from, not the transport. Making that isolation depend on standing up a second Agent-Protocol server is real, avoidable overhead for something that can be a straight in-process delegation call.

Why scoped-tools frontmatter (PR #5537) doesn't close this gap by itself: that PR is a real, tested precedent for the general direction — it extends dcode's markdown-subagent loader to expose SubAgent["tools"]/["skills"] fields the SDK already honors but dcode's loader never authored (13 unit tests, full suite passing, real end-to-end verification against create_cli_agent, closed only by the "no linked issue" bot, not on technical merits). But it only lets a subagent select from dcode's existing tool registry — it has no path to attach a genuinely new tool implementation, like a custom research_web client, that isn't already part of dcode's toolset. The two are complementary: #5537's mechanism scopes down, this one adds capability the harness doesn't already have.

The token-cost case for scoping tightly, with real numbers: PR #5537's own measurement — a workspace with 3 MCP servers (~50 tools) and 10 subagents, capturing what create_sub_agent actually receives, found all 10 subagents held all 50 tools, including subagents whose job never touches most of them. This isn't an isolated finding: a Claude Code user's measurement (anthropics/claude-code#11364) with 7 MCP servers active found tool definitions alone consumed 67,300 tokens — 33.7% of a 200k context budget — before any conversation began. Every subagent that inherits the full toolset pays that tax again. A mechanism that lets a subagent carry precisely the tool(s) it needs — not the harness's entire registry, not nothing — is the direct fix for a measured, recurring cost, not a hypothetical one.

Given this executes arbitrary local Python, it should sit behind a trust/approval gate — not something silently auto-loaded from a directory with no confirmation step. This isn't overcaution: config-driven local code execution in agent tooling has a real incident history. CVE-2025-59536 (Claude Code, CVSS 8.7–8.8, confirmed via NVD) let code in a project execute before the user accepted the startup trust dialog. VS Code's Workspace Trust model exists for exactly this class of risk ("a language extension may execute code from the currently loaded workspace... when in doubt, leave a folder in Restricted Mode"). The same gating already under discussion on #5309 for extensions applies directly here.

Additional context (optional)

Related: #5309 (extensions API trust mechanism — the same gating question applies here), #5532 (A2A client support — the remote, cross-process path to a similar outcome; this issue is the local, in-process alternative for when running a second server isn't warranted), #5537 (closed, no linked issue — scopes existing tools per subagent via frontmatter; complementary to, not overlapping with, this proposal).

Also related, distinct scope: #3909 ("Use configured custom agents as subagents") asks for reusing a configured agent as a subagent within a session — UI visibility of delegation, whether history persists, invocation style, no thread restart. One line in its proposed solution — "tool/middleware configuration where supported" — touches the same territory this issue covers, but #3909 doesn't specify a mechanism for it (no mention of CompiledSubAgent, no code-level detail). This issue is that mechanism: a concrete, source-cited answer to that one line, scoped narrowly to custom-tool subagents rather than the full session/UX surface #3909 covers.