# Deep Agent state cumbersome

**URL:** <https://forum.langchain.com/t/deep-agent-state-cumbersome/4078>\
**Category:** LangGraph\
**Tags:** intro-to-langgraph, python-help\
**Created:** [July 2, 2026, 1:09pm UTC](https://forum.langchain.com/t/deep-agent-state-cumbersome/4078 "2026-07-02T13:09:03Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![sasadangelo](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/sasadangelo/32/3242_2.png) [@sasadangelo](https://forum.langchain.com/u/sasadangelo)\
**Post date:** [July 2, 2026, 1:09pm UTC](https://forum.langchain.com/t/deep-agent-state-cumbersome/4078/1 "2026-07-02T13:09:03Z")

</div>

Hi Team,

I’m working on a project where I need to retrieve participants from a support ticket as well as from several other data sources. The challenge is that the required information is spread across multiple systems, so it has to be orchestrated through map/reduce-style operations.

My Deep Agent design is largely prompt-driven. The main conversational Deep Agent is intentionally very lightweight: almost all of the orchestration logic lives in `AGENTS.md` and `SKILL.md` files. I split the workflow into multiple subagents, each with its own `SKILL.md`.

My use case is roughly **60–70% deterministic** and **30–40% LLM-driven**.

I rely on the LLM for tasks such as:

- generating the execution plan,
- extracting participants from unstructured text,
- composing the final response.

Everything else is deterministic and mainly consists of calling APIs and processing structured data.

After reviewing several Deep Agent examples shared by my team, I noticed that almost everything is prompt-based, including the agent’s state, which is maintained in the conversation context. The main agent delegates work to subagents, each subagent performs API calls or LLM reasoning, returns its result, and the main agent orchestrates the overall workflow. As a consequence, the shared state also lives in the conversation context.

What I’m struggling with is that there doesn’t seem to be an equivalent of the strongly typed shared state you would normally build with LangGraph.

I experimented with storing the intermediate state in the filesystem, for example:

```auto
/work/<ticket_number>/
    participants.json
    emails.json
    ...

```

This approach works technically, but I’m concerned about isolation. What guarantees are there that an LLM won’t accidentally read files belonging to another ticket if they’re accessible through the filesystem?

In this workflow, one subagent produces part of the state and another consumes it. Since map/reduce operations don’t naturally fit a traditional LangGraph execution graph, it feels like additional orchestration logic is needed to implement them cleanly.

I also built an alternative solution based on compiled LangGraph graphs with a Pydantic state model. From a technical perspective, this approach works much better because it provides explicit state management. However, the architecture team considers it too rigid and prefers a pure Deep Agent approach.

This leads me to a few questions:

- Am I using Deep Agents in the wrong way for this type of orchestration?
- Is there a recommended pattern for sharing structured state across multiple cooperating subagents?
- Does Deep Agent support true parallel execution through prompting? If so, what is the recommended approach to execute multiple subagents concurrently to reduce latency?
- Are there any reference implementations or GitHub repositories demonstrating a Deep Agent orchestrating multiple subagents, where each contributes a portion of the overall state and the main agent aggregates the final result?

I’d really appreciate any guidance, best practices, or examples.

Thanks in advance!

PS  
I looked at deep agent documentation and I’ve already built my deep agent, however, the prompt driven approach doesn’t satisfy me with data reliability and performance are really bad (but today everything is sequence and I am trying to figure out how to do parallelism of subagents).

---

<div class="post-metadata">

**Author:** ![dariel.datoon](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/dariel.datoon/32/3152_2.png) [@dariel.datoon](https://forum.langchain.com/u/dariel.datoon)\
**Post date:** [July 2, 2026, 6:45pm UTC](https://forum.langchain.com/t/deep-agent-state-cumbersome/4078/2 "2026-07-02T18:45:09Z")

</div>

Hi @sasadangelo — a few current `deepagents` features map directly onto what you’re hitting, and importantly you **don’t** have to abandon typed state to go “pure Deep Agent.”

**1. Typed shared state (instead of stuffing everything into conversation context or loose JSON files)**

Deep Agents supports a strongly-typed `state_schema` — the equivalent of the LangGraph/Pydantic state you’re used to. Subclass `DeepAgentState` (this preserves the built-in `DeltaChannel` reducer on `messages`, keeping checkpoint growth linear) and pass it in:

```python
from typing import TypedDict
from deepagents import create_deep_agent
from deepagents.graph import DeepAgentState

class Participant(TypedDict):
    name: str
    role: str
    source: str

class TicketState(DeepAgentState):
    ticket_number: str
    participants: list[Participant]

agent = create_deep_agent(model=..., state_schema=TicketState)

```

Tools read/write that state through the injected `ToolRuntime` (`runtime.state["participants"]`) instead of parsing free text. Rule of thumb from the docs: **mutable data checkpointed with the thread → `state_schema`; immutable per-run inputs** (ticket ID, credentials) → runtime **context**. Declarative `SubAgent` specs automatically inherit the parent `state_schema`, so every subagent sees the same typed fields. (Caveat: pre-compiled `CompiledSubAgent` and remote `AsyncSubAgent` specs don’t inherit it — compile those with a compatible schema.)

Docs: [Custom state schema](https://docs.langchain.com/oss/python/deepagents/context-engineering#custom-state-schema)

**2. Parallelism (your performance problem) → Dynamic Subagents**

This is the big one for you, and it’s brand new. Regular subagents are dispatched one tool call at a time, which is why everything runs sequentially. **Dynamic subagents** let the agent write short orchestration code (in a sandboxed QuickJS interpreter) that dispatches subagents via a built-in `task()` global — so you get real concurrency with plain `Promise.all`, plus looping/branching/conditional logic:

```javascript
const sources = ["ticket", "crm", "directory", "email"];
const results = await Promise.all(sources.map(src =>
  task({ description: `Extract participants from ${src}`, subagentType: "participant-extractor" })
));

```

That’s the **“fanout and synthesize”** pattern — a direct match for gathering participants across multiple data sources in parallel and then combining them. Because the fan-out is expressed in code rather than model-driven tool sequencing, you get deterministic coverage, which suits your mostly-deterministic workload. The **“classify and act”** pattern (route mixed inputs to specialists) also lines up well with ticket triage.

Setup:

```python
from deepagents import create_deep_agent
from langchain_quickjs import CodeInterpreterMiddleware # install: uv add "deepagents[quickjs]"

agent = create_deep_agent(
    model=...,
    middleware=[CodeInterpreterMiddleware()],
    subagents=[participant_extractor, ...],
)

```

Blog: [Introducing Dynamic Subagents in Deep Agents](https://www.langchain.com/blog/introducing-dynamic-subagents-in-deep-agents) · Docs: [Subagents](https://docs.langchain.com/oss/python/deepagents/subagents)

(If you ever need genuinely remote or long-running background subagents rather than in-process fan-out, there’s also `AsyncSubAgentMiddleware`, added in [v0.5](https://www.langchain.com/blog/deep-agents-0-6) — but for your case dynamic subagents are the simpler, lower-infra answer.)

**3. File isolation between tickets**

Instead of hand-managing `/work/<ticket_number>/…` paths and hoping the LLM stays in its lane, swap the filesystem **backend**. A store-backed or composite backend namespaces storage per ticket so isolation is structural, not prompt-dependent. There’s also an `enabled_tools` allowlist on the filesystem middleware to restrict which file operations the agent can call at all.

Docs: [Customize Deep Agents](https://docs.langchain.com/oss/python/deepagents/customization)

**Bottom line:** you can keep your typed, structured modeling — express it as a `DeepAgentState` subclass, use dynamic subagents for parallel participant gathering, and a store/composite backend for per-ticket isolation. Hope that helps!

---

<div class="post-metadata">

**Author:** ![sasadangelo](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/sasadangelo/32/3242_2.png) [@sasadangelo](https://forum.langchain.com/u/sasadangelo)\
**Post date:** [July 3, 2026, 9:08am UTC](https://forum.langchain.com/t/deep-agent-state-cumbersome/4078/3 "2026-07-03T09:08:30Z")

</div>

Hi @dariel.datoon Thank you.  
You gave me a lot of insights. I was starting to explore a CompositeBackend with FilesystemBackend virtual=True for AGENTS.md and SKILL.md and StateBackend to have the JSON file as represantation of intermediate state but the possibility to use Pydantic is a game changer.

All this stuff is new to me so I need time to understand. I’ll be back as soon as I have more experience on it.

Can I have also map/reduce operations with pydantic in deep agents?

---

<div class="post-metadata">

**Author:** ![dariel.datoon](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/dariel.datoon/32/3152_2.png) [@dariel.datoon](https://forum.langchain.com/u/dariel.datoon)\
**Post date:** [July 3, 2026, 3:09pm UTC](https://forum.langchain.com/t/deep-agent-state-cumbersome/4078/4 "2026-07-03T15:09:32Z")

</div>

**Yes — map/reduce works natively through agent state.** That’s exactly what reducers are for.

Annotate a state key with `operator.add` and every subagent that writes to it **appends** instead of overwriting. That’s your reduce step, for free:

```python
import operator
from typing import Annotated
from pydantic import BaseModel
from deepagents.graph import DeepAgentState

class Participant(BaseModel):
    name: str
    role: str
    source: str

class TicketState(DeepAgentState):
    ticket_number: str
    participants: Annotated[list[Participant], operator.add] # ← fan-in

```

Now fan out extraction across your sources (map), and each subagent returns its slice into `participants` — LangGraph merges them concurrently, no clobbering. Need custom merge logic (e.g. dedup by email)? Swap `operator.add` for your own reducer function.

This is LangGraph’s Send-based map/reduce, and Deep Agents inherits it. Docs: [Graph API — reducers & the Send API](https://docs.langchain.com/oss/python/langgraph/graph-api).

And yes, your `CompositeBackend` + `StateBackend` design is right — `StateBackend` scopes files to the thread, so per-ticket isolation comes free.

Hope that helps!
