Class EmbabelTraceCollector

java.lang.Object
dev.dokimos.embabel.EmbabelTraceCollector
All Implemented Interfaces:
com.embabel.agent.api.event.AgenticEventListener

public final class EmbabelTraceCollector extends Object implements com.embabel.agent.api.event.AgenticEventListener
Accumulates an Embabel agent's tool calls into a Dokimos AgentTrace.

Embabel reports tool activity only through per-event AgenticEventListener callbacks during a run, never as a return value. A single collector therefore observes one agent run: register it on the run's ProcessOptions (see EmbabelSupport.attach(com.embabel.agent.core.ProcessOptions, dev.dokimos.embabel.EmbabelTraceCollector)), execute the agent, then read the trace:


 com.embabel.agent.core.ProcessOptions options = new com.embabel.agent.core.ProcessOptions();
 EmbabelTraceCollector collector = new EmbabelTraceCollector();
 options = options.withListener(collector);

 AgentInvocation<MyResult> inv = AgentInvocation.builder(platform)
         .options(options)
         .build(MyResult.class);
 inv.invoke(userInput);

 AgentTrace trace = collector.trace();
 EvalTestCase tc = trace.toTestCase(userInput, EmbabelSupport.toToolDefinitions(collector));
 

The collector maps every ToolCallResponseEvent to one ToolCall, reading the tool name and raw arguments from the back-referenced ToolCallRequestEvent and the tool result from the response event's kotlin.Result. The kotlin.Result accessor is name-mangled and cannot be called from Java source, so it is read through a single reflective helper that unwraps the boxed result and never throws.

Silent-drop contract. A tool call that is requested but never produces a ToolCallResponseEvent (for example, a tool that fails mid-run) is absent from the trace, because only response events map to a ToolCall. This is intentional.

The collector is not thread-safe and is meant for a single agent run. To reuse one instance across runs, call reset() between runs.

  • Nested Class Summary

    Nested classes/interfaces inherited from interface com.embabel.agent.api.event.AgenticEventListener

    com.embabel.agent.api.event.AgenticEventListener.Companion
  • Field Summary

    Fields inherited from interface com.embabel.agent.api.event.AgenticEventListener

    Companion, DevNull
  • Constructor Summary

    Constructors
    Constructor
    Description
    Creates a fresh collector with no captured events.
  • Method Summary

    Modifier and Type
    Method
    Description
    Returns the CallMetrics captured from the completed run, with no price fallback.
    callMetrics(String model, PriceTable prices)
    Returns the CallMetrics captured from the completed run, lighting up the run's metrics cards.
    Returns the distinct tool names observed during the run, in first-seen order.
    void
    onProcessEvent(com.embabel.agent.api.event.AgentProcessEvent event)
    Receives every AgentProcessEvent for the run and dispatches by concrete type.
    void
    Clears all captured state so this collector can observe a fresh run.
    Returns the tool calls captured so far, in execution order.
    Materializes the captured run into an AgentTrace.

    Methods inherited from class java.lang.Object

    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface com.embabel.agent.api.event.AgenticEventListener

    onPlatformEvent
  • Constructor Details

    • EmbabelTraceCollector

      public EmbabelTraceCollector()
      Creates a fresh collector with no captured events.
  • Method Details

    • onProcessEvent

      public void onProcessEvent(com.embabel.agent.api.event.AgentProcessEvent event)
      Receives every AgentProcessEvent for the run and dispatches by concrete type.

      This is the single surface that reads Embabel event fields: a pre-1.0 field rename is a one-method fix. ToolCallResponseEvents are mapped to ToolCalls and AgentProcessCompletedEvent sets the final response; all other events are ignored.

      Specified by:
      onProcessEvent in interface com.embabel.agent.api.event.AgenticEventListener
      Parameters:
      event - the process event, never null in practice
    • toolCalls

      public List<ToolCall> toolCalls()
      Returns the tool calls captured so far, in execution order.
      Returns:
      an immutable copy of the captured tool calls
    • observedToolNames

      public List<String> observedToolNames()
      Returns the distinct tool names observed during the run, in first-seen order.

      Used by EmbabelSupport.toToolDefinitions(EmbabelTraceCollector) to synthesize tool definitions when the framework does not expose the original tool contracts.

      Returns:
      an immutable copy of the observed tool names
    • trace

      public AgentTrace trace()
      Materializes the captured run into an AgentTrace.

      The final response is taken from the AgentProcessCompletedEvent if one was seen; otherwise it is left null. With no events seen, an empty trace is returned. This method never throws.

      Returns:
      an agent trace carrying the captured tool calls in order
    • callMetrics

      public CallMetrics callMetrics()
      Returns the CallMetrics captured from the completed run, with no price fallback.

      Equivalent to callMetrics(null, null): token counts and latency come from the completed AgentProcess, and cost is Embabel's own totalCost() (null when Embabel reported $0). Returns null until a completion event with a readable process has been seen.

      Returns:
      the captured call metrics, or null if no completion event was observed
    • callMetrics

      public CallMetrics callMetrics(String model, PriceTable prices)
      Returns the CallMetrics captured from the completed run, lighting up the run's metrics cards.

      Counterpart to the Spring AI measuredAsyncTask family: Embabel reports token usage and a computed cost as an aggregate on the AgentProcess, snapshotted at completion. The token fields and Embabel's own totalCost() are used as-is. The model/prices arguments are an optional fallback: when Embabel reported no cost (its pricing model didn't know the model) but a PriceTable and model id are supplied, cost is recomputed via prices.costUsd(model, tokensIn, tokensOut) so a known model still lights the Cost card. Embabel's own non-zero cost always wins. Any field stays null when not measured; never throws.

      Returns null until a completion event with a readable process has been seen, so a run that failed or was never executed yields no metrics rather than a fabricated zero.

      Parameters:
      model - the model id used as the PriceTable fallback lookup key, or null to skip it
      prices - the price lookup consulted only when Embabel reported no cost, or null to skip it
      Returns:
      the captured call metrics, or null if no completion event was observed
    • reset

      public void reset()
      Clears all captured state so this collector can observe a fresh run.

      Call between runs when reusing one collector instance to prevent tool calls from a prior run leaking into the next trace.