Skip to content

[api][runtime][python] Add Agent Trace recording to Event Log#924

Open
joeyutong wants to merge 3 commits into
apache:mainfrom
joeyutong:codex/agent-trace-event-log-pr
Open

[api][runtime][python] Add Agent Trace recording to Event Log#924
joeyutong wants to merge 3 commits into
apache:mainfrom
joeyutong:codex/agent-trace-event-log-pr

Conversation

@joeyutong

@joeyutong joeyutong commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Linked discussion: #900

Related: #710, #841, #923

Purpose of change

This PR implements the recording side of Agent Trace proposed in #900.

The existing Event Log records business Events but does not provide enough runtime context to identify one input run, distinguish concrete Action/LLM/Parser/Tool executions, reconstruct nested execution relationships, or attribute execution failures.

This PR adds execution identity and lifecycle recording to the existing Event Log path. It complements the business Event lineage implemented in #923 rather than defining another Event-to-Action lineage field:

  • Business Event lineage remains responsible for cross-Action causality.
  • This PR records concrete execution identity and parent-child containment.
  • Business Events emitted by an Action retain that Action execution's executionId, connecting the two models.

API and trace model

  • ExecutionTraceContext carries run identity, execution hierarchy, entity identity, and entity metadata.
  • ExecutionLifecycleEvents defines started, finished, failed, and reused lifecycle Events.
  • ExecutionReporter and ExecutionReporters provide an optional, best-effort capability for reporting nested executions.
  • ToolExecutionMetadataProvider allows Tools to contribute small structured execution metadata.
  • EventLogger accepts an optional ExecutionTraceContext; its default overload preserves compatibility with existing implementations.
  • AgentPlan carries the Agent name used by trace records.
  • event-log.trace.enabled controls Trace persistence and defaults to false.

Runtime integration

  • ActionExecutionOperator creates one run context per processed input and one execution context per Action invocation.
  • ActionTask carries the Action execution context and started-event marker across continuations and Flink state restoration.
  • ActionTaskContextManager keeps child-execution start/terminal pairing transient and scoped by Action execution id across live continuation tasks.
  • Action executions emit lifecycle Events around invocation and emit reused when completed Action state is reused.
  • Business Events continue through EventRouter.
  • Built-in lifecycle reporting sends Execution Events through ExecutionEventSink without automatically submitting them to the business Event routing path.
  • RunnerContextImpl implements ExecutionReporter, creates child execution contexts, and pairs start and terminal reports.
  • ExecutionEventLogger sends Execution Events to the shared EventLogWriter.
  • EventLogWriter owns logger open, append, flush, and close operations; write failures remain best-effort.

Action and resource instrumentation

  • ChatModelAction records one LLM execution per framework model invocation.
  • Structured-output parsing is recorded as a separate Parser execution.
  • ToolCallAction records one Tool execution per concrete tool call, including error responses and thrown exceptions.
  • The instrumentation does not change existing retry, ignore, or Tool-call execution semantics.
  • MCP Tools remain Tool executions; MCP Server identity is stored as metadata.
  • Explicit load_skill calls record the loaded Skill as Tool execution metadata.
  • Failure Events preserve the deepest available cause and use stable problem categories.

Python alignment

  • Python exposes the same ExecutionReporter capability and entity/problem vocabulary as Java.
  • Python LLM, Parser, and Tool boundaries report the same lifecycle semantics.
  • Python reporting delegates to the runtime context without introducing a second trace model.
  • Python Event IDs represent unique Event occurrences rather than content-derived identities.

Event Log format and compatibility

EventLogRecord combines EventContext, optional ExecutionTraceContext, and Event.

The JSONL representation is flattened for querying and aggregation. Framework-owned fields retain the existing camelCase convention, including eventType, eventAttributes, inputRunId, and executionId. The record includes Event occurrence fields, run identity, execution hierarchy, entity information, lifecycle status, failure category, and Event attributes.

The framework deserializer continues to read the previous nested Event Log format. Existing external consumers that parse the raw JSON shape must migrate to the normalized field names.

Trace persistence is disabled by default. When disabled, business Events continue to be logged without trace context and Execution Events are not persisted.

A restored ActionTask retains its run and execution identities. A source-replayed input not represented by restored Action state starts a new run.

This PR changes the pending ActionTask state schema. Restoring savepoints containing that state from before this change would require a versioned ActionTask state serializer, which is outside this PR.

Tests

  • Added and updated Java tests for trace contexts, lifecycle Events, Event Log serde, Event Log writing, Action execution, retries, Tool reporting, MCP metadata, and Skill metadata.
  • Added and updated Python tests for reporter behavior, LLM/Parser retries, Tool reporting, MCP metadata, and Skill metadata.
  • mvn -pl runtime -am -DskipITs test
    • API: 283 tests passed, 9 skipped.
    • MCP integration: 39 tests passed.
    • Plan: 199 tests passed, 1 skipped.
    • Runtime: 425 tests passed.
  • Focused Java validation for lifecycle reporting, Event Log serde/writing, Action execution, Tool/MCP/Skill metadata: 105 tests passed.
  • Focused Python validation for reporter, Tool, MCP, and Skill paths: 35 tests passed.
  • Java Spotless and Python Ruff checks passed.

API

This PR introduces the public Trace APIs described above and extends EventLogger with a backward-compatible default overload accepting optional trace context.

The normalized raw Event Log JSON shape is a compatibility change for external consumers. Legacy records remain readable through the framework deserializer.

Documentation

  • doc-needed
  • doc-not-needed
  • doc-included

@github-actions github-actions Bot added doc-included Your PR already contains the necessary documentation updates. fixVersion/0.4.0 priority/major Default priority of the PR or issue. labels Jul 24, 2026
@joeyutong
joeyutong marked this pull request as ready for review July 24, 2026 02:33
@github-actions github-actions Bot added doc-included Your PR already contains the necessary documentation updates. and removed doc-included Your PR already contains the necessary documentation updates. labels Jul 24, 2026
@github-actions github-actions Bot added doc-included Your PR already contains the necessary documentation updates. and removed doc-included Your PR already contains the necessary documentation updates. labels Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc-included Your PR already contains the necessary documentation updates. fixVersion/0.4.0 priority/major Default priority of the PR or issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant