@@ -7,6 +7,75 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
88## [ Unreleased]
99
10+ ## [ 1.2.0] - 2026-01-28
11+
12+ ### Added
13+
14+ #### Span Events Infrastructure (` msgtrace.sdk.events ` )
15+
16+ New module for emitting span events and real-time streaming, following OpenTelemetry GenAI semantic conventions.
17+
18+ ##### Event Types (` EventType ` )
19+ Constants for span event names:
20+ - ** Agent lifecycle** : ` AGENT_START ` , ` AGENT_STEP ` , ` AGENT_COMPLETE ` , ` AGENT_ERROR `
21+ - ** Model interactions** : ` MODEL_REQUEST ` , ` MODEL_RESPONSE ` , ` MODEL_RESPONSE_CHUNK ` , ` MODEL_REASONING ` , ` MODEL_REASONING_CHUNK `
22+ - ** Tool operations** : ` TOOL_CALL ` , ` TOOL_RESULT ` , ` TOOL_ERROR `
23+ - ** Flow control** : ` FLOW_STEP ` , ` FLOW_REASONING ` , ` FLOW_COMPLETE ` (for ReAct, CoT, etc.)
24+ - ** Module lifecycle** : ` MODULE_START ` , ` MODULE_COMPLETE ` , ` MODULE_ERROR `
25+
26+ ##### Core Function: ` add_event(name, attributes) `
27+ Dual emission to both OTel span and streaming queue:
28+ ``` python
29+ from msgtrace.sdk.events import add_event, EventType
30+
31+ add_event(EventType.TOOL_CALL , {
32+ " tool_name" : " search" ,
33+ " tool_id" : " call_123" ,
34+ " arguments" : {" query" : " weather" },
35+ })
36+ ```
37+
38+ ##### Convenience Functions
39+ - ` add_agent_start_event(agent_name, **extra) `
40+ - ` add_agent_complete_event(agent_name, response=None, **extra) `
41+ - ` add_agent_step_event(agent_name, step_number, step_type="", **extra) `
42+ - ` add_model_request_event(model=None, message_count=None, **extra) `
43+ - ` add_model_response_event(response_type, **extra) `
44+ - ` add_model_response_chunk_event(chunk, index=0, **extra) `
45+ - ` add_model_reasoning_event(reasoning, step=None, **extra) `
46+ - ` add_tool_call_event(tool_name, tool_id, arguments=None, step=None, **extra) `
47+ - ` add_tool_result_event(tool_name, tool_id, result=None, step=None, **extra) `
48+ - ` add_tool_error_event(tool_name, tool_id, error, step=None, **extra) `
49+ - ` add_flow_step_event(step_number, **extra) `
50+ - ` add_flow_reasoning_event(reasoning, step=None, **extra) `
51+ - ` add_flow_complete_event(step=None, **extra) `
52+
53+ ##### Real-Time Streaming (` EventStream ` )
54+ Context manager for capturing span events as an async stream:
55+ ``` python
56+ from msgtrace.sdk.events import EventStream
57+
58+ async with EventStream() as stream:
59+ task = asyncio.create_task(agent.acall(" Hello" ))
60+ async for event in stream:
61+ print (event.name, event.attributes)
62+ await task
63+ ```
64+
65+ ##### Stream Event Data Structure (` StreamEvent ` )
66+ Frozen dataclass with:
67+ - ` name ` : Event name (EventType constant)
68+ - ` attributes ` : Event-specific data
69+ - ` timestamp_ns ` : Nanoseconds since epoch
70+ - ` span_name ` , ` span_id ` , ` trace_id ` : Span context
71+
72+ ### Benefits
73+ - Zero overhead when not streaming (context variable is None)
74+ - Automatic JSON serialization for complex types (dicts, lists)
75+ - Full compatibility with OpenTelemetry span events
76+ - Thread-safe through context variables
77+ - Enables real-time UI updates and streaming responses
78+
1079## [ 1.1.0] - 2025-12-04
1180
1281### Added
0 commit comments