xray.trace()
Visual execution tracing for ConnectOnion agents. See exactly what happened during agent execution with timing, inputs, outputs, and errors.
Key Features
Visual Flow
See all tool calls in sequence
Performance
Execution timing for each step
Smart Display
Intelligent data truncation
Error Tracking
Clear error display and details
Progressive Examples
Learn xray.trace() from simple to advanced with these progressive examples. Each builds on the previous concepts.
1
1. Simple Single Tool
Minimal example with one tool call
Python Code
1from connectonion import Agent
2from connectonion.decorators import xray
3
4@xray
5def greet(name: str) -> str:
6 """Simple greeting function."""
7 return f"Hello, {name}!"
8
9# Create agent
10agent = Agent("greeter", tools=[greet])
11result = agent.input("Say hello to Alice")
12
13# View execution trace
14xray.trace(agent)
Trace Output
Task: "Say hello to Alice"
[1] • 12ms greet(name="Alice")
IN → name: "Alice"
OUT ← "Hello, Alice!"
Total: 12ms • 1 step • 1 iteration
2
2. Multiple Tool Chain
Agent uses multiple tools in sequence
Python Code
1from connectonion import Agent
2from connectonion.decorators import xray
3
4@xray
5def analyze_text(text: str) -> dict:
6 """Analyze text and return metrics."""
7 return {
8 'word_count': len(text.split()),
9 'char_count': len(text),
10 'sentiment': 'neutral'
11 }
12
13@xray
14def generate_summary(text: str, max_words: int = 10) -> str:
15 """Generate a summary of the text."""
16 words = text.split()[:max_words]
17 return f"Summary: {' '.join(words)}..."
18
19# Create and run agent
20agent = Agent(
21 name="text_processor",
22 tools=[analyze_text, generate_summary]
23)
24
25result = agent.input("Analyze this sample text and create a summary")
26
27# View the execution trace
28xray.trace(agent)
Trace Output
Task: "Analyze this sample text and create a summary"
[1] • 45ms analyze_text(text="Analyze this sample text and create a summary")
IN → text: "Analyze this sample text and create a summary"
OUT ← {'word_count': 11, 'char_count': 51, 'sentiment': 'neutral'}
[2] • 23ms generate_summary(text="Analyze this sample text and create a summary", max_words=10)
IN → text: "Analyze this sample text and create a summary"
IN → max_words: 10
OUT ← "Summary: Analyze this sample text and create..."
Total: 68ms • 2 steps • 1 iteration
3
3. Error Handling & Recovery
How trace displays errors and agent recovery
Python Code
1from connectonion import Agent
2from connectonion.decorators import xray
3
4@xray
5def validate_email(email: str) -> dict:
6 """Validate email format."""
7 if '@' not in email:
8 raise ValueError("Invalid email: missing @ symbol")
9 parts = email.split('@')
10 if len(parts) != 2 or not parts[0] or not parts[1]:
11 raise ValueError("Invalid email format")
12 return {"email": email, "valid": True}
13
14@xray
15def send_notification(email_data: dict) -> str:
16 """Send notification to validated email."""
17 if not email_data.get("valid"):
18 return "❌ Cannot send to invalid email"
19 return f"✅ Notification sent to {email_data['email']}"
20
21@xray
22def fallback_contact(message: str) -> str:
23 """Fallback contact method when email fails."""
24 return f"📞 Fallback: {message} (via phone/SMS)"
25
26# Create agent
27agent = Agent(
28 name="notification_agent",
29 tools=[validate_email, send_notification, fallback_contact]
30)
31
32result = agent.input("Send notification to user at bad-email-format")
33
34# View trace showing error handling
35xray.trace(agent)
Trace Output
Task: "Send notification to user at bad-email-format"
[1] • ERROR validate_email(email="bad-email-format")
IN → email: "bad-email-format"
ERR ✗ ValueError: Invalid email: missing @ symbol
[2] • 18ms fallback_contact(message="Send notification to user at bad-email-format")
IN → message: "Send notification to user at bad-email-format"
OUT ← "📞 Fallback: Send notification to user at bad-email-format (via phone/SMS)"
Total: 18ms • 2 steps • 1 iteration • 1 error
4
4. Performance Bottleneck Analysis
Identify slow operations and optimization opportunities
Python Code
1from connectonion import Agent
2from connectonion.decorators import xray
3import time
4import random
5
6@xray
7def fetch_user_data(user_id: str) -> dict:
8 """Fast database lookup."""
9 time.sleep(0.05) # 50ms DB query
10 return {"user_id": user_id, "name": "John Doe", "tier": "premium"}
11
12@xray
13def complex_calculation(data: dict) -> dict:
14 """CPU intensive calculation."""
15 time.sleep(1.2) # 1.2s processing
16 score = random.randint(750, 850)
17 return {"score": score, "calculation_time": "1.2s", "tier": data["tier"]}
18
19@xray
20def external_api_call(user_data: dict, score_data: dict) -> dict:
21 """Slow external API call."""
22 time.sleep(0.8) # 800ms network call
23 return {
24 "recommendation": f"Premium package for {user_data['name']}",
25 "api_response_time": "800ms",
26 "confidence": 0.95
27 }
28
29@xray
30def format_response(user_data: dict, score_data: dict, recommendation: dict) -> str:
31 """Fast formatting step."""
32 time.sleep(0.01) # 10ms formatting
33 return f"""
34 🎯 Analysis Complete:
35 User: {user_data['name']} (ID: {user_data['user_id']})
36 Score: {score_data['score']} ({score_data['tier']} tier)
37 Recommendation: {recommendation['recommendation']}
38 Confidence: {recommendation['confidence']*100:.0f}%
39 """
40
41# Create agent
42agent = Agent(
43 name="analytics_engine",
44 tools=[fetch_user_data, complex_calculation, external_api_call, format_response]
45)
46
47result = agent.input("Generate analytics report for user ID 12345")
48
49# Analyze performance bottlenecks
50xray.trace(agent)
Trace Output
Task: "Generate analytics report for user ID 12345"
[1] • 52ms fetch_user_data(user_id="12345")
IN → user_id: "12345"
OUT ← {"user_id": "12345", "name": "John Doe", "tier": "premium"}
[2] • 1.2s complex_calculation(data={...}) ⚠️ SLOW
IN → data: {"user_id": "12345", "name": "John Doe", "tier": "premium"}
OUT ← {"score": 823, "calculation_time": "1.2s", "tier": "premium"}
[3] • 803ms external_api_call(user_data={...}, score_data={...}) ⚠️ SLOW
IN → user_data: {"user_id": "12345", "name": "John Doe", "tier": "premium"}
IN → score_data: {"score": 823, "calculation_time": "1.2s", "tier": "premium"}
OUT ← {"recommendation": "Premium package for John Doe", "api_response_time": "800ms", "confidence": 0.95}
[4] • 11ms format_response(user_data={...}, score_data={...}, recommendation={...})
IN → user_data: {"user_id": "12345", "name": "John Doe", "tier": "premium"}
IN → score_data: {"score": 823, "calculation_time": "1.2s", "tier": "premium"}
IN → recommendation: {"recommendation": "Premium package for John Doe", ... (2 more)}
OUT ← "🎯 Analysis Complete:\nUser: John Doe (ID: 12345)\nScore: 823 (premium tier)..."
Total: 2.07s • 4 steps • 1 iteration
⚠️ ⚠️ Performance Issues Detected:
• Step 2: complex_calculation (1.2s) - Consider caching or async processing
• Step 3: external_api_call (803ms) - Implement timeout/retry logic
5
5. IDE Breakpoint Debugging
Advanced debugging with IDE breakpoints and live context inspection
Python Code
1from connectonion import Agent
2from connectonion.decorators import xray
3
4@xray
5def process_order(order_data: dict) -> dict:
6 """Process customer order with validation."""
7 # 🔴 SET BREAKPOINT HERE - Debug order validation
8 # In IDE debugger console:
9 # >>> xray.trace() # See current execution state
10 # >>> xray.agent.name # Current agent name
11 # >>> xray.task # Original user request
12 # >>> order_data # Inspect current parameters
13
14 if not order_data.get("items"):
15 return {"error": "No items in order", "status": "failed"}
16
17 # Calculate totals
18 total = sum(item.get("price", 0) * item.get("qty", 1)
19 for item in order_data["items"])
20
21 # 🔴 BREAKPOINT OPPORTUNITY - Check calculations
22 # >>> xray.trace() # Updated trace
23 # >>> total # Inspect calculated total
24
25 return {
26 "order_id": f"ORD-{hash(str(order_data)) % 10000:04d}",
27 "total": total,
28 "status": "validated",
29 "items_count": len(order_data["items"])
30 }
31
32@xray
33def apply_discounts(validated_order: dict) -> dict:
34 """Apply business rules and discounts."""
35 # 🔴 BREAKPOINT - Discount logic debugging
36 # >>> xray.trace() # See previous tool results
37 # >>> validated_order # Inspect order from previous step
38
39 if validated_order.get("error"):
40 return validated_order # Pass through errors
41
42 total = validated_order["total"]
43 discount = 0
44
45 # Business rules
46 if total > 100:
47 discount = total * 0.1 # 10% discount for orders > $100
48 if validated_order["items_count"] >= 5:
49 discount = max(discount, total * 0.15) # 15% for bulk orders
50
51 # 🔴 BREAKPOINT - Final calculations
52 # >>> discount # Check discount amount
53 # >>> xray.trace() # See full execution flow
54
55 final_total = total - discount
56
57 return {
58 **validated_order,
59 "original_total": total,
60 "discount": discount,
61 "final_total": final_total,
62 "discount_percent": (discount / total * 100) if total > 0 else 0
63 }
64
65@xray
66def generate_invoice(order: dict) -> str:
67 """Generate final invoice."""
68 # 🔴 FINAL BREAKPOINT - Invoice generation
69 # >>> xray.trace() # Complete execution trace
70 # >>> order # Final order data
71
72 if order.get("error"):
73 return f"❌ Order failed: {order['error']}"
74
75 return f"""
76 🧾 INVOICE #{order['order_id']}
77 ═══════════════════════════
78 Items: {order['items_count']}
79 Subtotal: ${order['original_total']:.2f}
80 Discount ({order['discount_percent']:.1f}%): -${order['discount']:.2f}
81 ───────────────────────────
82 TOTAL: ${order['final_total']:.2f}
83 """
84
85# Create agent for step-by-step debugging
86agent = Agent(
87 name="order_processor",
88 tools=[process_order, apply_discounts, generate_invoice]
89)
90
91# Complex order to debug
92order_data = {
93 "customer": "Alice Smith",
94 "items": [
95 {"name": "Laptop", "price": 899.99, "qty": 1},
96 {"name": "Mouse", "price": 29.99, "qty": 2},
97 {"name": "Keyboard", "price": 79.99, "qty": 1},
98 {"name": "Monitor", "price": 299.99, "qty": 2},
99 {"name": "Cables", "price": 15.99, "qty": 3}
100 ]
101}
102
103# Run with IDE breakpoints set at marked locations
104result = agent.input(f"Process this order: {order_data}")
105
106# Final comprehensive trace
107xray.trace(agent)
Trace Output
💻 IDE Debugging Session - Order Processing:
🔴 Breakpoint 1: process_order() - Line 8
>>> xray.trace()
Task: "Process this order: {'customer': 'Alice Smith', 'items': [...]}"
[Starting] • process_order(order_data={...})
IN → order_data: {"customer": "Alice Smith", "items": [...] (5 items)}
Context: agent='order_processor', iteration=1
Variables: order_data={'customer': 'Alice Smith', 'items': [5 items]}
🔴 Breakpoint 2: process_order() - Line 20
>>> total
1385.93
>>> xray.trace()
[1] • process_order(order_data={...}) [IN PROGRESS]
IN → order_data: {"customer": "Alice Smith", "items": [...] (5 items)}
Progress: Calculated total=1385.93, processing...
🔴 Breakpoint 3: apply_discounts() - Line 35
>>> validated_order
{'order_id': 'ORD-3847', 'total': 1385.93, 'status': 'validated', 'items_count': 5}
>>> xray.trace()
[1] ✓ 156ms process_order(order_data={...})
IN → order_data: {"customer": "Alice Smith", "items": [...] (5 items)}
OUT ← {"order_id": "ORD-3847", "total": 1385.93, "status": "validated", "items_count": 5}
[2] • apply_discounts(validated_order={...}) [IN PROGRESS]
IN → validated_order: {"order_id": "ORD-3847", "total": 1385.93, ... (3 more)}
🔴 Breakpoint 4: apply_discounts() - Line 47
>>> discount
207.89
>>> xray.trace()
[1] ✓ 156ms process_order(order_data={...})
OUT ← {"order_id": "ORD-3847", "total": 1385.93, "status": "validated", "items_count": 5}
[2] • apply_discounts(validated_order={...}) [IN PROGRESS]
Progress: Applied 15% bulk discount (5+ items), discount=207.89
🔴 Breakpoint 5: generate_invoice() - Line 60
>>> order
{'order_id': 'ORD-3847', 'original_total': 1385.93, 'discount': 207.89, 'final_total': 1178.04, 'discount_percent': 15.0}
>>> xray.trace()
[1] ✓ 156ms process_order(order_data={...})
OUT ← {"order_id": "ORD-3847", "total": 1385.93, "status": "validated", "items_count": 5}
[2] ✓ 89ms apply_discounts(validated_order={...})
OUT ← {"order_id": "ORD-3847", "original_total": 1385.93, "discount": 207.89, "final_total": 1178.04, "discount_percent": 15.0, ... (4 more)}
[3] • generate_invoice(order={...}) [IN PROGRESS]
IN → order: {"order_id": "ORD-3847", "original_total": 1385.93, ... (6 more)}
🎯 Final Complete Trace:
[1] ✓ 156ms process_order(order_data={...})
IN → order_data: {"customer": "Alice Smith", "items": [...] (5 items)}
OUT ← {"order_id": "ORD-3847", "total": 1385.93, "status": "validated", "items_count": 5}
[2] ✓ 89ms apply_discounts(validated_order={...})
IN → validated_order: {"order_id": "ORD-3847", "total": 1385.93, ... (3 more)}
OUT ← {"order_id": "ORD-3847", "original_total": 1385.93, "discount": 207.89, "final_total": 1178.04, ... (6 more)}
[3] ✓ 23ms generate_invoice(order={...})
IN → order: {"order_id": "ORD-3847", "original_total": 1385.93, "discount": 207.89, ... (6 more)}
OUT ← "🧾 INVOICE #ORD-3847\n═══════════════════════════\nItems: 5\nSubtotal: $1385.93..."
Total: 268ms • 3 steps • 1 iteration
🧠 🧠 Debugging Insights:
• Order validation: 5 items totaling $1385.93
• Discount logic: 15% bulk discount applied (items >= 5)
• Final total: $1178.04 (saved $207.89)
• Use breakpoints to inspect variables at each step
• xray.trace() shows live execution state during debugging
Visual Format Reference
Status Indicators
•Successful execution
ERRORFailed execution
...Pending/in-progress
Data Flow
IN →Input parameters
OUT ←Return values
ERR ✗Error messages
Timing Display
0.03msSub-millisecond
45msTypical operations
2.3sLonger operations