Skip to Content
🎉 Welcome to handit.ai Documentation!
TracingTracing GuideOverview

Tracing Guide

Master comprehensive AI agent observability. This guide covers all the different methods for implementing tracing in your AI applications, helping you choose the right approach for your specific needs.

Whether you’re building a new AI agent or adding observability to an existing system, this guide will help you implement the most effective tracing strategy.

Each tracing method serves different purposes. You can combine multiple approaches in the same application for maximum observability.

Tracing Methods Overview

Agent-Level Tracing

For complete workflows and end-to-end processes:

Agent Wrapper/Decorator - Most convenient approach that automatically traces entire agent workflows with minimal code changes. Perfect for main entry points, API endpoints, and complete workflows.

Manual Agent Tracing - Maximum control approach that gives you complete control over what gets tracked and when. Ideal for complex error handling, custom workflows, and existing monitoring integration.

Function-Level Tracing

For individual functions and components:

Node Wrapper/Decorator - Balanced approach that provides automatic tracing with function-level granularity. Great for LLM calls, tool executions, and data processing steps.

Node Function Tracing - Maximum flexibility approach that offers programmatic control over function tracing. Perfect for dynamic tracing, third-party libraries, and conditional tracking.

Choosing the Right Method

Decision Matrix

Use CaseRecommended MethodWhy
New AI applicationAgent Wrapper/DecoratorEasiest to implement, comprehensive coverage
Legacy codebaseNode Function TracingIntegrates without refactoring
Specific functionsNode Wrapper/DecoratorFunction-level control with automation
Complex error handlingManual Agent TracingFull control over error scenarios
High-performance requirementsNode Function TracingConditional and optimized tracing
Third-party integrationsNode Function TracingWorks with any library or service

Implementation Strategies

🚀 Getting Started (New Projects)

  1. Start with Agent Wrapper/Decorator for main workflows
  2. Add Node Wrapper/Decorator for key functions
  3. Use Node Function Tracing for special cases
  4. Consider Manual Agent Tracing for complex scenarios

🔄 Gradual Adoption (Existing Projects)

  1. Begin with Node Function Tracing for minimal changes
  2. Gradually add Node Wrapper/Decorator to key functions
  3. Upgrade to Agent Wrapper/Decorator for complete workflows
  4. Implement Manual Agent Tracing where needed

Method Comparison

FeatureAgent WrapperManual AgentNode WrapperNode Function
Ease of Use⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Flexibility⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Performance⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Error Handling⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Legacy Integration⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

Real-World Examples

E-commerce AI Assistant

/** * E-commerce AI Assistant example * Demonstrates the use of basic Handit.ai tracing methods: * - startTracing: Initiates a new trace session * - trackNode: Records individual operations * - endTracing: Completes the trace session */ async function processOrder(orderData) { // Initialize a new trace session and get execution ID // This ID will be used to link all operations in this workflow const tracingResponse = await startTracing({ agentName: 'order_processor' // Unique identifier for this agent }); const executionId = tracingResponse.executionId; try { // Track order validation step const validation = await validateOrder(orderData); await trackNode({ input: orderData, // Input data for this example output: validation, // Result of the operation nodeName: 'order_validation', // Unique identifier for this operation agentName: 'order_processor', // Must match the agent name from startTracing nodeType: 'tool', // Type of operation (tool, llm, etc.) executionId // Links this operation to the trace session }); // Track payment processing step const payment = await processPayment(orderData.payment); await trackNode({ input: orderData.payment, output: payment, nodeName: 'payment_processing', agentName: 'order_processor', nodeType: 'tool', executionId }); // Track confirmation generation using LLM const confirmation = await generateConfirmation(orderData, payment); await trackNode({ input: { order: orderData, payment }, output: confirmation, nodeName: 'confirmation_generation', agentName: 'order_processor', nodeType: 'llm', // Indicates this is an LLM operation executionId }); return confirmation; } catch (error) { // Track any errors that occur during processing await trackNode({ input: orderData, output: { error: error.message }, nodeName: 'error_handling', agentName: 'order_processor', nodeType: 'tool', executionId }); throw error; } finally { // Always end the trace session to ensure proper cleanup // This is crucial for maintaining accurate trace data await endTracing({ executionId, agentName: 'order_processor' }); } }

Data Science Pipeline

""" Data Science Pipeline example Demonstrates the use of basic Handit.ai tracing methods: - start_tracing: Initiates a new trace session - track_node: Records individual operations - end_tracing: Completes the trace session """ async def process_dataset(dataset_path): # Initialize a new trace session and get execution ID # This ID will be used to link all operations in this workflow tracing_response = tracker.start_tracing( agent_name="data_processor" # Unique identifier for this agent ) execution_id = tracing_response.get("executionId") try: # Track data loading step data = await load_data(dataset_path) tracker.track_node( input={"path": dataset_path}, # Input data for this example output={"records": len(data)}, # Result of the operation node_name="data_loading", # Unique identifier for this operation agent_name="data_processor", # Must match the agent name from start_tracing node_type="tool", # Type of operation (tool, llm, etc.) execution_id=execution_id # Links this operation to the trace session ) # Track data cleaning step cleaned_data = await clean_data(data) tracker.track_node( input={"records": len(data)}, output={"cleaned_records": len(cleaned_data)}, node_name="data_cleaning", agent_name="data_processor", node_type="tool", execution_id=execution_id ) # Track data analysis step analysis = await analyze_data(cleaned_data) tracker.track_node( input={"records": len(cleaned_data)}, output=analysis, node_name="data_analysis", agent_name="data_processor", node_type="tool", execution_id=execution_id ) return analysis except Exception as e: # Track any errors that occur during processing tracker.track_node( input={"path": dataset_path}, output={"error": str(e)}, node_name="error_handling", agent_name="data_processor", node_type="tool", execution_id=execution_id ) raise finally: # Always end the trace session to ensure proper cleanup # This is crucial for maintaining accurate trace data tracker.end_tracing( execution_id=execution_id, agent_name="data_processor" )

Best Practices

Combining Methods

Recommended Pattern: Use Agent Wrappers for main workflows, Node Wrappers for key functions, and Node Function tracing for special cases.

Hierarchical Tracing - Start broad with agent wrappers, then add specific function tracing for detailed insights

Performance Monitoring - Use conditional tracing to avoid overhead in production environments

Error Boundaries - Implement proper error handling at each tracing level to ensure reliability

Context Propagation - Ensure tracing context flows through all methods for complete correlation

Common Implementation Patterns

MVP Approach - Start with Agent Wrappers for quick implementation and immediate value

Enterprise Pattern - Combine all methods for comprehensive monitoring and observability

Legacy Integration - Use Node Function tracing to gradually add observability without major refactoring

High-Performance - Use conditional tracing with smart sampling for performance-critical applications

Next Steps

Ready to implement tracing? Choose your approach:

Last updated on