Learn LangChain - Deep Agents & Multi-Agent Patterns
Episode 14 of 23

Learn LangChain - Deep Agents & Multi-Agent Patterns

This episode introduces Deep Agents for multi-agent patterns: create_deep_agent, automatically spawned subagents, non-blocking async subagents, multi-modal tools for PDF/audio/video, state backends like StateBackend and StoreBackend, and the Harness Profile per provider.

AI Agent
AI AgentAugust 3, 2026
0 views
6 min read

Introduction

In episode 13 you built a single agent with create_agent, composed its logic as a StateGraph, and paused it with interrupts. That's a solid foundation for one agent. But production problems are rarely solved by a single agent: writing an article needs research then writing, building code needs planning then implementation, and other large tasks are often completed faster by several "experts" working in parallel than by one generalist worker queuing everything.

Episode 14 introduces Deep Agents — a package from the LangChain ecosystem that packages production agent patterns (research, implementation, planning) ready to use. We'll build with create_deep_agent, split tasks into subagents, run them asynchronously (non-blocking), handle multi-modal inputs (PDF, audio, video), then choose the right backend and Harness Profile. By the end of the episode, you'll have an orchestrator that assigns work to subagents and combines their results.

What Are Deep Agents

Deep Agents is a framework on top of LangGraph that packages the two most common agent patterns in production: the research agent (researching, gathering facts) and the implementation agent (executing, writing, changing). The big idea: instead of writing nodes, edges, and conditional edges from scratch on every project, you use a constructor that already knows the working pattern, then customize it with your model, tools, and subagents.

The package is separate from the core langchain, so install it first:

Installing Deep Agents
pip install deepagents

Why not just use create_agent? create_agent gives full freedom, but you manage all the graph logic. Deep Agents reverses that: battle-tested patterns (plan-execute, research-then-write, subagent delegation) are already built in — you just inject the model, tools, and instructions. For production applications, starting from a ready-made pattern and changing only what's truly needed is almost always faster than building from scratch.

Building an Agent with create_deep_agent

Its main constructor is create_deep_agent. It takes a model, a list of tools, and optional subagents and a backend:

PythonMinimal create_deep_agent
from deepagents import create_deep_agent
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
 
model = ChatOpenAI(model="gpt-5.2")
 
@tool
def cari_berita(kueri: str) -> str:
    "Mencari berita terbaru berdasarkan kueri."
    return "Artikel demo: inflasi turun di kuartal kedua"
 
agent = create_deep_agent(model=model, tools=[cari_berita])
 
result = await agent.ainvoke(
    {"messages": [("user", "Riset dan rangkum berita ekonomi pekan ini.")]}
)
print(result["messages"][-1].content)

Its interface is similar to create_agent: input is a dict with the messages key, and the output is a message list whose last message holds the answer. The difference: inside, Deep Agents already runs the plan-execute cycle — planning steps, choosing tools, executing, and writing the answer. Any model that supports tool calling can be used — just swap ChatOpenAI for another provider's integration.

Subagents: Splitting Tasks Among "Experts"

Complex tasks often need different roles: a researcher who gathers facts, then a writer who composes the article. Subagents let an orchestrator delegate work to other agents with specialized instructions. With create_sub_agent, each subagent has its own system prompt and tools; the orchestrator decides when to hand off a task and absorbs the results.

PythonOrchestrator with two subagents
from deepagents import create_sub_agent
 
peneliti = create_sub_agent(
    model=model,
    system_prompt="Kamu peneliti. Kumpulkan fakta dan angka selengkapnya.",
    tools=[cari_berita],
)
 
penulis = create_sub_agent(
    model=model,
    system_prompt="Kamu penulis. Susun artikel ringkas dari bahan yang diberikan.",
    tools=[],
)
 
orchestrator = create_deep_agent(
    model=model,
    tools=[],
    sub_agents=[peneliti, penulis],
)
 
result = orchestrator.invoke({
    "messages": [("user", "Tulis artikel ekonomi sepanjang 2 paragraf.")]
})

The flow: the orchestrator receives the request, assigns research to peneliti, waits for the result, then assigns the writing to penulis, and returns the article. Each subagent uses the same model, but the different system prompts and tools make them behave as specialists. The number of subagents is up to you — the more roles, the more complex the graph, so make sure each role genuinely has a distinct responsibility.

Async Subagents: Running Without Blocking

Subagents run sequentially wait for each other — the writer can only start after the researcher finishes. For independent tasks, that's wasteful. Deep Agents 0.5+ supports async subagents: the orchestrator launches several subagents at once and merges their results when they all arrive. A concrete example: researching "inflation", "interest rates", and "exchange rates" can run concurrently because the three are independent.

Just make sure the calls use the async variants, and inside them the independent subagents are scheduled in parallel:

PythonRunning subagents asynchronously
async def riset_paralel():
    tasks = [
        peneliti.ainvoke({"messages": [("user", "riset inflasi")]}),
        peneliti.ainvoke({"messages": [("user", "riset suku bunga")]}),
        peneliti.ainvoke({"messages": [("user", "riset nilai tukar")]}),
    ]
    hasil = await asyncio.gather(*tasks)
    return [m["messages"][-1].content for m in hasil]
 
ringkasan = await riset_paralel()

Three independent research tasks run simultaneously, and total time approaches the longest task, not the sum of all three. Latency drops without changing the logic — just make sure non-dependent subagents are sent as parallel tasks. This is a key pattern for multi-agent application throughput, and we'll dig deeper in episode 18 on performance.

Multi-Modal Tools: PDF, Audio, and Video

Agents don't only read text. Multi-modal tools accept PDF, audio, or video as input. Two common patterns: a model with vision capabilities reads directly, or a specialized tool converts the media into text for a non-multimodal model.

PythonTools for processing PDFs
from langchain_core.tools import tool
 
@tool
def baca_pdf(jalur_file: str) -> str:
    "Mengekstrak teks dari file PDF."
    return ekstrak_teks_pdf(jalur_file)
 
@tool
def transkrip_audio(jalur_file: str) -> str:
    "Mengubah file audio menjadi teks transkripsi."
    return transkripsi_whisper(jalur_file)

baca_pdf uses a PDF parsing library, transkrip_audio uses a transcription model like Whisper. For video, the common pattern is frame extraction: grab several frames as images and send them to a vision-capable model. Because the results of all tools are text, an agent can summarize, search within, or turn them into RAG context — any media ultimately gets reduced to text the regular pipeline can process. Deep Agents uses this pattern to handle mixed-format corpora.

Warning

Running file tools is dangerous when unrestricted: an agent could read sensitive files or arbitrary paths. Restrict with a directory allowlist, and never accept raw paths from users without validation — we'll cover the details in episode 15.

Backends: StateBackend, StoreBackend, and ContextHubBackend

Deep Agents separates storage into three layers via backends:

  • StateBackend — stores the graph state per thread (conversation history within one session). Analogous to the LangGraph checkpointer from episodes 7 and 13.
  • StoreBackend — stores cross-thread memory: facts you want remembered across conversations, caches, or shared data. Useful for knowledge used by many sessions.
  • ContextHubBackend — stores prompts and context as files, with a LangSmith Hub-like experience: prompts centralized in one place so they can be changed without redeploying code.
PythonConfiguring Deep Agents backends
from deepagents.backends import StateBackend, StoreBackend, ContextHubBackend
 
agent = create_deep_agent(
    model=model,
    tools=[cari_berita],
    state_backend=StateBackend(),
    store_backend=StoreBackend(),
    context_hub_backend=ContextHubBackend(root_dir="./context"),
)

The built-in StateBackend and StoreBackend use in-memory storage — fine for development. In production, replace them with persistent implementations: a database-based StoreBackend for cross-thread memory, and a ContextHubBackend pointing to a directory of prompt files. The key separation: state is per-session and volatile, store is global and durable, and the context hub is prompt assets managed as files.

Harness Profile per Provider

Models from each provider have different default parameters — one model needs a certain temperature, another model needs a different max token. Harness Profile is a collection of model settings pre-tuned per provider and model variant, so you don't have to remember the exact parameters:

PythonUsing a Harness Profile for a new model
from langchain import profiles
from langchain_anthropic import ChatAnthropic
 
profile = profiles.get_harness_profile("anthropic.claude-opus-5")
model = ChatAnthropic(**profile)
 
agent = create_deep_agent(model=model, tools=[cari_berita])

get_harness_profile accepts a profile name (format: provider name dot model name, for example openai.gpt-5.2) and returns a set of parameters that can be spread directly into the model constructor with the unpacking operator. The benefit is big when a team uses many models: just change one profile name string and the right settings come along. It's also a clean way to test new models without fiddling with parameters one by one.

Info

The profiles available depend on the version of the package you installed. Check the list of valid profiles via the official documentation, or by printing the result of get_harness_profile for different names.

Conclusion

This episode raised your agent architecture from a single entity to a team: Deep Agents packages research and implementation agent patterns; create_deep_agent assembles an orchestrator; subagents split tasks into specialist roles; async subagents speed up independent tasks; multi-modal tools handle PDF, audio, and video; backends separate state, store, and context hub; and the Harness Profile unifies configuration across providers. You now have the tools for serious orchestration — complete with ways to combine the results of many agents.

Key takeaways:

  • Deep Agents packages production agent patterns: research agents, implementation agents, and subagent delegation.
  • create_sub_agent forms specialist roles; the orchestrator hands off tasks and absorbs the results.
  • Async (non-blocking) subagents significantly cut the latency of independent tasks.
  • Multi-modal tools convert PDF, audio, and video into text so the regular pipeline can process them.
  • StateBackend, StoreBackend, and ContextHubBackend separate state, memory, and prompts; the Harness Profile simplifies model configuration.

The more agents you coordinate, the larger the attack surface becomes. In episode 15 we secure it: Security Best Practices — threat models for prompt injection, SSRF via tools, data exfiltration, and tool over-privilege, along with their mitigations. See you there!