How to Debug Issues in DeepTutor: A Complete Troubleshooting Guide

Enable verbose logging via load_logging_config(), inspect the UnifiedContext before calling the orchestrator, and monitor StreamBus events to trace every execution step from input to output.

DeepTutor is a sophisticated AI tutoring framework built around a single-turn orchestrator that coordinates capabilities and tools through asynchronous event streams. When issues arise in the HKUDS/DeepTutor codebase, debugging requires understanding how the Orchestrator, StreamBus, and EventBus interact to process requests. This guide walks through the exact source code locations and debugging patterns you need to isolate failures in capabilities, tool execution, or context handling.

Understanding DeepTutor's Debugging Architecture

DeepTutor processes each request through three interconnected layers that emit traceable events. Understanding these components is essential before applying specific debugging techniques.

  • Orchestrator Layer: The ChatOrchestrator class in deeptutor/runtime/orchestrator.py (lines 32-49) receives a UnifiedContext, looks up the requested capability, initializes a StreamBus, and publishes completion events. This is the central entry point for every tutoring interaction.

  • Registry Layer: The CapabilityRegistry (deeptutor/runtime/registry/capability_registry.py, lines 48-55) and ToolRegistry (deeptutor/runtime/registry/tool_registry.py, lines 41-52) maintain the catalog of available functions. These registries expose OpenAI function schemas and handle plugin discovery.

  • Event & Stream Infrastructure: The StreamBus (deeptutor/core/stream_bus.py, lines 39-48) manages per-turn asynchronous events including content, tool calls, and errors. The global EventBus (deeptutor/events/event_bus.py, lines 101-107) handles cross-module notifications like CAPABILITY_COMPLETE.

  • Context Object: The UnifiedContext defined in deeptutor/core/context.py (lines 26-58) carries all request data including session IDs, enabled tools, and knowledge bases through the entire stack.

  • Logging System: The LoggingConfig in deeptutor/logging/config.py (lines 71-79) controls global log levels across all modules including RAG components.

Step-by-Step DeepTutor Debugging Workflow

Follow this systematic approach to isolate issues in the DeepTutor pipeline. Each step targets a specific failure point in the request lifecycle.

  1. Enable Verbose Logging: Set the global log level to DEBUG using load_logging_config(). This function reads main.yaml and applies the level to every logger in the system, including RAG modules.

  2. Validate the UnifiedContext: Before invoking the orchestrator, inspect the UnifiedContext object. Missing session_id fields or empty enabled_tools lists are frequent causes of silent failures.

  3. Monitor the StreamBus: Iterate over the async generator returned by ChatOrchestrator.handle(). Each StreamEvent reveals execution stages, tool invocations, and error states in chronological order.

  4. Attach EventBus Listeners: Subscribe to EventType.CAPABILITY_COMPLETE events to capture completion metadata. This reveals which tools executed and whether uncaught exceptions occurred.

  5. Verify Registry Contents: Call list_capabilities() and list_tools() on the respective registries at startup. If expected capabilities like deep_solve are missing, check for import failures in builtin_capability_classes.

  6. Check Error Event Paths: The orchestrator catches capability exceptions and emits ERROR stream events via bus.error. Search logs and stream output for these events to pinpoint failure locations.

Practical Code Examples for Debugging DeepTutor

These runnable examples demonstrate how to instrument the DeepTutor runtime for debugging.

Running a Single Turn with Debug Output

This example enables DEBUG logging and prints every StreamEvent to trace the execution flow:

import asyncio
import logging

from deeptutor.runtime.orchestrator import ChatOrchestrator
from deeptutor.core.context import UnifiedContext
from deeptutor.logging.config import load_logging_config

# 1️⃣ Enable DEBUG logging for the whole app

cfg = load_logging_config()
logging.basicConfig(level=cfg.level)

async def debug_turn(message: str, tools: list[str] | None = None):
    ctx = UnifiedContext(
        user_message=message,
        enabled_tools=tools,
        # any other fields you care about …

    )
    orchestrator = ChatOrchestrator()
    async for ev in orchestrator.handle(ctx):
        # StreamBus events arrive in order – print them for live debugging

        print(f"[{ev.type}] {ev.source}: {getattr(ev, 'content', '')}")

# Example usage

asyncio.run(debug_turn("Explain the Fourier transform", tools=["rag", "web_search"]))

Attaching EventBus Listeners for Capability Completion

This pattern captures high-level completion events regardless of how many stream events were emitted:

import asyncio
from deeptutor.events.event_bus import EventType, get_event_bus, Event

async def on_capability_complete(event: Event):
    print("\n--- Capability completed ---")
    print(f"Capability: {event.metadata.get('capability')}")
    print(f"Session: {event.metadata.get('session_id')}")
    print(f"Turn: {event.metadata.get('turn_id')}")

async def main():
    bus = get_event_bus()
    bus.subscribe(EventType.CAPABILITY_COMPLETE, on_capability_complete)

    # Run a turn (reuse the debug_turn from above)

    await debug_turn("What is the derivative of sin(x)?")

    # Give the bus a moment to process the async handler

    await asyncio.sleep(0.1)

asyncio.run(main())

Verifying Registry Contents at Startup

Check that your capabilities and tools are properly registered before processing requests:

from deeptutor.runtime.registry.capability_registry import get_capability_registry
from deeptutor.runtime.registry.tool_registry import get_tool_registry

cap_registry = get_capability_registry()
tool_registry = get_tool_registry()

print("Capabilities:", cap_registry.list_capabilities())
print("Tools:", tool_registry.list_tools())

Key Source Files for DeepTutor Debugging

When tracing issues, examine these specific files in the HKUDS/DeepTutor repository:

File Role
deeptutor/runtime/orchestrator.py Central turn orchestrator that routes context to capabilities and emits stream events
deeptutor/core/context.py Definition of UnifiedContext carrying all request data
deeptutor/runtime/registry/capability_registry.py Loads built-in and plugin capabilities
deeptutor/runtime/registry/tool_registry.py Loads tools and resolves OpenAI schemas
deeptutor/core/stream_bus.py Async fan-out bus for per-turn events
deeptutor/events/event_bus.py Global event bus for cross-module notifications
deeptutor/logging/config.py Global logging configuration loader

Summary

  • Enable DEBUG logging via load_logging_config() in deeptutor/logging/config.py to capture system-wide trace information.
  • Inspect UnifiedContext before orchestration to catch missing session IDs or tool configurations.
  • Monitor StreamBus events by iterating over ChatOrchestrator.handle() to observe real-time execution flow.
  • Validate registries using list_capabilities() and list_tools() to ensure all components are registered.
  • Capture EventBus notifications for completion and error events that indicate turn-level success or failure.

Frequently Asked Questions

How do I enable DEBUG logging in DeepTutor?

Call load_logging_config() from deeptutor/logging/config.py and set the level to DEBUG in your main.yaml configuration file. This applies the log level globally across all modules including RAG components, allowing you to trace execution through the orchestrator and tool layers.

What is the UnifiedContext and why does it cause silent failures?

The UnifiedContext is the data object defined in deeptutor/core/context.py that carries session state, user messages, and enabled tools through the entire stack. Silent failures often occur when required fields like session_id are missing or when enabled_tools is empty, causing the orchestrator to route requests to default capabilities without the intended tool support.

How can I trace tool execution in DeepTutor?

Iterate over the async generator returned by ChatOrchestrator.handle() and inspect the StreamEvent objects. Tool calls appear as TOOL_CALL events and results as TOOL_RESULT events. Alternatively, subscribe to the EventBus to capture CAPABILITY_COMPLETE events that include metadata about which tools were invoked during the turn.

Where does DeepTutor log errors from capabilities?

The orchestrator catches exceptions from capabilities and emits them as ERROR events through the StreamBus via bus.error(). These events appear in your stream iteration output and are also available through the logging system if DEBUG level is enabled, allowing you to pinpoint the exact line where failures occur in deeptutor/runtime/orchestrator.py.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →