You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+35Lines changed: 35 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -147,6 +147,41 @@ samples/ # Example traces and eval sets
147
147
docs/ # Documentation
148
148
```
149
149
150
+
## Trace Processing Architecture
151
+
152
+
agentevals converts OTel traces from agent frameworks into a common `Invocation` format for evaluation. If you're adding support for a new framework or changing how we extract data from spans, this section will help you find your way around.
153
+
154
+
### Key Modules
155
+
156
+
| Module | What it does |
157
+
|--------|--------------|
158
+
|`trace_attrs.py`| Single source of truth for OTel attribute key constants (`OTEL_GENAI_*` for standard semconv, `ADK_*` for Google ADK) |
159
+
|`extraction.py`| Shared extraction functions, span classifiers, and the `TraceFormatExtractor` protocol with `AdkExtractor` / `GenAIExtractor`|
|`genai_converter.py`| Batch conversion for GenAI semconv traces (single-turn and multi-turn) |
162
+
|`streaming/incremental_processor.py`| Real-time span processing for the live UI, uses the same shared extraction functions |
163
+
|`utils/log_enrichment.py`| Reconstructs `gen_ai.input/output.messages` from OTel log records into span attributes |
164
+
165
+
### Adding a new attribute constant
166
+
167
+
Add it to `trace_attrs.py` and import from there. Don't use hardcoded attribute key strings elsewhere.
168
+
169
+
### Adding or modifying extraction logic
170
+
171
+
The extraction functions in `extraction.py` accept flat `dict[str, Any]` attribute maps. This means they work with both `Span`-based batch converters (via `span.tags`) and the raw OTLP dict incremental processor. When extracting data, check ADK-specific attributes first (they contain richer data), then fall back to GenAI semconv.
172
+
173
+
### Supporting a new trace format
174
+
175
+
1. Add a new `TraceFormatExtractor` implementation in `extraction.py` with `detect()`, `find_invocation_spans()`, `find_llm_spans_in()`, `find_tool_spans_in()`, and `classify_span()`
176
+
2. Register it in the `_EXTRACTORS` list. Order matters here: more specific formats should come first so they get detected before the generic GenAI fallback
177
+
3. If the format introduces new attribute keys, add them to `trace_attrs.py`
178
+
4. If you need conversion logic that the shared extraction functions don't cover, add a dedicated converter module (see `genai_converter.py` for an example)
179
+
5. Add tests to `tests/test_extraction.py` for detection and span classification
180
+
181
+
### Adding an SDK example
182
+
183
+
Each example directory under `examples/` is self-contained with its own `requirements.txt`. The example needs to actually produce OTel spans. For OpenAI-based agents this means including `opentelemetry-instrumentation-openai-v2` in the requirements. Make sure all framework-specific OTel dependencies are listed in the example's `requirements.txt`.
184
+
150
185
## Getting Help
151
186
152
187
- Open an [issue](https://github.com/agentevals-dev/agentevals/issues) for bugs or questions
0 commit comments