Module 2: Agentic Research with the Explore Subagent

Exploration Patterns — Top-Down, Dependency-Following, Feature-Tracing

Exploration Patterns — Top-Down, Dependency-Following, Feature-Tracing

Capsule description

Knowing how to use Explore and understanding the difference between semantic search and grep is necessary but not sufficient. What separates an efficient investigator from one who wanders aimlessly is having exploration patterns — predefined strategies to approach different types of questions about a codebase.

In this capsule you're going to learn three exploration patterns that cover 90% of the investigations you'll do in code: top-down (from the general to the specific), dependency-following (following imports and calls), and feature-tracing (tracing a feature end-to-end). Each pattern has a purpose, a starting point, and a sequence of steps.

The connection with the project is direct: in capsule 05, the questions you have to answer require different patterns. "What's the general architecture?" is top-down. "What does the payments module depend on?" is dependency-following. "How does a login request flow?" is feature-tracing. Without these patterns, you're going to improvise and waste time.


The Problem: Exploration Without a Strategy

What exploration without a pattern looks like

# Typical session without a strategy:
> "Explore this project"
# Result: a generic list of files and directories

> "What does this project do?"
# Result: a vague description based on the README

> "Show me the important code"
# Result: important for what? No context, no direction

# 15 minutes later: you have data but no comprehension

The problem isn't the tool — it's the lack of strategy. Exploring without a pattern is like walking through a city without a map: you see things, but you don't build a coherent mental model.

What exploration with a pattern looks like

# Session with a top-down strategy:
> "Use Explore to describe the first-level directory structure
   and the purpose of each main folder"
# Result: a clear map of the main components

> "Now dig into src/api/ — what routes does it expose
   and how are they organized?"
# Result: a list of endpoints grouped by domain

> "Dig into the POST /api/orders endpoint —
   what functions does it call and what services does it use?"
# Result: a complete call chain

# 15 minutes later: you have a layered mental model

Pattern 1: Top-Down (From the General to the Specific)

When to use it

Use top-down when you need to understand the general structure of a codebase or a module. It's the starting pattern — you almost always start here.

Analogy

It's like looking at Google Maps: you start at the country level, then city, then street, then building. You never start with the building.

Sequence of steps

Level 1: Project structure
    ↓
Level 2: Main components
    ↓
Level 3: Modules within a component
    ↓
Level 4: Key functions within a module
    ↓
Level 5: Implementation of a specific function

Implementation with Explore

Level 1 — Project structure:

> "Use Explore to describe the first-level directory
   structure of this project. For each main folder,
   state its purpose in one sentence."

# Expected output:
# /src — Main source code
#   /api — HTTP endpoints (FastAPI routes)
#   /services — Business logic
#   /models — Data models (SQLAlchemy)
#   /utils — Shared utilities
#   /config — App configuration
# /tests — Unit and integration tests
# /migrations — Database migrations (Alembic)
# /scripts — Deployment and maintenance scripts
# /docs — Documentation

Level 2 — Main components:

> "Use Explore to dig into src/api/. How many
   endpoints are there, how are they organized, and what's
   the routing pattern?"

# Expected output:
# src/api/ uses a routers-by-domain pattern:
#   /routes/auth.py — 4 endpoints (login, register, logout, refresh)
#   /routes/users.py — 5 endpoints (CRUD + profile)
#   /routes/orders.py — 6 endpoints (CRUD + status + payment)
#   /routes/products.py — 4 endpoints (CRUD)
#   /middleware/ — auth, cors, logging, rate_limit
# Total: 19 endpoints, organized by business domain

Level 3 — Specific module:

> "Use Explore to analyze src/services/order_service.py.
   What methods does it expose, what dependencies does it have, and what's
   the main logic of create_order()?"

# Expected output: a complete breakdown of the service
# with methods, dependencies, and the create_order flow

Level 4 — Specific function:

> "Use Explore to analyze the create_order() function
   in detail. What validations does it do, what external
   services does it call, and how does it handle errors?"

# Expected output: a line-by-line analysis of the function

Common mistakes with top-down

  • Skipping levels: going straight from structure to a specific function loses context
  • Staying at the high level: exploring only the structure without digging deeper doesn't produce real comprehension
  • Not documenting each level: the value of top-down is the map you build progressively

Pattern 2: Dependency-Following (Following the Connections)

When to use it

Use dependency-following when you need to understand what depends on what. It's essential before refactoring (Module 4) because a change in one module affects all its dependents.

Analogy

It's like pulling a thread: you start with one module and follow each connection (import, call, inheritance) to map the entire network of dependencies.

Sequence of steps

Starting module (the one you're investigating)
    ↓
What does it import? (outgoing dependencies)
    ↓
Who imports it? (incoming dependents)
    ↓
For each critical dependency: repeat
    ↓
Result: a dependency graph

Implementation with Explore

Step 1 — Outgoing dependencies (what does it depend on?):

> "Use Explore to list all the dependencies
   of src/services/payment_service.py. Include internal
   and external imports, and for each one state what
   is used from that module."

# Expected output:
# External dependencies:
#   - stripe (stripe.Charge, stripe.Customer)
#   - sqlalchemy (Session, select)
#   - pydantic (BaseModel)
#
# Internal dependencies:
#   - src/models/transaction.py (Transaction model)
#   - src/models/user.py (User model)
#   - src/services/email_service.py (send_receipt)
#   - src/utils/currency.py (convert_currency)
#   - src/config/settings.py (STRIPE_API_KEY)

Step 2 — Incoming dependents (who depends on this?):

> "Use Explore to find all the files that
   import or use PaymentService or payment_service"

# Expected output:
# Dependents:
#   - src/api/routes/checkout.py — calls create_payment()
#   - src/api/routes/orders.py — calls process_refund()
#   - src/services/order_service.py — calls verify_payment()
#   - src/tasks/recurring_payments.py — calls charge_subscription()
#   - tests/test_payment_service.py — tests for the service

Step 3 — Dig into critical dependencies:

> "Use Explore to analyze the dependency between
   payment_service and email_service. What functions
   of email_service does payment_service use, and what happens
   if email_service fails?"

# Expected output: an analysis of the coupling
# and behavior in case of failure

Step 4 — Build the graph:

> "Use Explore to generate a mermaid diagram of
   payment_service's dependencies, showing outgoing
   and incoming dependencies to 2 levels of depth"

# Expected output:
# ```mermaid
# graph LR
#     checkout --> PaymentService
#     orders --> PaymentService
#     order_service --> PaymentService
#     recurring --> PaymentService
#     PaymentService --> Transaction
#     PaymentService --> User
#     PaymentService --> EmailService
#     PaymentService --> Currency
#     PaymentService --> Stripe
# ```

Warning signs in dependency-following

  • Circular dependencies: A depends on B, B depends on A → indicates high coupling
  • Excessive fan-out: a module that imports 15+ other modules → possible god object
  • Excessive fan-in: a module that 20+ others depend on → a change here affects everything
  • Hidden dependencies: communication via events, globals, or side effects

Pattern 3: Feature-Tracing (End-to-End Tracing)

When to use it

Use feature-tracing when you need to understand how a specific feature works end-to-end. It's the most valuable pattern for understanding business logic.

Analogy

It's like following a ball in a game: it starts at one point (user request) and you follow it through each player (function/service) until it reaches the goal (response).

Sequence of steps

Entry point (request/event/CLI command)
    ↓
Middleware / interceptors
    ↓
Route handler / controller
    ↓
Service layer (business logic)
    ↓
Repository / data access
    ↓
Database / external service
    ↓
Response construction
    ↓
Return to the user

Implementation with Explore

Complete trace — Login flow:

> "Use Explore to trace the complete login flow
   in this project. Start from the POST /login endpoint
   and follow every function that's called up to the final
   response. For each step, state: file, function, and what
   it does."

# Expected output:
#
# 1. src/api/routes/auth.py:login()
#    → Receives POST /login with {email, password}
#    → Validates the format with LoginRequest (pydantic)
#
# 2. src/services/auth_service.py:authenticate()
#    → Looks up the user by email
#    → Verifies the password with bcrypt
#    → If it fails: raise AuthError("Invalid credentials")
#
# 3. src/models/user.py:User.get_by_email()
#    → Query: SELECT * FROM users WHERE email = ?
#    → Returns a User object or None
#
# 4. src/utils/security.py:verify_password()
#    → bcrypt.checkpw(password, hashed)
#    → Returns bool
#
# 5. src/services/auth_service.py:create_tokens()
#    → Generates a JWT access token (15 min)
#    → Generates a JWT refresh token (7 days)
#    → Saves the refresh token in the DB
#
# 6. src/api/routes/auth.py:login()
#    → Returns {access_token, refresh_token, user_info}
#    → HTTP 200

Data trace — How the input is transformed:

> "Use Explore to trace how the data is transformed
   in a create-order request. From the JSON the client
   sends to what's saved in the database."

# Expected output:
#
# Client input:
#   {"product_id": 123, "quantity": 2, "coupon": "SAVE10"}
#
# Transformation 1 (route handler):
#   → Validation with Pydantic → OrderCreateRequest object
#   → user_id is added from the JWT token
#
# Transformation 2 (order_service):
#   → The product is looked up → the price is computed
#   → The coupon is applied → adjusted price
#   → Tax is computed → final price
#
# Transformation 3 (payment_service):
#   → A charge is created in Stripe
#   → A transaction_id is obtained
#
# What's saved in the DB:
#   Order(user_id=456, product_id=123, quantity=2,
#         subtotal=49.98, discount=5.00, tax=4.05,
#         total=49.03, stripe_tx="ch_abc123",
#         status="confirmed", created_at=...)

Feature-tracing in depth

Error tracing:

> "Use Explore to trace what happens when the payment
   fails during order creation. How does the error
   propagate from Stripe to the user?"

# Expected output: the error handling chain from
# stripe.CardError → PaymentError → order not created
# → HTTP 402 with a message to the user

Side effect tracing:

> "Use Explore to find all the side effects
   of creating an order successfully. What else happens
   besides saving the order in the DB?"

# Expected output:
# 1. A confirmation email is sent (email_service)
# 2. Inventory is updated (inventory_service)
# 3. An OrderCreated event is published (event_bus)
# 4. Analytics is updated (analytics_service)
# 5. An entry is created in the audit log

Combining Patterns

The complete investigation workflow

The three patterns complement each other. In a real investigation you combine them:

# 1. Top-Down: understand the general structure
> "The project structure and main components"

# 2. Feature-Tracing: understand a critical flow
> "Trace the checkout flow end-to-end"

# 3. Dependency-Following: understand the impact of changes
> "What depends on payment_service? If I change it,
   what breaks?"

When to use each pattern

QuestionPatternWhy
"How is this project organized?"Top-DownYou need the general structure
"How does login work?"Feature-TracingYou need the end-to-end flow
"What happens if I change UserModel?"Dependency-FollowingYou need the impact of changes
"What's the architecture?"Top-DownYou need layers and components
"How are payments processed?"Feature-TracingYou need the business flow
"What modules does the scheduler use?"Dependency-FollowingYou need the connections

The fundamental principle

Investigate before you modify. This principle repeats throughout the guide. The three patterns are investigation tools. Explore is the tool. The patterns are the strategy. Together they produce deep comprehension that informs refactoring decisions.


Connection with the Project

In the Module Project (capsule 05) you're going to use the three patterns to answer questions about a codebase:

  • Top-Down: "What's the project's general architecture?"
  • Feature-Tracing: "How does a login request flow from the endpoint to the DB?"
  • Dependency-Following: "What dependencies does the payments module have?"

The project evaluates whether you can choose the right pattern for each question and execute it efficiently with Explore.


Troubleshooting

Problem 1: I don't know which pattern to use

Cause: The question is ambiguous.

Solution: Classify the question:

  • Does it ask about structure? → Top-Down
  • Does it ask about a flow? → Feature-Tracing
  • Does it ask about connections? → Dependency-Following

Problem 2: Top-Down gets lost in details

Cause: You went down a level too quickly.

Solution: Keep level discipline. Don't go down to level 3 without having documented the complete level 2.

Problem 3: Feature-Tracing branches out too much

Cause: The feature has many side effects.

Solution: First trace the happy path (main flow without errors). Then trace error paths and side effects separately.

Problem 4: Dependency-Following finds circular dependencies

Cause: A coupled design of the codebase (it's not your fault).

Solution: Document it as a finding. Circular dependencies are an anti-pattern that's addressed in Module 3 (Architecture) and resolved in Module 4 (Refactoring).

Problem 5: Explore doesn't follow the pattern I asked for

Cause: The prompt doesn't specify the strategy clearly.

Solution: Be explicit about the pattern:

# Vague:
> "Analyze the payments module"

# Explicit:
> "Use a top-down approach to analyze the payments
   module. Start with the file structure,
   then describe the main components, and
   finally detail the key functions of
   payment_service.py"

Exercises

Exercise 1: Classify questions by pattern (Easy)

Classify each question with the right pattern (Top-Down, Dependency-Following, or Feature-Tracing):

  1. "How many modules does this project have and what does each one do?"
  2. "What happens when a user uploads an image?"
  3. "What breaks if I remove the Logger class?"
  4. "How is the tests directory organized?"
  5. "How is a Stripe webhook processed?"
  6. "Who uses the calculate_tax() function?"
See solution
  1. Top-Down — asks about the general structure
  2. Feature-Tracing — asks about the end-to-end flow of a feature
  3. Dependency-Following — asks about the impact of a change (dependents)
  4. Top-Down — asks about the structure of a directory
  5. Feature-Tracing — asks about the flow of an event
  6. Dependency-Following — asks about who depends on a function

Rule: structure = top-down, flow = feature-tracing, impact = dependency-following

Exercise 2: Design top-down prompts (Easy)

Write a sequence of 4 top-down prompts to investigate the src/services/ directory of a project, going from level 1 (overview) to level 4 (specific function):

See solution
# Level 1: Overview
> "Use Explore to list all the files in src/services/
   and describe the purpose of each service in one sentence"

# Level 2: Component
> "Use Explore to analyze src/services/order_service.py.
   What public methods does it expose and what's the responsibility
   of each one?"

# Level 3: Method
> "Use Explore to detail the create_order() method of
   OrderService. What steps does it execute, what does it validate, and what
   external services does it call?"

# Level 4: Implementation
> "Use Explore to analyze the error handling within
   create_order(). What exceptions can it raise and
   how are they handled?"

Key: each level uses the result of the previous one to decide where to dig deeper.

Exercise 3: Complete Feature-Tracing (Medium)

Write the Explore prompts needed to trace the complete "user registers" flow in a typical web app. Include the happy path and at least 2 error paths.

See solution
# Happy Path:
> "Use Explore to trace the complete user registration
   flow. Start from the POST /register endpoint and
   follow every function up to the response. Include: file,
   function, what data it receives, what data it produces."

# Error Path 1 — Duplicate email:
> "Use Explore to trace what happens when a user
   tries to register with an email that already exists. Where
   is it detected, what error is raised, and what HTTP response
   does the user receive?"

# Error Path 2 — Failed validation:
> "Use Explore to trace what happens when the registration
   request has invalid data (short password,
   malformed email). In which layer is it validated and how
   is the error communicated?"

# Side Effects:
> "Use Explore to find all the side effects
   of a successful registration. Is a verification email sent?
   Is any additional record created? Is any external
   service notified?"

Why 4 prompts: the happy path gives you the normal flow, error paths show you robustness, side effects show you the complete impact.

Exercise 4: Dependency map of a module (Medium)

Choose a module from a project you know (or use an open-source project). Write the prompts to build a complete dependency map using Explore:

See solution
# Step 1: Outgoing dependencies
> "Use Explore to list all the dependencies of
   [module]. Separate into: external dependencies (pip packages)
   and internal dependencies (other project modules).
   For each one, state what is imported/used."

# Step 2: Incoming dependents
> "Use Explore to find all the project files
   that import or use [module]. State what
   function or class they use from [module]."

# Step 3: Transitive dependencies (1 more level)
> "For the 3 most important internal dependencies
   of [module], what do they in turn depend on?"

# Step 4: Generate a diagram
> "Generate a mermaid diagram showing [module] at
   the center, its outgoing dependencies on the right,
   and its incoming dependents on the left."

# Step 5: Risk analysis
> "Based on the dependency map, which change
   to [module] would have the greatest impact on the rest
   of the project? And which would have the least impact?"

Value: this exercise produces a real artifact (dependency map) you can use to plan refactoring.

Exercise 5: Combined investigation (Hard)

A colleague asks you to investigate why the /api/reports/generate endpoint takes 30 seconds. Design a 6-step investigation plan using the 3 patterns:

See solution
# 1. Top-Down: understand the reports module
> "Use Explore to describe the structure of the reports
   module. What files make it up, what services
   does it use, and how is it organized?"

# 2. Feature-Tracing: trace the endpoint's flow
> "Use Explore to trace the complete flow of
   GET /api/reports/generate. From the request to
   the response, what functions run and in what
   order?"

# 3. Feature-Tracing: identify bottlenecks
> "From the previous flow, which steps involve I/O
   (database queries, API calls, file system)? Those
   are the candidates for causing the 30 seconds."

# 4. Dependency-Following: analyze heavy dependencies
> "Use Explore to analyze the dependencies of the
   report generator. Does it use any external service, a complex
   query, or intensive processing?"

# 5. Feature-Tracing: look for N+1 queries
> "Use Explore to analyze the database queries in
   the generate_report() flow. Is there any that runs
   in a loop (N+1 problem)?"

# 6. Top-Down: look for existing solutions
> "Use Explore to check whether the project has
   any cache system, background jobs, or optimized
   queries that the report generator isn't using."

Pattern: Top-Down (context) → Feature-Tracing (flow + bottleneck) → Dependency-Following (causes) → Top-Down (existing solutions).


Summary

In this capsule you learned:

  • Three exploration patterns cover 90% of investigations: top-down, dependency-following, and feature-tracing
  • Top-Down goes from the general to the specific: structure → components → modules → functions
  • Dependency-Following maps connections: what does it depend on? who depends on this?
  • Feature-Tracing traces flows end-to-end: request → processing → response
  • Each pattern has a purpose: structure (top-down), impact (dependencies), flows (tracing)
  • Combining patterns produces complete and efficient investigations
  • Investigate before you modify is the principle all the patterns reinforce

Next capsule: Module Project — Codebase Exploration with Explore. You're going to put the three patterns into practice by answering specific questions about a real codebase.


Additional Resources

  1. Explore Subagent - Claude Code Docs - Official documentation of the Explore subagent
  2. Code Reading: The Open Source Perspective - A classic book on systematic code reading
  3. Working Effectively with Legacy Code - Michael Feathers - The reference book on working with existing code
  4. Dependency Analysis Tools - Python - pydeps for generating dependency graphs in Python
  5. Architecture Decision Records - Documenting the architectural decisions you find
  6. The Art of Code Review - Google Engineering - Review practices that complement exploration

Module 2, Capsule 04 — Refactoring & Legacy Code with Claude Code Guide