Skill v1.0.1
Automated scan100/1004 files
version: "1.0.1" name: deepagents-code-review description: Reviews Deep Agents code for bugs, anti-patterns, and improvements. Use when reviewing code that uses create_deep_agent, backends, subagents, middleware, or human-in-the-loop patterns. Catches common configuration and usage mistakes.
Deep Agents Code Review
When reviewing Deep Agents code, check for these categories of issues.
Review gates (evidence-bound)
Run these steps in order before and while you write findings. Skipping a step is a failed review.
- Locate — Enumerate call sites in scope (
create_deep_agent,CompiledSubAgent,CompositeBackend, custombackend=,interrupt_on,checkpointer,store). Pass: You list each relevant file path and line number (or a grep/search result that proves where the code lives). - Anchor — For each suspected issue, tie it to quoted or line-referenced code from those files, not to imports or names alone. Pass: Every finding includes evidence (
path:lineplus a short quote or “absent parameter” note showing the gap). - Classify — Map each anchored issue to one category below (Critical → Performance) and a severity. Pass: The category label matches what the cited code actually does or omits.
- Runtime claims — If you say something will error, fail at runtime, or leak data, Pass: The cited snippet shows the exact API combo (e.g.
interrupt_onset with nocheckpointerin the same construction path), or you state uncertain and what would confirm it.
If you cannot satisfy step 1, stop and say what file or search is missing instead of inferring issues from memory.
Critical Issues
1. Missing Checkpointer with interrupt_on
# BAD - interrupt_on without checkpointeragent = create_deep_agent(tools=[send_email],interrupt_on={"send_email": True},# No checkpointer! Interrupts will fail)# GOOD - checkpointer required for interruptsfrom langgraph.checkpoint.memory import InMemorySaveragent = create_deep_agent(tools=[send_email],interrupt_on={"send_email": True},checkpointer=InMemorySaver(),)
2. Missing Store with StoreBackend
# BAD - StoreBackend without storefrom deepagents.backends import StoreBackendagent = create_deep_agent(backend=lambda rt: StoreBackend(rt),# No store! Will raise ValueError at runtime)# GOOD - provide storefrom langgraph.store.memory import InMemoryStorestore = InMemoryStore()agent = create_deep_agent(backend=lambda rt: StoreBackend(rt),store=store,)
3. Missing thread_id with Checkpointer
# BAD - no thread_id when using checkpointeragent = create_deep_agent(checkpointer=InMemorySaver())agent.invoke({"messages": [...]}) # Error!# GOOD - always provide thread_idconfig = {"configurable": {"thread_id": "user-123"}}agent.invoke({"messages": [...]}, config)
4. Relative Paths in Filesystem Tools
# BAD - relative paths not supportedread_file(path="src/main.py")read_file(path="./config.json")# GOOD - absolute paths requiredread_file(path="/workspace/src/main.py")read_file(path="/config.json")
5. Windows Paths in Virtual Filesystem
# BAD - Windows paths rejectedread_file(path="C:\\Users\\file.txt")write_file(path="D:/projects/code.py", content="...")# GOOD - Unix-style virtual pathsread_file(path="/workspace/file.txt")write_file(path="/projects/code.py", content="...")
Backend Issues
6. StateBackend Expecting Persistence
# BAD - expecting files to persist across threadsagent = create_deep_agent() # Uses StateBackend by default# Thread 1agent.invoke({"messages": [...]}, {"configurable": {"thread_id": "a"}})# Agent writes to /data/report.txt# Thread 2 - file won't exist!agent.invoke({"messages": [...]}, {"configurable": {"thread_id": "b"}})# Agent tries to read /data/report.txt - NOT FOUND# GOOD - use StoreBackend or CompositeBackend for cross-thread persistenceagent = create_deep_agent(backend=CompositeBackend(default=StateBackend(),routes={"/data/": StoreBackend(store=store)},),store=store,)
7. FilesystemBackend Without root_dir Restriction
# BAD - unrestricted filesystem accessagent = create_deep_agent(backend=FilesystemBackend(root_dir="/"), # Full system access!)# GOOD - scope to project directoryagent = create_deep_agent(backend=FilesystemBackend(root_dir="/home/user/project"),)
8. CompositeBackend Route Order Confusion
# BAD - shorter prefix shadows longer prefixagent = create_deep_agent(backend=CompositeBackend(default=StateBackend(),routes={"/mem/": backend_a, # This catches /mem/long-term/ too!"/mem/long-term/": backend_b, # Never reached},),)# GOOD - CompositeBackend sorts by length automatically# But be explicit about your intent:agent = create_deep_agent(backend=CompositeBackend(default=StateBackend(),routes={"/memories/": persistent_backend,"/workspace/": ephemeral_backend,},),)
9. Expecting execute Tool Without SandboxBackend
# BAD - execute tool won't work with StateBackendagent = create_deep_agent() # Default StateBackend# Agent calls execute("ls -la") → Error: not supported# GOOD - use FilesystemBackend for shell executionagent = create_deep_agent(backend=FilesystemBackend(root_dir="/project"),)# Agent calls execute("ls -la") → Works
Subagent Issues
10. Subagent Missing Required Fields
# BAD - missing required fieldsagent = create_deep_agent(subagents=[{"name": "helper",# Missing: description, system_prompt, tools}])# GOOD - all required fields presentagent = create_deep_agent(subagents=[{"name": "helper","description": "General helper for misc tasks","system_prompt": "You are a helpful assistant.","tools": [], # Can be empty but must be present}])
11. Subagent Name Collision
# BAD - duplicate subagent namesagent = create_deep_agent(subagents=[{"name": "research", "description": "A", ...},{"name": "research", "description": "B", ...}, # Collision!])# GOOD - unique namesagent = create_deep_agent(subagents=[{"name": "web-research", "description": "Web-based research", ...},{"name": "doc-research", "description": "Document research", ...},])
12. Overusing Subagents for Simple Tasks
# BAD - subagent overhead for trivial task# In system prompt or agent behavior:"Use the task tool to check the current time""Delegate file reading to a subagent"# GOOD - use subagents for complex, isolated work"Use the task tool for multi-step research that requires many searches""Delegate the full analysis workflow to a subagent"
13. CompiledSubAgent Without Proper State
# BAD - subgraph with incompatible state schemafrom langgraph.graph import StateGraphclass CustomState(TypedDict):custom_field: str # No messages field!sub_builder = StateGraph(CustomState)# ... build graphsubgraph = sub_builder.compile()agent = create_deep_agent(subagents=[CompiledSubAgent(name="custom",description="Custom workflow",runnable=subgraph, # State mismatch!)])# GOOD - ensure compatible state or use message-based interfaceclass CompatibleState(TypedDict):messages: Annotated[list, add_messages]custom_field: str
Middleware Issues
14. Middleware Order Misunderstanding
# BAD - expecting custom middleware to run firstclass PreProcessMiddleware(AgentMiddleware):def transform_request(self, request):# Expecting this runs before built-in middlewarereturn requestagent = create_deep_agent(middleware=[PreProcessMiddleware()])# Actually runs AFTER TodoList, Filesystem, SubAgent, etc.# GOOD - understand middleware runs after built-in stack# Built-in order:# 1. TodoListMiddleware# 2. FilesystemMiddleware# 3. SubAgentMiddleware# 4. SummarizationMiddleware# 5. AnthropicPromptCachingMiddleware# 6. PatchToolCallsMiddleware# 7. YOUR MIDDLEWARE HERE# 8. HumanInTheLoopMiddleware (if interrupt_on set)
15. Middleware Mutating Request/Response
# BAD - mutating instead of returning new objectclass BadMiddleware(AgentMiddleware):def transform_request(self, request):request.messages.append(extra_message) # Mutation!return request# GOOD - return modified copyclass GoodMiddleware(AgentMiddleware):def transform_request(self, request):return ModelRequest(messages=[*request.messages, extra_message],**other_fields)
16. Middleware Tools Without Descriptions
# BAD - tool without docstring@tooldef my_tool(arg: str) -> str:return process(arg)class MyMiddleware(AgentMiddleware):tools = [my_tool] # LLM won't know how to use it!# GOOD - descriptive docstring@tooldef my_tool(arg: str) -> str:"""Process the input string and return formatted result.Args:arg: The string to processReturns:Formatted result string"""return process(arg)
System Prompt Issues
17. Duplicating Built-in Tool Instructions
# BAD - re-explaining what middleware already coversagent = create_deep_agent(system_prompt="""You have access to these tools:- write_todos: Create task lists- read_file: Read files from the filesystem- task: Delegate to subagentsWhen using files, always use absolute paths...""")# This duplicates what FilesystemMiddleware and TodoListMiddleware inject!# GOOD - focus on domain-specific guidanceagent = create_deep_agent(system_prompt="""You are a code review assistant.Workflow:1. Read the files to review2. Create a todo list of issues found3. Delegate deep analysis to subagents if needed4. Compile findings into a report""")
18. Contradicting Built-in Instructions
# BAD - contradicting default behavioragent = create_deep_agent(system_prompt="""Never use the task tool.Always process everything in the main thread.Don't use todos, just remember everything.""")# Fighting against the framework!# GOOD - work with the frameworkagent = create_deep_agent(system_prompt="""For simple tasks, handle directly.For complex multi-step research, use subagents.Track progress with todos for tasks with 3+ steps.""")
19. Missing Stopping Criteria
# BAD - no guidance on when to stopagent = create_deep_agent(system_prompt="Research everything about the topic thoroughly.")# Agent may run indefinitely!# GOOD - define completion criteriaagent = create_deep_agent(system_prompt="""Research the topic with these constraints:- Maximum 5 web searches- Stop when you have 3 reliable sources- Limit subagent delegations to 2 parallel tasks- Summarize findings within 500 words""")
Performance Issues
20. Not Parallelizing Independent Subagents
# BAD - sequential subagent calls (in agent behavior)# Agent calls: task(research topic A) → wait → task(research topic B) → wait# GOOD - parallel subagent calls# Agent calls in single turn:# task(research topic A)# task(research topic B)# task(research topic C)# All run concurrently!# Guide via system prompt:agent = create_deep_agent(system_prompt="""When researching multiple topics,launch all research subagents in parallel in a single response.""")
21. Large Files in State
# BAD - writing large files to StateBackend# Agent writes 10MB log file to /output/full_log.txt# This bloats every checkpoint!# GOOD - use FilesystemBackend for large files or paginateagent = create_deep_agent(backend=CompositeBackend(default=StateBackend(), # Small filesroutes={"/large_files/": FilesystemBackend(root_dir="/tmp/agent"),},),)
22. InMemorySaver in Production
# BAD - ephemeral checkpointer in productionagent = create_deep_agent(checkpointer=InMemorySaver(), # Lost on restart!)# GOOD - persistent checkpointerfrom langgraph.checkpoint.postgres import PostgresSaveragent = create_deep_agent(checkpointer=PostgresSaver.from_conn_string(DATABASE_URL),)
23. Missing Recursion Awareness
# BAD - no guard against long-running loopsagent = create_deep_agent(system_prompt="Keep improving the solution until it's perfect.")# May hit recursion limit (default 1000)# GOOD - explicit iteration limitsagent = create_deep_agent(system_prompt="""Improve the solution iteratively:- Maximum 3 revision cycles- Stop if quality score > 90%- Stop if no improvement after 2 iterations""")
Code Review Checklist
See `references/checklist.md` for the full per-area checklist (Configuration, Backends, Subagents, Middleware, System Prompt, Performance). Run it after the Review gates and the numbered issue catalogue above.