I’d start simpler: give the Deep Agent the browser, API, and infrastructure tools directly and let it dynamically plan, execute, observe, and replan.
I don’t think I’d introduce LangGraph as a separate testing layer just because the plans are dynamic. The graph does not need to encode every possible test path.
For example, the user could ask:
“Test checkout on production. If it fails, determine whether the problem is the frontend, API, or payment service.”
The agent might decide at runtime to do:
browser.login()
→ browser.checkout()
→ checkout fails
→ api.check_order()
→ infra.check_payment_service()
→ infra.inspect_logs()
→ diagnose root cause
→ report
A different request can produce a completely different sequence. The plan is runtime state, not a graph you have to predefine.
That is also how I’d think about the LangChain stack today. Deep Agents are the higher level agent harness, while LangGraph provides the underlying runtime capabilities. Deep Agents also support custom subagents, including CompiledSubAgent instances backed by a compiled LangGraph graph. (Docs by LangChain)
So I’d introduce an explicit LangGraph subgraph only when a particular part of the system needs deterministic orchestration.
For example, deployment verification might be:
deploy
→ wait for rollout
→ health check
→ smoke test
→ check metrics
→ rollback if necessary
That is a great candidate for a LangGraph subgraph because you may want explicit state transitions, retries, persistence, and recovery. LangGraph checkpoints state and supports durable execution and interrupts around those workflows. (Docs by LangChain)
I’d also put Human in the Loop at the risk boundary, not everywhere.
Safe operations can run autonomously:
browser.navigate()
browser.screenshot()
api.get()
api.health_check()
infra.read_logs()
infra.get_metrics()
But I’d require approval for things like:
infra.restart_service()
infra.execute_command()
api.delete_resource()
api.modify_production_data()
deploy()
rollback()
LangChain’s current HITL middleware supports exactly this pattern: specific tools can interrupt execution for approve, edit, or reject, with graph state persisted so the run can safely resume afterward. Deep Agents expose the same interrupt_on mechanism. (Docs by LangChain)
So my architecture would be:
So my rule of thumb would be:
Agent first, workflow where needed, human at the risk boundary.
I would not start with Deep Agent → LangGraph testing subagent → tools unless the testing domain itself becomes complex enough to justify that additional abstraction. Start with the Deep Agent and well scoped tools, then introduce LangGraph subgraphs for the workflows that genuinely need deterministic state, retries, approvals, or recovery. (Docs by LangChain)