# Different agent frameworks log 'input_tokens' differently. Here's the fix.

> Source: <https://dev.to/mukundakatta/different-agent-frameworks-log-inputtokens-differently-heres-the-fix-igk>
> Published: 2026-05-28 21:06:18+00:00

*This is a submission for the Hermes Agent Challenge.*

I run agents on three different frameworks. Each one logs differently. One uses `input_tokens`

. Another uses `prompt_tokens`

. A third uses `tokens_prompt`

. My trace analysis code had to handle all three. Every new framework meant another alias to add everywhere.

That's `trace-field-normalize`

.

``` python
from trace_field_normalize import normalize_event

event = {"input_tokens": 42, "latency_ms": 350, "model_id": "claude-sonnet-4-5"}
result = normalize_event(event)
# {"tokens_in": 42, "duration_ms": 350, "model": "claude-sonnet-4-5"}
```

Unknown fields pass through unchanged. Nothing is dropped.

``` python
from trace_field_normalize import normalize_file

events = normalize_file("raw_traces.jsonl", "normalized.jsonl")
```

Reads the source line by line, normalizes each event, writes to dest. Blank lines are skipped.

| Canonical | Variants |
|---|---|
`tokens_in` |
`input_tokens` , `prompt_tokens` , `tokens_prompt`
|
`tokens_out` |
`output_tokens` , `completion_tokens` , `tokens_completion`
|
`cost_usd` |
`cost` , `price_usd` , `usd` , `price`
|
`duration_ms` |
`latency_ms` , `elapsed_ms` , `duration` , `latency`
|
`kind` |
`event_type` , `type` , `event_kind`
|
`name` |
`step` , `tool` , `tool_name` , `function_name`
|
`error` |
`err` , `exception` , `error_message`
|
`model` |
`model_id` , `model_name`
|
`lane` |
`worker` , `agent_id` , `thread`
|
`timestamp` |
`ts` , `time` , `created_at` , `event_time`
|

``` python
from trace_field_normalize import FieldMap, normalize_event

fm = FieldMap(
    {"score": ["rating", "confidence"]},
    include_defaults=True,  # keep the built-in map too
)

event = {"rating": 0.95, "input_tokens": 100}
normalize_event(event, fm)
# {"score": 0.95, "tokens_in": 100}
```

`include_defaults=False`

gives you a clean slate.

If the event already has the canonical name, variants are left alone:

```
event = {"tokens_in": 99, "input_tokens": 42}
normalize_event(event)
# {"tokens_in": 99, "input_tokens": 42}
normalize_event({"ts": 1700000000}, keep_original=True)
# {"timestamp": 1700000000, "ts": 1700000000}
```

Useful when downstream code still uses the old name.

``` python
from trace_field_normalize import normalize_events

events = normalize_events(raw_event_list)
```

Returns a new list. Originals are not modified.

Standard library only: `json`

, `dataclasses`

, `pathlib`

. Nothing else.

```
git clone https://github.com/MukundaKatta/trace-field-normalize
cd trace-field-normalize && pip install -e .
```


