@smythos/sre 1.7.40 → 1.7.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/index.js +49 -42
  2. package/dist/index.js.map +1 -1
  3. package/dist/types/Components/AgentPlugin.class.d.ts +1 -1
  4. package/dist/types/Components/RAG/DataSourceCleaner.class.d.ts +4 -4
  5. package/dist/types/Components/RAG/DataSourceComponent.class.d.ts +5 -1
  6. package/dist/types/config.d.ts +1 -0
  7. package/dist/types/helpers/Conversation.helper.d.ts +10 -13
  8. package/dist/types/helpers/TemplateString.helper.d.ts +1 -1
  9. package/dist/types/index.d.ts +1 -0
  10. package/dist/types/subsystems/IO/VectorDB.service/VectorDBConnector.d.ts +1 -0
  11. package/dist/types/subsystems/LLMManager/LLM.helper.d.ts +19 -0
  12. package/dist/types/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.d.ts +15 -10
  13. package/dist/types/types/LLM.types.d.ts +23 -0
  14. package/package.json +1 -1
  15. package/src/Components/AgentPlugin.class.ts +20 -3
  16. package/src/Components/Classifier.class.ts +79 -16
  17. package/src/Components/ForEach.class.ts +34 -6
  18. package/src/Components/GenAILLM.class.ts +54 -23
  19. package/src/Components/LLMAssistant.class.ts +56 -21
  20. package/src/Components/RAG/DataSourceCleaner.class.ts +13 -11
  21. package/src/Components/RAG/DataSourceComponent.class.ts +39 -13
  22. package/src/Components/RAG/DataSourceIndexer.class.ts +18 -12
  23. package/src/Components/RAG/DataSourceLookup.class.ts +14 -10
  24. package/src/Components/ScrapflyWebScrape.class.ts +7 -0
  25. package/src/config.ts +1 -0
  26. package/src/helpers/Conversation.helper.ts +112 -26
  27. package/src/helpers/TemplateString.helper.ts +6 -5
  28. package/src/index.ts +213 -212
  29. package/src/index.ts.bak +213 -212
  30. package/src/subsystems/IO/VectorDB.service/VectorDBConnector.ts +1 -0
  31. package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +11 -0
  32. package/src/subsystems/IO/VectorDB.service/embed/index.ts +9 -11
  33. package/src/subsystems/LLMManager/LLM.helper.ts +25 -0
  34. package/src/subsystems/LLMManager/LLM.service/LLMConnector.ts +1 -1
  35. package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +190 -146
  36. package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/utils.ts +1 -1
  37. package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.ts +402 -66
  38. package/src/types/LLM.types.ts +24 -0
  39. package/src/utils/data.utils.ts +6 -4
  40. package/src/Components/DataSourceIndexer.class.ts +0 -295
@@ -5,7 +5,7 @@ import { IAccessCandidate } from '@sre/types/ACL.types';
5
5
  import { TelemetryConnector } from '../../TelemetryConnector';
6
6
  import { AgentCallLog } from '@sre/types/AgentLogger.types';
7
7
 
8
- import { trace, context, SpanStatusCode, Tracer } from '@opentelemetry/api';
8
+ import { trace, context, SpanStatusCode, Tracer, propagation } from '@opentelemetry/api';
9
9
  import { Logger as OTelLogger, logs, SeverityNumber } from '@opentelemetry/api-logs';
10
10
  import { OTelContextRegistry } from './OTelContextRegistry';
11
11
  import { HookService, THook } from '@sre/Core/HookService';
@@ -62,6 +62,10 @@ export class OTel extends TelemetryConnector {
62
62
 
63
63
  constructor(protected _settings: OTelLogConfig) {
64
64
  super();
65
+ if (!_settings.endpoint) {
66
+ outputLogger.warn('OTel initialization skipped, endpoint is not set');
67
+ return;
68
+ }
65
69
 
66
70
  outputLogger.log(`Initializing Tracer ...`);
67
71
 
@@ -279,6 +283,7 @@ export class OTel extends TelemetryConnector {
279
283
  attributes: {
280
284
  'agent.id': hookContext.agentId,
281
285
  'conv.id': hookContext.processId,
286
+ 'team.id': hookContext.teamId,
282
287
  'llm.model': modelId || 'unknown',
283
288
  },
284
289
  },
@@ -312,6 +317,7 @@ export class OTel extends TelemetryConnector {
312
317
  attributes: {
313
318
  'agent.id': hookContext.agentId,
314
319
  'conv.id': hookContext.processId,
320
+ 'team.id': hookContext.teamId,
315
321
  'request.id': reqInfo.requestId,
316
322
  'llm.model': modelId || 'unknown',
317
323
  'metric.type': 'ttfb',
@@ -331,11 +337,21 @@ export class OTel extends TelemetryConnector {
331
337
  HookService.register(
332
338
  'Conversation.streamPrompt',
333
339
  async function (additionalContext, args) {
334
- const conversation: Conversation = this.instance;
335
- const processId = conversation.id;
340
+ const conversation: Conversation = this.instance; //this.instance.agentData.teamId // this.instance.agentData.parenparentTeamId //this.instance.agentData.planInfo.properties this.instance.agentData.planInfo.flags
341
+ const processId = conversation.storeId || conversation.id;
336
342
  const agentId = conversation.agentId;
337
343
  const message = typeof args === 'object' ? args?.message : args || null;
338
344
  const hookContext: any = this.context;
345
+ const teamId = conversation.agentData.teamId;
346
+ const orgTier = 'standard';
347
+ const orgSlot = this.instance.agentData?.planInfo?.flags ? `standard/${teamId}` : undefined;
348
+ const agentData = conversation.agentData || {};
349
+ const isDebugSession = agentData.debugSessionEnabled || false;
350
+ const isTestDomain = agentData.usingTestDomain || false;
351
+ const sessionId = processId;
352
+ const workflowId = agentData?.workflowReqId || agentData?.workflowID || agentData?.workflowId || undefined;
353
+ const logTags = agentData?.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
354
+
339
355
  if (message == null) {
340
356
  //this is a conversation step, will be handled by createRequestedHandler
341
357
 
@@ -354,14 +370,36 @@ export class OTel extends TelemetryConnector {
354
370
  'gen_ai.conversation.id': processId,
355
371
  'gen_ai.request.model': modelId || 'unknown',
356
372
  ////////////////////////////////
373
+ 'team.id': teamId,
374
+ 'org.tier': orgTier,
375
+ 'org.slot': orgSlot,
357
376
  'agent.id': agentId,
358
377
  'conv.id': processId,
359
378
  'llm.model': modelId || 'unknown',
379
+ 'agent.debug': isDebugSession,
380
+ 'agent.isTest': isTestDomain,
381
+ 'session.id': sessionId,
382
+ 'workflow.id': workflowId,
360
383
  },
361
384
  });
362
385
  hookContext.convSpan = convSpan;
363
386
  hookContext.agentId = agentId;
364
387
  hookContext.processId = processId;
388
+ hookContext.teamId = teamId;
389
+ hookContext.orgSlot = orgSlot;
390
+ hookContext.isDebugSession = isDebugSession;
391
+ hookContext.isTestDomain = isTestDomain;
392
+
393
+ // Inject trace context into conversation headers for distributed tracing
394
+ let headers = {};
395
+ const traceContext = trace.setSpan(context.active(), convSpan);
396
+ propagation.inject(traceContext, headers);
397
+ for (let [key, value] of Object.entries(headers)) {
398
+ conversation.headers[key] = value as string;
399
+ }
400
+ if (OTEL_DEBUG_LOGS) {
401
+ outputLogger.debug('Injected trace headers into conversation', { processId, headers });
402
+ }
365
403
 
366
404
  hookContext.dataHandler = createDataHandler(hookContext);
367
405
  conversation.on(TLLMEvent.Data, hookContext.dataHandler);
@@ -395,10 +433,19 @@ export class OTel extends TelemetryConnector {
395
433
  span_id: spanCtx.spanId,
396
434
  trace_flags: spanCtx.traceFlags,
397
435
 
436
+ /////
437
+ 'team.id': teamId,
438
+ 'org.slot': orgSlot,
439
+
398
440
  'agent.id': agentId,
399
441
  'conv.id': processId,
400
442
  'input.size': JSON.stringify(message || {}).length,
401
443
  'input.preview': message.substring(0, 2000),
444
+ 'agent.debug': isDebugSession,
445
+ 'agent.isTest': isTestDomain,
446
+ 'session.id': sessionId,
447
+ 'workflow.id': workflowId,
448
+ 'log.tags': logTags,
402
449
  },
403
450
  });
404
451
  });
@@ -410,10 +457,21 @@ export class OTel extends TelemetryConnector {
410
457
  'Conversation.streamPrompt',
411
458
  async function ({ result, args, error }) {
412
459
  const conversation: Conversation = this.instance;
413
- const processId = conversation.id;
460
+ const processId = conversation.storeId || conversation.id;
414
461
  const agentId = conversation.agentId;
415
462
  const message = typeof args?.[0] === 'object' ? args?.[0]?.message : args?.[0] || null;
416
463
  const hookContext: any = this.context;
464
+ const teamId = conversation.agentData.teamId;
465
+ const orgTier = 'standard';
466
+ const orgSlot = this.instance.agentData?.planInfo?.flags ? `standard/${teamId}` : undefined;
467
+
468
+ const isDebugSession = hookContext.isDebugSession || conversation.agentData?.debugSessionEnabled || false;
469
+ const isTestDomain = hookContext.isTestDomain || conversation.agentData?.usingTestDomain || false;
470
+ const agentData = conversation.agentData || {};
471
+ const sessionId = processId;
472
+ const workflowId = agentData?.workflowReqId || agentData?.workflowID || agentData?.workflowId || undefined;
473
+ const logTags = agentData?.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
474
+
417
475
  if (message == null) {
418
476
  return;
419
477
  }
@@ -424,10 +482,14 @@ export class OTel extends TelemetryConnector {
424
482
  const accessCandidate = AccessCandidate.agent(agentId);
425
483
  if (OTEL_DEBUG_LOGS) outputLogger.debug('Conversation.streamPrompt completed', { processId }, accessCandidate);
426
484
 
485
+ // Handle curLLMGenSpan with error awareness
427
486
  if (hookContext.curLLMGenSpan) {
487
+ if (error) {
488
+ hookContext.curLLMGenSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
489
+ }
428
490
  hookContext.curLLMGenSpan.addEvent('llm.gen.content', {
429
491
  'content.size': JSON.stringify(result || {}).length,
430
- 'content.preview': result.substring(0, 200),
492
+ 'content.preview': typeof result === 'string' ? result.substring(0, 200) : JSON.stringify(result || {}).substring(0, 200),
431
493
  });
432
494
  hookContext.curLLMGenSpan.end();
433
495
 
@@ -440,19 +502,69 @@ export class OTel extends TelemetryConnector {
440
502
 
441
503
  const spanCtx = convSpan.spanContext();
442
504
  const spanContext = trace.setSpan(context.active(), convSpan);
443
- context.with(spanContext, () => {
444
- logger.emit({
445
- severityNumber: SeverityNumber.INFO,
446
- severityText: 'INFO',
447
- body: `Conversation.streamPrompt completed: ${processId}`,
448
- attributes: {
449
- 'agent.id': agentId,
450
- 'conv.id': processId,
451
- 'output.size': JSON.stringify(result || {}).length,
452
- 'output.preview': result.substring(0, 2000),
453
- },
505
+
506
+ if (error) {
507
+ // Error handling for conversation span
508
+ convSpan.recordException(error);
509
+ convSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
510
+ convSpan.addEvent('conv.error', {
511
+ 'error.message': error.message,
454
512
  });
455
- });
513
+
514
+ // Emit ERROR log
515
+ context.with(spanContext, () => {
516
+ logger.emit({
517
+ severityNumber: SeverityNumber.ERROR,
518
+ severityText: 'ERROR',
519
+ body: `Conversation.streamPrompt failed: ${processId}`,
520
+ attributes: {
521
+ // Explicit trace correlation
522
+ trace_id: spanCtx.traceId,
523
+ span_id: spanCtx.spanId,
524
+ trace_flags: spanCtx.traceFlags,
525
+
526
+ 'agent.id': agentId,
527
+ 'conv.id': processId,
528
+ 'error.message': error.message,
529
+ 'error.stack': error.stack,
530
+ 'team.id': teamId,
531
+ 'org.tier': orgTier,
532
+ 'org.slot': orgSlot,
533
+ 'agent.debug': isDebugSession,
534
+ 'agent.isTest': isTestDomain,
535
+ 'session.id': sessionId,
536
+ 'workflow.id': workflowId,
537
+ 'log.tags': logTags,
538
+ },
539
+ });
540
+ });
541
+ } else {
542
+ // Success handling
543
+ convSpan.setStatus({ code: SpanStatusCode.OK });
544
+
545
+ context.with(spanContext, () => {
546
+ logger.emit({
547
+ severityNumber: SeverityNumber.INFO,
548
+ severityText: 'INFO',
549
+ body: `Conversation.streamPrompt completed: ${processId}`,
550
+ attributes: {
551
+ 'agent.id': agentId,
552
+ 'conv.id': processId,
553
+ 'output.size': JSON.stringify(result || {}).length,
554
+ 'output.preview':
555
+ typeof result === 'string' ? result.substring(0, 2000) : JSON.stringify(result || {}).substring(0, 2000),
556
+ 'team.id': teamId,
557
+ 'org.tier': orgTier,
558
+ 'org.slot': orgSlot,
559
+ 'agent.debug': isDebugSession,
560
+ 'agent.isTest': isTestDomain,
561
+ 'session.id': sessionId,
562
+ 'workflow.id': workflowId,
563
+ 'log.tags': logTags,
564
+ },
565
+ });
566
+ });
567
+ }
456
568
 
457
569
  convSpan.end();
458
570
 
@@ -471,11 +583,21 @@ export class OTel extends TelemetryConnector {
471
583
  const conversationId = agent.conversationId || agent.agentRequest?.header('X-CONVERSATION-ID');
472
584
  const processId = agentProcessId.split(':').shift();
473
585
 
586
+ const orgTier = 'standard';
587
+ const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
474
588
  const agentId = agent.id;
475
589
  const agentRequest = agent.agentRequest;
476
590
  const teamId = agent.teamId;
477
591
  const _hookContext: any = this.context;
478
592
 
593
+ const sessionId = agent.callerSessionId || undefined;
594
+ const workflowId = agent.agentRuntime?.workflowReqId || undefined;
595
+
596
+ const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
597
+ const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
598
+ const isTestDomain = agent.usingTestDomain || false;
599
+ const domain = agent.domain || undefined;
600
+
479
601
  const accessCandidate = AccessCandidate.agent(agentId);
480
602
  if (OTEL_DEBUG_LOGS) outputLogger.debug('SREAgent.process started', { processId, agentProcessId, endpointPath }, accessCandidate);
481
603
 
@@ -487,22 +609,50 @@ export class OTel extends TelemetryConnector {
487
609
  const input = { body, query, headers, processInput: agentInput };
488
610
 
489
611
  let convSpan;
490
- const ctx = OTelContextRegistry.get(agentId, processId) || OTelContextRegistry.get(agentId, conversationId);
612
+ let parentContext = context.active();
613
+
614
+ //try reading ctx from local registry (local execution)
615
+ let ctx = OTelContextRegistry.get(agentId, processId) || OTelContextRegistry.get(agentId, conversationId);
491
616
 
492
617
  if (ctx) {
493
618
  convSpan = ctx.rootSpan;
494
619
  _hookContext.otelSpan = convSpan;
620
+ parentContext = trace.setSpan(context.active(), convSpan);
621
+ } else {
622
+ // No local context found - try extracting from headers (remote execution)
623
+ const extractedContext = propagation.extract(context.active(), agentRequest.headers);
624
+ const extractedSpan = trace.getSpan(extractedContext);
625
+
626
+ if (extractedSpan) {
627
+ // Successfully extracted parent span from headers
628
+ parentContext = extractedContext;
629
+ if (OTEL_DEBUG_LOGS) {
630
+ outputLogger.debug('SREAgent.process extracted remote parent context from headers', {
631
+ processId,
632
+ traceId: extractedSpan.spanContext().traceId,
633
+ });
634
+ }
635
+ }
495
636
  }
637
+
496
638
  const agentSpan = tracer.startSpan(
497
639
  'Agent.Skill',
498
640
  {
499
641
  attributes: {
500
642
  'agent.id': agentId,
501
643
  'team.id': teamId,
644
+ 'conv.id': conversationId,
502
645
  'process.id': agentProcessId,
646
+ 'org.slot': orgSlot,
647
+ 'org.tier': orgTier,
648
+ 'session.id': sessionId,
649
+ 'workflow.id': workflowId,
650
+ 'agent.debug': isDebugSession,
651
+ 'agent.isTest': isTestDomain,
652
+ 'agent.domain': domain,
503
653
  },
504
654
  },
505
- convSpan ? trace.setSpan(context.active(), convSpan) : undefined
655
+ parentContext
506
656
  );
507
657
 
508
658
  // Add start event
@@ -528,12 +678,22 @@ export class OTel extends TelemetryConnector {
528
678
  trace_id: spanCtx.traceId,
529
679
  span_id: spanCtx.spanId,
530
680
  trace_flags: spanCtx.traceFlags,
531
- agentId,
532
- processId: agentProcessId,
681
+ 'agent.id': agentId,
682
+ 'process.id': agentProcessId,
533
683
  input: agentInput,
534
684
  body,
535
685
  query,
536
686
  headers,
687
+ 'team.id': teamId,
688
+ 'org.slot': orgSlot,
689
+ 'org.tier': orgTier,
690
+ 'conv.id': conversationId,
691
+ 'session.id': sessionId,
692
+ 'workflow.id': workflowId,
693
+ 'log.tags': logTags,
694
+ 'agent.debug': isDebugSession,
695
+ 'agent.isTest': isTestDomain,
696
+ 'agent.domain': domain,
537
697
  },
538
698
  } as any);
539
699
  });
@@ -546,8 +706,20 @@ export class OTel extends TelemetryConnector {
546
706
  async function ({ result, error }) {
547
707
  const agent = this.instance;
548
708
  const agentProcessId = agent.agentRuntime.processID; // nested process has a subID that needs to be removed
709
+ const conversationId = agent.conversationId || agent.agentRequest?.header('X-CONVERSATION-ID');
549
710
  const agentId = agent.id;
550
711
  const _hookContext: any = this.context;
712
+ const teamId = agent.teamId;
713
+ const orgTier = 'standard';
714
+ const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
715
+
716
+ const sessionId = agent.callerSessionId || undefined;
717
+ const workflowId = agent.agentRuntime?.workflowReqId || undefined;
718
+
719
+ const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
720
+ const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
721
+ const isTestDomain = agent.usingTestDomain || false;
722
+ const domain = agent.domain || undefined;
551
723
 
552
724
  const ctx = OTelContextRegistry.get(agentId, agentProcessId);
553
725
  if (!ctx) return;
@@ -558,12 +730,32 @@ export class OTel extends TelemetryConnector {
558
730
  const accessCandidate = AccessCandidate.agent(agentId);
559
731
  if (OTEL_DEBUG_LOGS) outputLogger.debug('SREAgent.process completed', { agentProcessId }, accessCandidate);
560
732
 
733
+ // Check for error indicators in result (process returned error without throwing)
734
+ const hasResultError = !error && (!!result?._error || !!result?.error);
735
+ const resultError = hasResultError ? result._error || result.error : null;
736
+ const resultErrorMessage = resultError?.message || (typeof resultError === 'string' ? resultError : null);
737
+
738
+ // Determine if this is an error case (either thrown error or result error)
739
+ const isError = !!error || hasResultError;
740
+ const errorMessage = error?.message || resultErrorMessage || 'Process returned error';
741
+
561
742
  if (error) {
562
743
  agentSpan.recordException(error);
563
744
  agentSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
564
745
  agentSpan.addEvent('skill.process.error', {
565
746
  'error.message': error.message,
566
747
  });
748
+ } else if (hasResultError) {
749
+ // Handle error in result (no exception thrown)
750
+ agentSpan.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
751
+ agentSpan.addEvent('skill.process.error', {
752
+ 'error.message': errorMessage,
753
+ 'error.type': 'result_error',
754
+ });
755
+ agentSpan.setAttributes({
756
+ 'output.size': JSON.stringify(result || {}).length,
757
+ 'output.has_error': true,
758
+ });
567
759
  } else {
568
760
  agentSpan.setStatus({ code: SpanStatusCode.OK });
569
761
  agentSpan.addEvent('skill.process.completed', {
@@ -575,18 +767,29 @@ export class OTel extends TelemetryConnector {
575
767
  }
576
768
 
577
769
  // Emit log BEFORE ending span to ensure context is active
578
- const outputForLog = oTelInstance.formatOutputForLog(result, !!error);
770
+ const outputForLog = oTelInstance.formatOutputForLog(result, isError);
579
771
  const spanCtx = agentSpan.spanContext();
580
772
  const logAttributes: Record<string, any> = {
581
773
  // Explicit trace correlation (some backends need these)
582
774
  trace_id: spanCtx.traceId,
583
775
  span_id: spanCtx.spanId,
584
776
  trace_flags: spanCtx.traceFlags,
585
- agentId,
586
- processId: agentProcessId,
587
- hasError: !!error,
588
- 'error.message': error?.message,
777
+ 'agent.id': agentId,
778
+ 'process.id': agentProcessId,
779
+ hasError: isError,
780
+ 'error.message': isError ? errorMessage : undefined,
589
781
  'error.stack': error?.stack,
782
+ 'error.type': hasResultError ? 'result_error' : undefined,
783
+ 'team.id': teamId,
784
+ 'org.slot': orgSlot,
785
+ 'org.tier': orgTier,
786
+ 'conv.id': conversationId,
787
+ 'session.id': sessionId,
788
+ 'workflow.id': workflowId,
789
+ 'log.tags': logTags,
790
+ 'agent.debug': isDebugSession,
791
+ 'agent.isTest': isTestDomain,
792
+ 'agent.domain': domain,
590
793
  };
591
794
 
592
795
  // Only include output if formatOutputForLog returns a value
@@ -598,9 +801,9 @@ export class OTel extends TelemetryConnector {
598
801
  const spanContext = trace.setSpan(context.active(), agentSpan);
599
802
  context.with(spanContext, () => {
600
803
  logger.emit({
601
- severityNumber: error ? SeverityNumber.ERROR : SeverityNumber.INFO,
602
- severityText: error ? 'ERROR' : 'INFO',
603
- body: `Agent process ${error ? 'failed' : 'completed'}: ${agentProcessId}`,
804
+ severityNumber: isError ? SeverityNumber.ERROR : SeverityNumber.INFO,
805
+ severityText: isError ? 'ERROR' : 'INFO',
806
+ body: `Agent process ${isError ? 'failed' : 'completed'}: ${agentProcessId}`,
604
807
  attributes: logAttributes,
605
808
  } as any);
606
809
  });
@@ -625,7 +828,27 @@ export class OTel extends TelemetryConnector {
625
828
  const componentName = settings.displayName || settings.name;
626
829
  const eventId = settings.eventId; // specific event id attached to this component execution
627
830
  const accessCandidate = AccessCandidate.agent(agentId);
628
- if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process started', { componentId }, accessCandidate);
831
+ const teamId = agent.teamId;
832
+ const orgTier = 'standard';
833
+ const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
834
+
835
+ const componentData = agent.agentRuntime?.getComponentData?.(componentId);
836
+ const sourceId = componentData?.sourceId || 'AGENT';
837
+ const sourceComponentData = sourceId !== 'AGENT' ? agent.components?.[sourceId] : null;
838
+ const sourceName = sourceComponentData?.displayName || sourceComponentData?.name || sourceId;
839
+
840
+ const sessionId = agent.callerSessionId || undefined;
841
+ const workflowId = agent.agentRuntime?.workflowReqId || undefined;
842
+ const workflowStep = agent.agentRuntime?.curStep || undefined;
843
+
844
+ const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
845
+ const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
846
+ const isTestDomain = agent.usingTestDomain || false;
847
+
848
+ const inputAction = input?.__action || undefined;
849
+ const inputStatus = input?.__status || undefined;
850
+
851
+ if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process started', { componentId, sourceId }, accessCandidate);
629
852
 
630
853
  const ctx = OTelContextRegistry.get(agentId, processId);
631
854
  const parentSpan = ctx?.rootSpan;
@@ -642,13 +865,23 @@ export class OTel extends TelemetryConnector {
642
865
  'cmp.id': componentId,
643
866
  'cmp.type': componentType,
644
867
  'cmp.name': componentName,
868
+ 'team.id': teamId,
869
+ 'org.tier': orgTier,
870
+ 'org.slot': orgSlot,
871
+ 'source.id': sourceId,
872
+ 'source.name': sourceName,
873
+ 'session.id': sessionId,
874
+ 'workflow.id': workflowId,
875
+ 'workflow.step': workflowStep,
876
+ 'agent.debug': isDebugSession,
877
+ 'agent.isTest': isTestDomain,
645
878
  ...compSettingsData,
646
879
  },
647
880
  },
648
881
  parentSpan ? trace.setSpan(context.active(), parentSpan) : undefined
649
882
  );
650
883
 
651
- // Add event: Component started
884
+ // Add event: Component started - includes input.action and input.status for workflow tracking
652
885
  const inputStr = JSON.stringify(input || {});
653
886
 
654
887
  const compInputData = oTelInstance.prepareComponentData(input || {});
@@ -656,6 +889,8 @@ export class OTel extends TelemetryConnector {
656
889
  'event.id': eventId,
657
890
  'cmp.input.size': JSON.stringify(input || {}).length,
658
891
  'cmp.input': JSON.stringify(compInputData),
892
+ 'input.action': inputAction,
893
+ 'input.status': inputStatus,
659
894
  });
660
895
 
661
896
  // Emit structured log with full details
@@ -673,6 +908,17 @@ export class OTel extends TelemetryConnector {
673
908
  'cmp.type': componentType,
674
909
  'cmp.name': componentName,
675
910
  'cmp.input': input,
911
+ 'team.id': teamId,
912
+ 'org.slot': orgSlot,
913
+ 'org.tier': orgTier,
914
+ 'source.id': sourceId,
915
+ 'source.name': sourceName,
916
+ 'session.id': sessionId,
917
+ 'workflow.id': workflowId,
918
+ 'workflow.step': workflowStep,
919
+ 'log.tags': logTags,
920
+ 'agent.debug': isDebugSession,
921
+ 'agent.isTest': isTestDomain,
676
922
  },
677
923
  });
678
924
  });
@@ -699,6 +945,22 @@ export class OTel extends TelemetryConnector {
699
945
  const componentId = settings.id || 'unknown';
700
946
  const componentType = settings.name;
701
947
  const componentName = settings.displayName || settings.name;
948
+ const teamId = agent.teamId;
949
+ const orgTier = 'standard';
950
+ const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
951
+
952
+ const componentData = agent.agentRuntime?.getComponentData?.(componentId);
953
+ const sourceId = componentData?.sourceId || 'AGENT';
954
+ const sourceComponentData = sourceId !== 'AGENT' ? agent.components?.[sourceId] : null;
955
+ const sourceName = sourceComponentData?.displayName || sourceComponentData?.name || sourceId;
956
+
957
+ const sessionId = agent.callerSessionId || undefined;
958
+ const workflowId = agent.agentRuntime?.workflowReqId || undefined;
959
+ const workflowStep = agent.agentRuntime?.curStep || undefined;
960
+
961
+ const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
962
+ const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
963
+ const isTestDomain = agent.usingTestDomain || false;
702
964
 
703
965
  const accessCandidate = AccessCandidate.agent(agentId);
704
966
  if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process completed', { componentId }, accessCandidate);
@@ -736,51 +998,125 @@ export class OTel extends TelemetryConnector {
736
998
  'error.type': error.name,
737
999
  'error.message': error.message,
738
1000
  'error.stack': error.stack, // ← Full stack in logs
1001
+ 'team.id': teamId,
1002
+ 'org.slot': orgSlot,
1003
+ 'org.tier': orgTier,
1004
+ 'source.id': sourceId,
1005
+ 'source.name': sourceName,
1006
+ 'session.id': sessionId,
1007
+ 'workflow.id': workflowId,
1008
+ 'workflow.step': workflowStep,
1009
+ 'log.tags': logTags,
1010
+ 'agent.debug': isDebugSession,
1011
+ 'agent.isTest': isTestDomain,
739
1012
  },
740
1013
  });
741
1014
  });
742
1015
  } else {
743
- span.setStatus({ code: SpanStatusCode.OK });
744
-
745
- // Add success event with output summary
1016
+ // Check if result contains an error indicator (component returned error without throwing)
1017
+ const hasResultError = !!result?._error || !!result?.error;
746
1018
  const resultStr = JSON.stringify(result || {});
747
- span.addEvent('cmp.call.result', {
748
- 'output.size': resultStr.length,
749
- 'output.preview': resultStr.substring(0, 200),
750
- });
751
1019
 
752
- // Add output attributes to span
753
- span.setAttributes({
754
- 'output.size': JSON.stringify(result || {}).length,
755
- 'output.has_error': !!result?._error,
756
- });
1020
+ if (hasResultError) {
1021
+ // Treat as error even though no exception was thrown
1022
+ const resultError = result._error || result.error;
1023
+ const errorMessage = resultError?.message || (typeof resultError === 'string' ? resultError : 'Component returned error');
757
1024
 
758
- // Emit success log with output (formatted safely)
759
- const outputForLog = oTelInstance.formatOutputForLog(result, false);
760
- const logAttributes: Record<string, any> = {
761
- 'agent.id': agentId,
762
- 'cmp.id': componentId,
763
- 'cmp.type': componentType,
764
- 'cmp.name': componentName,
765
- 'process.id': processId,
766
- 'event.id': eventId,
767
- 'cmp.output': result,
768
- };
1025
+ span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
1026
+ span.addEvent('cmp.call.error', {
1027
+ 'event.id': eventId,
1028
+ 'cmp.id': componentId,
1029
+ 'cmp.type': componentType,
1030
+ 'cmp.name': componentName,
1031
+ 'error.type': 'result_error',
1032
+ 'error.message': errorMessage,
1033
+ });
769
1034
 
770
- // Only include output if formatOutputForLog returns a value
771
- // if (outputForLog !== undefined) {
772
- // logAttributes['cmp.output'] = outputForLog;
773
- // }
1035
+ // Add output attributes to span
1036
+ span.setAttributes({
1037
+ 'output.size': resultStr.length,
1038
+ 'output.has_error': true,
1039
+ });
774
1040
 
775
- const spanContext = trace.setSpan(context.active(), span);
776
- context.with(spanContext, () => {
777
- logger.emit({
778
- severityNumber: SeverityNumber.INFO,
779
- severityText: 'INFO',
780
- body: `Component ${componentType} (${componentId}) completed successfully`,
781
- attributes: logAttributes,
1041
+ // Emit ERROR log for result error
1042
+ const spanContext = trace.setSpan(context.active(), span);
1043
+ context.with(spanContext, () => {
1044
+ logger.emit({
1045
+ severityNumber: SeverityNumber.ERROR,
1046
+ severityText: 'ERROR',
1047
+ body: `Component ${componentType} (${componentId}) failed: ${errorMessage}`,
1048
+ attributes: {
1049
+ 'agent.id': agentId,
1050
+ 'process.id': processId,
1051
+ 'event.id': eventId,
1052
+ 'cmp.id': componentId,
1053
+ 'cmp.name': componentName,
1054
+ 'cmp.type': componentType,
1055
+ 'error.type': 'result_error',
1056
+ 'error.message': errorMessage,
1057
+ 'cmp.output': result,
1058
+ 'team.id': teamId,
1059
+ 'org.slot': orgSlot,
1060
+ 'org.tier': orgTier,
1061
+ 'source.id': sourceId,
1062
+ 'source.name': sourceName,
1063
+ 'session.id': sessionId,
1064
+ 'workflow.id': workflowId,
1065
+ 'workflow.step': workflowStep,
1066
+ 'log.tags': logTags,
1067
+ 'agent.debug': isDebugSession,
1068
+ 'agent.isTest': isTestDomain,
1069
+ },
1070
+ });
782
1071
  });
783
- });
1072
+ } else {
1073
+ // True success case
1074
+ span.setStatus({ code: SpanStatusCode.OK });
1075
+
1076
+ // Add success event with output summary
1077
+ span.addEvent('cmp.call.result', {
1078
+ 'output.size': resultStr.length,
1079
+ 'output.preview': resultStr.substring(0, 200),
1080
+ });
1081
+
1082
+ // Add output attributes to span
1083
+ span.setAttributes({
1084
+ 'output.size': resultStr.length,
1085
+ 'output.has_error': false,
1086
+ });
1087
+
1088
+ // Emit success log with output (formatted safely)
1089
+ const logAttributes: Record<string, any> = {
1090
+ 'agent.id': agentId,
1091
+ 'cmp.id': componentId,
1092
+ 'cmp.type': componentType,
1093
+ 'cmp.name': componentName,
1094
+ 'process.id': processId,
1095
+ 'event.id': eventId,
1096
+ 'cmp.output': result,
1097
+ 'team.id': teamId,
1098
+ 'org.slot': orgSlot,
1099
+ 'org.tier': orgTier,
1100
+ 'source.id': sourceId,
1101
+ 'source.name': sourceName,
1102
+ 'session.id': sessionId,
1103
+ 'workflow.id': workflowId,
1104
+ 'workflow.step': workflowStep,
1105
+ 'log.tags': logTags,
1106
+ 'agent.debug': isDebugSession,
1107
+ 'agent.isTest': isTestDomain,
1108
+ };
1109
+
1110
+ const spanContext = trace.setSpan(context.active(), span);
1111
+ context.with(spanContext, () => {
1112
+ logger.emit({
1113
+ severityNumber: SeverityNumber.INFO,
1114
+ severityText: 'INFO',
1115
+ body: `Component ${componentType} (${componentId}) completed successfully`,
1116
+ attributes: logAttributes,
1117
+ });
1118
+ });
1119
+ }
784
1120
  }
785
1121
 
786
1122
  span.end();