For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://docs.nvidia.com/dynamo/llms.txt. For full content including API reference and SDK examples, see https://docs.nvidia.com/dynamo/llms-full.txt.
Трассировка агентов
Трассировка агентов фиксирует, кто вызвал (nvext.agent_context), что Dynamo измерил по каждому запросу к LLM (request_end), а также необязательные интервалы инструментов harness (tool_*). Контекст пассивен: он не влияет ни на маршрутизацию, ни на кэширование. Результат представляет собой профилирующие данные best-effort, а не журнал аудита.
Поток: Harness отправляет chat completions с agent_context → Dynamo публикует request_end в приемники трассировки. Harness отправляет события инструментов по ZMQ → в те же приемники.
Добавление контекста трассировки в каждый вызов LLM
Прямой вызов LLM
Внедрите agent_context в каждый запрос к LLM
{
"model": "my-model",
"messages": [{ "role": "user", "content": "..." }],
"nvext": {
"agent_context": {
"session_type_id": "deep_research",
"session_id": "research-run-42",
"trajectory_id": "research-run-42:researcher",
"parent_trajectory_id": "research-run-42:planner"
}
}
}
| Поле | Обязательно | Значение |
|---|---|---|
session_type_id | Да | Класс рабочей нагрузки (например, deep_research). |
session_id | Да | Весь прогон агента. |
trajectory_id | Да | Одна цепочка рассуждений/инструментов внутри прогона. |
parent_trajectory_id | Нет | Родительская траектория при использовании сабагентов. |
Клиент OpenAI: объединяйте в extra_body / extra_headers:
import uuid
def instrument_llm_request(kwargs, agent_context):
body = dict(kwargs.get("extra_body") or {})
nvext = dict(body.get("nvext") or {})
nvext["agent_context"] = dict(agent_context)
body["nvext"] = nvext
headers = dict(kwargs.get("extra_headers") or {})
headers.setdefault("x-request-id", str(uuid.uuid4()))
out = dict(kwargs)
out["extra_body"] = body
out["extra_headers"] = headers
return out
x-request-id — это ваш логический идентификатор на вызов; Dynamo сохраняет его как request.x_request_id (отдельно от внутреннего request_id Dynamo). В harness не требуется импортов Dynamo. Храните контекст в contextvar, прикрепляйте его перед каждым completion и передавайте через потоки/процессы, когда эти пути вызывают модель или отправляют инструменты.
Включение вывода
Быстрый путь — одна переменная окружения:
export DYN_AGENT_TRACE=1
Это выбирает вывод jsonl_gz в /tmp/dynamo-agent-trace.*.jsonl.gz и привязывает
ZMQ endpoint для событий инструментов harness к tcp://127.0.0.1:20390. Любая
из переменных ниже по-прежнему имеет приоритет при явном задании, так что к ним
нужно обращаться только чтобы перенести вывод, добавить stderr или настроить буферы.
Чтобы только перенести место сохранения:
export DYN_AGENT_TRACE=1
export DYN_AGENT_TRACE_OUTPUT_PATH=/mnt/captures/run-42
Все переменные окружения трассировки агентов
| Переменная | Обязательно | Значение по умолчанию (когда DYN_AGENT_TRACE=1) | Примечания |
|---|---|---|---|
DYN_AGENT_TRACE | Главный переключатель | unset | Истинное значение (1, true, on, yes) включает трассировку со всеми значениями по умолчанию ниже. |
DYN_AGENT_TRACE_SINKS | Нет | jsonl_gz | jsonl, jsonl_gz, stderr или список через запятую (например, jsonl_gz,stderr). |
DYN_AGENT_TRACE_OUTPUT_PATH | Нет | /tmp/dynamo-agent-trace | Путь к файлу для jsonl; префикс сегмента для jsonl_gz → prefix.NNNNNN.jsonl.gz. |
DYN_AGENT_TRACE_CAPACITY | Нет | 1024 | Ёмкость trace bus. |
DYN_AGENT_TRACE_JSONL_BUFFER_BYTES | Нет | 1048576 | Порог буфера / пакета gzip. |
DYN_AGENT_TRACE_JSONL_FLUSH_INTERVAL_MS | Нет | 1000 | Интервал сброса. |
DYN_AGENT_TRACE_JSONL_GZ_ROLL_BYTES | Нет | 268435456 | Роллинг сегмента gzip по несжатым байтам. |
DYN_AGENT_TRACE_JSONL_GZ_ROLL_LINES | Нет | unset | Необязательный роллинг по числу строк. |
DYN_AGENT_TRACE_REPLAY_HASHES | Нет | on | Ложное значение (0, no, …) отключает хэши replay в запросах. |
DYN_AGENT_TRACE_TOOL_EVENTS_ZMQ_ENDPOINT | Нет | tcp://127.0.0.1:20390 | Адрес привязки PULL для записей инструментов. |
DYN_AGENT_TRACE_TOOL_EVENTS_ZMQ_TOPIC | Нет | unset | Если задано, первый фрейм ZMQ должен совпадать. |
Без DYN_AGENT_TRACE=1 трассировка выключена; остальные переменные
начинают действовать только после включения мастер-переключателя.
События инструментов (ZMQ)
Формат передачи: [topic, seq_be_u64, msgpack(AgentTraceRecord)]. Чтобы публиковать в Dynamo, используйте фоновый publisher, ограниченную очередь, монотонную последовательность и PUSH с HWM. Конечные строки tool_end / tool_error должны содержать тайминги (started_at_unix_ms, ended_at_unix_ms, duration_ms), даже если tool_start был потерян.
Используйте тот же agent_context, что и у окружающих вызовов LLM; tool_call_id должен быть уникален в пределах одной траектории. Объединяйте офлайн по session_id, trajectory_id, tool_call_id.
Пример tool_end:
{
"schema": "dynamo.agent.trace.v1",
"event_type": "tool_end",
"event_time_unix_ms": 1777312801500,
"event_source": "harness",
"agent_context": {
"session_type_id": "deep_research",
"session_id": "research-run-42",
"trajectory_id": "research-run-42:researcher"
},
"tool": {
"tool_call_id": "call-abc",
"tool_class": "web_search",
"status": "succeeded",
"started_at_unix_ms": 1777312801080,
"ended_at_unix_ms": 1777312801500,
"duration_ms": 420.5
}
}
Необязательные ключи tool: output_tokens, output_bytes, tool_name_hash, error_type (полезно для tool_error). Значения статуса: running, succeeded, error, cancelled; синонимы ok/success, failed, timeout/canceled тоже десериализуются.
Запись Dynamo request_end
Публикуется после завершения потока ответа или после его сброса. Пропущенные ключи на этом пути не записывались; полный Rust-схемы см. в AgentTraceRecord / AgentRequestMetrics в lib/llm/src/agents/trace/types.rs.
{
"schema": "dynamo.agent.trace.v1",
"event_type": "request_end",
"event_time_unix_ms": 1777312801000,
"event_source": "dynamo",
"agent_context": {
"session_type_id": "deep_research",
"session_id": "research-run-42",
"trajectory_id": "research-run-42:researcher",
"parent_trajectory_id": "research-run-42:planner"
},
"request": {
"request_id": "dynamo-request-id",
"x_request_id": "llm-call-42",
"model": "my-model",
"output_tokens": 16,
"finish_reason_metadata": {
"finish_reason": "tool_calls",
"backend_finish_reason": "stop",
"stop_reason": "END",
"tool_calls": [
{
"choice_index": 0,
"tool_call_index": 0,
"id": "call-abc",
"name": "web_search"
}
],
"choices": [
{
"choice_index": 0,
"finish_reason": "tool_calls",
"backend_finish_reason": "stop",
"stop_reason": "END"
}
]
},
"replay": {
"trace_block_size": 64,
"input_length": 128,
"input_sequence_hashes": [14879255164371896291, 274632075616497421]
}
}
}
finish_reason_metadata необязателен. backend_finish_reason и stop_reason
поступают из пути остановки backend/token; finish_reason — это финальная
OpenAI-compatible причина завершения после переписывания парсером, например tool_calls.
Поля завершения верхнего уровня суммируют типичный случай с одним выбором; choices
сохраняет поля завершения для каждого варианта, когда n > 1. Метаданные tool-call содержат только id и
имена; аргументы намеренно не сохраняются в agent traces.
Для chat streams финальные метаданные завершения записываются после переписывания parser/jail;
completion streams записывают финальную OpenAI-compatible причину завершения
из choices ответа completion.
По умолчанию мы не сохраняем входные/выходные payload'ы. Чтобы увидеть их, используйте встроенную функцию Dynamo audit_sink.
Audit side-by-side (тот же механизм gzip/jsonl):
# enable agent trace sinks
export DYN_AGENT_TRACE_SINKS=jsonl_gz
export DYN_AGENT_TRACE_OUTPUT_PATH=/tmp/dynamo-trace
# enable audit sinks
export DYN_AUDIT_SINKS=jsonl_gz
export DYN_AUDIT_OUTPUT_PATH=/tmp/dynamo-audit
export DYN_AUDIT_FORCE_LOGGING=true
После прогона сопоставьте по id:
gzip -cd /tmp/dynamo-audit.*.jsonl.gz | jq -c '.event' > /tmp/audit.jsonl
gzip -cd /tmp/dynamo-trace.*.jsonl.gz | jq -c '.event' > /tmp/trace.jsonl
jq -s 'group_by(.request_id // .request.request_id)' /tmp/audit.jsonl /tmp/trace.jsonl
Результат — файл JSONL, где каждая строка оборачивает запись:
{
"timestamp": 1234,
"event": { "schema": "dynamo.agent.trace.v1", "...": "..." }
}
timestamp — это elapsed ms относительно sink; для порядка по реальному времени используйте event.event_time_unix_ms.
Просмотр трассировок в Perfetto
Чтобы визуализировать и оптимизировать ваш agentic graph, мы предоставляем утилиту для преобразования agent trace JSONL-файлов в trace-файл Perfetto. Мы считаем это крайне полезным для pipeline-агентов, которые пишет наша команда!
uv run --no-project python benchmarks/agent_trace/convert_to_perfetto.py \
"${DYN_AGENT_TRACE_OUTPUT_PATH}".*.jsonl.gz \
--output "${DYN_AGENT_TRACE_OUTPUT_PATH}.perfetto.json"
Откройте в Perfetto UI. Флаги: --include-markers, --no-stages, --separate-stage-tracks.
Срезы запросов включают сглаженные метаданные завершения, если они присутствуют, например finish.finish_reason,
finish.backend_finish_reason, finish.stop_reason, finish.tool_call_count,
finish.tool_call_names и сводки по каждому выбору, такие как finish.choice_finish_reasons.
[Экспериментально] Повтор agent traces с помощью agentic Mooncake replay
Вы можете преобразовать собранный agent trace в trace agentic Mooncake и воспроизвести его с помощью
python -m dynamo.replay. Конвертер использует строки Dynamo request_end для таймингов запросов, длины токенов, размещения worker'ов и replay hashes. Он также использует конечные строки инструментов harness (tool_end / tool_error), чтобы сохранить время ожидания инструментов между зависимыми запросами LLM.
Replay игнорирует не относящиеся к replay поля запроса, такие как finish_reason_metadata; используйте
представление Perfetto выше, когда нужно посмотреть финальные причины завершения, backend stop
сигналы или полные метаданные tool-call внутри trace.
cargo run -p dynamo-bench --bin agent_trace_to_mooncake -- \
--agentic \
--input-path "${DYN_AGENT_TRACE_OUTPUT_PATH}".*.jsonl.gz \
--output-file /tmp/dynamo-agent-trace.agentic-mooncake.jsonl
Бинарник выводит trace_block_size. Используйте именно это значение для replay, чтобы сегментация хэшей
совпадала с тем, что записал Dynamo. Согласуйте размер блока mock engine с тем же числом в
--extra-engine-args.
TRACE_BLOCK_SIZE=128
uv run --no-sync python -m dynamo.replay /tmp/dynamo-agent-trace.agentic-mooncake.jsonl \
--trace-format agentic_mooncake \
--trace-block-size "${TRACE_BLOCK_SIZE}" \
--replay-mode offline \
--router-mode kv_router \
--num-workers 4 \
--extra-engine-args "{\"block_size\":${TRACE_BLOCK_SIZE}}" \
--report-json /tmp/dynamo-agent-trace.replay-report.json
kv_router требует как минимум двух mock workers; для smoke test с одним worker используйте
--router-mode round_robin --num-workers 1.
Строки Agentic Mooncake сохраняют:
request_id: идентичность строки запроса LLM.session_id: Dynamotrajectory_id.wait_for: id запросов, которые должны завершиться, прежде чем эта строка станет доступной.branches: дочерние id запросов, порождённых этой строкой.prefix_reset: первый запрос в траектории.delay: задержка не из-за инструментов после завершения зависимостей.tool_wait_ms: время инструментов после завершения зависимостей с учётом параллельности (объединение перекрывающихся интервалов, а не их сумма).tool_events: интервалы по каждому инструменту, привязанные к этому запросу LLM, каждый содержитtool_call_id,tool_class,status,started_at_unix_ms,ended_at_unix_ms,duration_ms, а также необязательныеoutput_bytes/output_tokens/error_type.hash_ids,input_lengthиoutput_length: данные о prompt-prefix и длине для replay через mocker.
Строки без wait_for используют свой timestamp как время начала replay. Строки с зависимостями ждут,
пока завершатся все перечисленные запросы, затем ждут delay + tool_wait_ms перед отправкой. Дополнительные
флаги и настройки engine см. в DynoSim Runs.
Согласование ATIF
Dynamo выпускает dynamo.agent.trace.v1, а не полные ATIF-логи, но идентификаторы совпадают с ATIF / Harbor, так что вы можете объединять траектории harness со строками Dynamo по session_id + trajectory_id. Dynamo намеренно не включает разговорные данные.
| Dynamo | Роль |
|---|---|
session_id | Общий id прогона |
trajectory_id | Ветвь внутри прогона |
parent_trajectory_id | Связь с сабагентом |
session_type_id | Профиль / тип нагрузки |