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 Case | Recommended Method | Why |
---|---|---|
New AI application | Agent Wrapper/Decorator | Easiest to implement, comprehensive coverage |
Legacy codebase | Node Function Tracing | Integrates without refactoring |
Specific functions | Node Wrapper/Decorator | Function-level control with automation |
Complex error handling | Manual Agent Tracing | Full control over error scenarios |
High-performance requirements | Node Function Tracing | Conditional and optimized tracing |
Third-party integrations | Node Function Tracing | Works with any library or service |
Implementation Strategies
🚀 Getting Started (New Projects)
- Start with Agent Wrapper/Decorator for main workflows
- Add Node Wrapper/Decorator for key functions
- Use Node Function Tracing for special cases
- Consider Manual Agent Tracing for complex scenarios
🔄 Gradual Adoption (Existing Projects)
- Begin with Node Function Tracing for minimal changes
- Gradually add Node Wrapper/Decorator to key functions
- Upgrade to Agent Wrapper/Decorator for complete workflows
- Implement Manual Agent Tracing where needed
Method Comparison
Feature | Agent Wrapper | Manual Agent | Node Wrapper | Node 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:
- Learn about Agent Wrapper/Decorator for quick implementation
- Explore Manual Agent Tracing for maximum control
- Check Node Wrapper/Decorator for function-level tracing
- Discover Node Function Tracing for flexible integration