deep-agents-orchestration

INVOKE THIS SKILL when using subagents, task planning, or human approval in Deep Agents. Covers SubAgentMiddleware, TodoList for planning, and HITL interrupts.

npx skills add https://github.com/langchain-ai/langchain-skills --skill deep-agents-orchestration
Deep Agents include three orchestration capabilities:
  1. SubAgentMiddleware: Delegate work via task tool to specialized agents
  2. TodoListMiddleware: Plan and track tasks via write_todos tool
  3. HumanInTheLoopMiddleware: Require approval before sensitive operations

All three are automatically included in create_deep_agent().


Subagents (Task Delegation)

Use Subagents WhenUse Main Agent When
Task needs specialized toolsGeneral-purpose tools sufficient
Want to isolate complex workSingle-step operation
Need clean context for main agentContext bloat acceptable
Main agent has `task` tool -> creates fresh subagent -> subagent executes autonomously -> returns final report.

Default subagent: "general-purpose" - automatically available with same tools/config as main agent.

Create a custom "researcher" subagent with specialized tools for academic paper search.
from deepagents import create_deep_agent
from langchain.tools import tool

@tool
def search_papers(query: str) -> str:
    """Search academic papers."""
    return f"Found 10 papers about {query}"

agent = create_deep_agent(
    subagents=[
        {
            "name": "researcher",
            "description": "Conduct web research and compile findings",
            "system_prompt": "Search thoroughly, return concise summary",
            "tools": [search_papers],
        }
    ]
)

# Main agent delegates: task(agent="researcher", instruction="Research AI trends")
Create a custom "researcher" subagent with specialized tools for academic paper search.
import { createDeepAgent } from "deepagents";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const searchPapers = tool(
  async ({ query }) => `Found 10 papers about ${query}`,
  { name: "search_papers", description: "Search papers", schema: z.object({ query: z.string() }) }
);

const agent = await createDeepAgent({
  subagents: [
    {
      name: "researcher",
      description: "Conduct web research and compile findings",
      systemPrompt: "Search thoroughly, return concise summary",
      tools: [searchPapers],
    }
  ]
});

// Main agent delegates: task(agent="researcher", instruction="Research AI trends")
Configure a subagent with HITL approval for sensitive operations.
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver

agent = create_deep_agent(
    subagents=[
        {
            "name": "code-deployer",
            "description": "Deploy code to production",
            "system_prompt": "You deploy code after tests pass.",
            "tools": [run_tests, deploy_to_prod],
            "interrupt_on": {"deploy_to_prod": True},  # Require approval
        }
    ],
    checkpointer=MemorySaver()  # Required for interrupts
)
Subagents are stateless - provide complete instructions in a single call.
# WRONG: Subagents don't remember previous calls
# task(agent='research', instruction='Find data')
# task(agent='research', instruction='What did you find?')  # Starts fresh!

# CORRECT: Complete instructions upfront
# task(agent='research', instruction='Find data on AI, save to /research/, return summary')
Subagents are stateless - provide complete instructions in a single call.
// WRONG: Subagents don't remember previous calls
// task research: Find data
// task research: What did you find?  // Starts fresh!

// CORRECT: Complete instructions upfront
// task research: Find data on AI, save to /research/, return summary
Custom subagents don't inherit skills from the main agent.
# WRONG: Custom subagent won't have main agent's skills
agent = create_deep_agent(
    skills=["/main-skills/"],
    subagents=[{"name": "helper", ...}]  # No skills inherited
)

# CORRECT: Provide skills explicitly (general-purpose subagent DOES inherit)
agent = create_deep_agent(
    skills=["/main-skills/"],
    subagents=[{"name": "helper", "skills": ["/helper-skills/"], ...}]
)

TodoList (Task Planning)

Use TodoList WhenSkip TodoList When
Complex multi-step tasksSimple single-action tasks
Long-running operationsQuick operations (< 3 steps)
write_todos(todos: list[dict]) -> None

Each todo item has:

  • content: Description of the task
  • status: One of "pending", "in_progress", "completed"
Invoke an agent that automatically creates a todo list for a multi-step task.
from deepagents import create_deep_agent

agent = create_deep_agent()  # TodoListMiddleware included by default

result = agent.invoke({
    "messages": [{"role": "user", "content": "Create a REST API: design models, implement CRUD, add auth, write tests"}]
}, config={"configurable": {"thread_id": "session-1"}})

# Agent's planning via write_todos:
# [
#   {"content": "Design data models", "status": "in_progress"},
#   {"content": "Implement CRUD endpoints", "status": "pending"},
#   {"content": "Add authentication", "status": "pending"},
#   {"content": "Write tests", "status": "pending"}
# ]
Invoke an agent that automatically creates a todo list for a multi-step task.
import { createDeepAgent } from "deepagents";

const agent = await createDeepAgent();  // TodoListMiddleware included

const result = await agent.invoke({
  messages: [{ role: "user", content: "Create a REST API: design models, implement CRUD, add auth, write tests" }]
}, { configurable: { thread_id: "session-1" } });
Access the todo list from the agent's final state after invocation.
result = agent.invoke({...}, config={"configurable": {"thread_id": "session-1"}})

# Access todo list from final state
todos = result.get("todos", [])
for todo in todos:
    print(f"[{todo['status']}] {todo['content']}")
Todo list state requires a thread_id for persistence across invocations.
# WRONG: Fresh state each time without thread_id
agent.invoke({"messages": [...]})

# CORRECT: Use thread_id
config = {"configurable": {"thread_id": "user-session"}}
agent.invoke({"messages": [...]}, config=config)  # Todos preserved

Human-in-the-Loop (Approval Workflows)

Use HITL WhenSkip HITL When
High-stakes operations (DB writes, deployments)Read-only operations
Compliance requires human oversightFully automated workflows
Configure which tools require human approval before execution.
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver

agent = create_deep_agent(
    interrupt_on={
        "write_file": True,  # All decisions allowed
        "execute_sql": {"allowed_decisions": ["approve", "reject"]},
        "read_file": False,  # No interrupts
    },
    checkpointer=MemorySaver()  # REQUIRED for interrupts
)
Configure which tools require human approval before execution.
import { createDeepAgent } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";

const agent = await createDeepAgent({
  interruptOn: {
    write_file: true,
    execute_sql: { allowedDecisions: ["approve", "reject"] },
    read_file: false,
  },
  checkpointer: new MemorySaver()  // REQUIRED
});
Complete workflow: trigger an interrupt, check state, approve action, and resume execution.
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver
from langgraph.types import Command

agent = create_deep_agent(
    interrupt_on={"write_file": True},
    checkpointer=MemorySaver()
)

config = {"configurable": {"thread_id": "session-1"}}

# Step 1: Agent proposes write_file - execution pauses
result = agent.invoke({
    "messages": [{"role": "user", "content": "Write config to /prod.yaml"}]
}, config=config)

# Step 2: Check for interrupts
state = agent.get_state(config)
if state.next:
    print(f"Pending action")

# Step 3: Approve and resume
result = agent.invoke(Command(resume={"decisions": [{"type": "approve"}]}), config=config)
Complete workflow: trigger an interrupt, check state, approve action, and resume execution.
import { createDeepAgent } from "deepagents";
import { MemorySaver, Command } from "@langchain/langgraph";

const agent = await createDeepAgent({
  interruptOn: { write_file: true },
  checkpointer: new MemorySaver()
});

const config = { configurable: { thread_id: "session-1" } };

// Step 1: Agent proposes write_file - execution pauses
let result = await agent.invoke({
  messages: [{ role: "user", content: "Write config to /prod.yaml" }]
}, config);

// Step 2: Check for interrupts
const state = await agent.getState(config);
if (state.next) {
  console.log("Pending action");
}

// Step 3: Approve and resume
result = await agent.invoke(
  new Command({ resume: { decisions: [{ type: "approve" }] } }), config
);
Reject a pending action with feedback, prompting the agent to try a different approach.
result = agent.invoke(
    Command(resume={"decisions": [{"type": "reject", "message": "Run tests first"}]}),
    config=config,
)
Reject a pending action with feedback, prompting the agent to try a different approach.
const result = await agent.invoke(
  new Command({ resume: { decisions: [{ type: "reject", message: "Run tests first" }] } }),
  config,
);
Edit the proposed action arguments before allowing execution.
result = agent.invoke(
    Command(resume={"decisions": [{
        "type": "edit",
        "edited_action": {
            "name": "execute_sql",
            "args": {"query": "DELETE FROM users WHERE last_login < '2020-01-01' LIMIT 100"},
        },
    }]}),
    config=config,
)
### What Agents CAN Configure
  • Subagent names, tools, models, system prompts
  • Which tools require approval
  • Allowed decision types per tool
  • TodoList content and structure

What Agents CANNOT Configure

  • Tool names (task, write_todos)
  • HITL protocol (approve/edit/reject structure)
  • Skip checkpointer requirement for interrupts
  • Make subagents stateful (they're ephemeral)
Checkpointer is required when using interrupt_on for HITL workflows.
# WRONG
agent = create_deep_agent(interrupt_on={"write_file": True})

# CORRECT
agent = create_deep_agent(interrupt_on={"write_file": True}, checkpointer=MemorySaver())
Checkpointer is required when using interruptOn for HITL workflows.
// WRONG
const agent = await createDeepAgent({ interruptOn: { write_file: true } });

// CORRECT
const agent = await createDeepAgent({ interruptOn: { write_file: true }, checkpointer: new MemorySaver() });
A consistent thread_id is required to resume interrupted workflows.
# WRONG: Can't resume without thread_id
agent.invoke({"messages": [...]})

# CORRECT
config = {"configurable": {"thread_id": "session-1"}}
agent.invoke({...}, config=config)
# Resume with Command using same config
agent.invoke(Command(resume={"decisions": [{"type": "approve"}]}), config=config)
A consistent thread_id is required to resume interrupted workflows.
// WRONG: Can't resume without thread_id
await agent.invoke({ messages: [...] });

// CORRECT
const config = { configurable: { thread_id: "session-1" } };
await agent.invoke({ messages: [...] }, config);
// Resume with Command using same config
await agent.invoke(new Command({ resume: { decisions: [{ type: "approve" }] } }), config);
Interrupts happen BETWEEN invoke() calls, not mid-execution.
result = agent.invoke({...}, config=config)       # Step 1: triggers interrupt
if "__interrupt__" in result:                      # Step 2: check for interrupt
    result = agent.invoke(                         # Step 3: resume
        Command(resume={"decisions": [{"type": "approve"}]}),
        config=config,
    )

Mais skills de langchain-ai

langgraph-docs
langchain-ai
Acesse a documentação do LangGraph para construir agentes com estado e fluxos de trabalho multiagente. Busca a documentação oficial do LangGraph em Python, abordando máquinas de estado, design de agentes baseado em grafos e padrões com intervenção humana. Prioriza a documentação relevante por tipo de consulta: guias de implementação para perguntas de "como fazer", páginas conceituais para teoria, tutoriais para exemplos completos e referências de API para detalhes técnicos. Seleciona automaticamente de 2 a 4 URLs de documentação mais relevantes e recupera seu conteúdo para responder...
official
langgraph-human-in-the-loop
langchain-ai
Pausar a execução do grafo para revisão, aprovação ou validação humana e, em seguida, retomar com a contribuição do usuário. Requer três componentes: um checkpointer (InMemorySaver ou PostgresSaver), um ID de thread na configuração e payloads de interrupção serializáveis em JSON. interrupt(value) pausa e exibe dados; Command(resume=value) retoma e retorna esse valor ao nó pausado. Todo código antes de interrupt() é reexecutado na retomada, portanto, os efeitos colaterais devem ser idempotentes (use upsert, não insert). Suporta fluxos de aprovação,...
official
web-research
langchain-ai
Use esta habilidade para solicitações relacionadas a pesquisa na web; ela fornece uma abordagem estruturada para realizar pesquisas web abrangentes.
official
langchain-oss-primer
langchain-ai
SEMPRE COMEÇE AQUI para qualquer projeto de construção de agentes LangChain, Deep Agents ou LangGraph. Ponto de partida obrigatório antes de escolher outras habilidades ou escrever qualquer…
official
skill-creator
langchain-ai
Guia para criar skills eficazes que estendem as capacidades do agente com conhecimento especializado, fluxos de trabalho ou integrações de ferramentas. Use esta skill quando o usuário…
official
social-media
langchain-ai
Cria posts para redes sociais específicas da plataforma, com conteúdo baseado em pesquisa e imagens de acompanhamento geradas. Suporta posts no LinkedIn (1.300 caracteres com tom profissional) e threads no Twitter/X (280 caracteres por tweet no formato 1/🧵). Exige delegar a pesquisa a um subagente antes de escrever e, em seguida, ler os resultados para garantir precisão e relevância. Gera imagens sociais atraentes automaticamente usando a ferramenta generate_social_image, com composições ousadas e de alto contraste otimizadas para telas pequenas...
official
deep-agents-memory
langchain-ai
Backends de memória e arquivos plugáveis para Deep Agents com opções de roteamento efêmero, persistente e híbrido. Quatro tipos de backend: StateBackend (efêmero, com escopo de thread), StoreBackend (persistente entre sessões), FilesystemBackend (acesso real a disco para desenvolvimento local) e CompositeBackend (roteia diferentes caminhos para diferentes backends). FilesystemMiddleware fornece seis ferramentas de operação de arquivos: ls, read_file, write_file, edit_file, glob, grep. CompositeBackend usa correspondência de prefixo mais longo para rotear...
official
deep-agents-orchestration
langchain-ai
Orquestrar subagentes, planejar tarefas de múltiplas etapas e exigir aprovação humana para operações sensíveis. Delegar trabalho a subagentes especializados por meio da ferramenta de tarefas; subagentes personalizados suportam conjuntos de ferramentas isolados e prompts de sistema, enquanto o subagente "de propósito geral" padrão herda a configuração do agente principal. Planejar e acompanhar fluxos de trabalho complexos com write_todos, organizando tarefas entre estados pendente, em andamento e concluído; requer um thread_id para persistência entre invocações. Implementar...
official