See also (wiki): wiki/agent-operations-observability.md · wiki/semantic-observability.md · wiki/mlops-ai-platform-engineering.md · wiki/model-risk-management.md
Source credibility: MEDIUM-HIGH. Primary sources are Hugging Face Hub/Datasets/TRL docs, Dagster pricing/docs, AWS CloudWatch/S3/Glue/Athena/Firehose pricing docs, OpenTelemetry/OpenInference docs already cited in the companion pages, and the local redacted Codex conversion experiment. This page is architecture research, not a claim that a full end-to-end production pipeline has been run in this repo.
Executive Summary
Agent logs should not be treated as one thing. They are four different data products:
- Raw evidence: native Claude/Codex JSONL, SQLite rows, Bedrock invocation logs, Strands/AgentCore traces, AG-UI/A2A events, local screenshots and file artifacts.
- Operational telemetry: OpenTelemetry traces, metrics, and logs with
trace_id,span_id, parentage, timing, resource attributes, service version, tenant, and rollout/session IDs. - AI semantics: OpenInference, OTel GenAI, and MCP semantic-convention
spans for LLM, tool, retriever, reranker, embedding, chain, agent,
evaluator, prompt, guardrail, memory, context, and protocol events. Pin the
semantic-convention version and record
OTEL_SEMCONV_STABILITY_OPT_INwhenevergen_ai_latest_experimentalor other GenAI opt-ins are used. - Learning datasets: curated SFT rows, preference pairs, verifier environments, eval/golden-set cases, skill candidates, KB defect records, and reliability metric aggregates.
The recommended pipeline is:
native agent logs + cloud invocation logs + protocol events
-> raw vault: S3 or HF private bucket/dataset, partitioned by date/source/tenant
-> OTel collector / ADOT / app instrumentation
-> OpenInference / OTel GenAI / MCP semantic spans
-> bronze/silver/gold tables
-> review queues and redaction gates
-> Hugging Face / internal lake datasets in Parquet + JSONL
-> TRL / Unsloth / LLaMA-Factory / Axolotl / PRIME-RL / AgentCore RL Toolkit
-> eval, benchmark, and rollout promotion
Use AWS when regulated cloud audit, IAM/KMS, Bedrock joins, private VPC data paths, and long-term enterprise retention dominate. Use Dagster when the hard problem is repeatable, inspectable curation across many sources and review stages. Use Hugging Face when the hard problem is ML-native dataset distribution, trace browsing, mounted storage for Jobs/Spaces, TRL-compatible training data, and collaboration around models/datasets.
What Hugging Face Adds
Hugging Face now matters for agent traces directly, not only for model hosting. The Hub’s agent-trace docs say raw JSONL sessions from Claude Code, Codex, and Pi Agent are natively supported. The documented local directories are:
| Agent | Local trace directory |
|---|---|
| Claude Code | ~/.claude/projects |
| Codex | ~/.codex/sessions |
| Pi Agent | ~/.pi/agent/sessions |
The Hub can show these in a trace viewer after upload to a Dataset or Storage Bucket. This is important because it creates a low-friction route from local agent sessions to an inspectable dataset. It is also risky: the same docs warn that trace files can include prompts, tool inputs, command output, local paths, screenshots, secrets, private code, and personal data. The enterprise pattern is therefore private upload first, redaction second, public release never unless a review gate passes.
Hugging Face Storage Buckets are a new fit for mutable agent artifacts: checkpoints, trace batches, redaction outputs, and intermediate curation results. Buckets are not versioned like model/dataset repos; they are mutable object storage on the Hub. Access patterns now include:
| HF access path | Best use | Agent telemetry use |
|---|---|---|
hf upload to Dataset |
Versioned/shareable dataset snapshots | Curated redacted traces, eval sets, SFT/preference splits |
hf buckets sync |
Continuous batch transfer | Sync ~/.codex/sessions or redacted lake extracts into a private bucket |
hf-mount |
Mount bucket/repo as a local filesystem | Let training scripts, DuckDB, vLLM, pandas, or shell tools read trace/data files |
hf:// with fsspec |
Python analytics | Read/write Parquet from pandas, DuckDB, Dask, Spark-style flows |
| HF Jobs/Spaces volume mount | Managed compute reads bucket data | Run curation or training jobs without copying large datasets into the image |
Two technical implications matter:
- Hugging Face Datasets still has local cache behavior. The Hub cache defaults
to
~/.cache/huggingface/hub; Datasets converts data into Arrow cache for non-streaming loads. On large trace corpora, use streaming, Parquet, or mounted buckets deliberately instead of accidentally duplicating hundreds of GB into local Arrow caches. - HF storage is ML-native and cheaper to browse/share in many workflows, but it is not AWS S3. Current docs say bucket S3 API access is not yet supported, so AWS-native systems still need S3, Firehose, Glue, and Athena unless you build a copy bridge.
Hugging Face Trace and Training Formats
Hugging Face gives three related but distinct format layers.
| Layer | Recommended format | Why |
|---|---|---|
| Raw trace storage | Native JSONL plus content-addressed artifacts | Preserves Claude/Codex/Pi replay shape and lets HF trace viewer work |
| Analytics storage | Parquet with stable schema and partitions | Works with DuckDB, pandas, Datasets, Spark-like readers, and cheap column scans |
| Training storage | TRL-supported conversational, prompt-completion, preference, prompt-only, or stepwise-supervision datasets | Matches SFT/DPO/GRPO/Reward/PPO/PRM trainers |
ShareGPT Is a Training Shape, Not a Trace Standard
ShareGPT-style data is useful but easy to overuse. Its common shape is a
conversation array with role-like fields such as from: "human" and
from: "gpt" plus text values. That makes it a convenient bridge for
multi-turn SFT, especially when older fine-tuning stacks expect ShareGPT-like
JSON. It does not preserve enough structure for observability or reliable
agent mining:
| Format | Primary unit | Good for | Weak for |
|---|---|---|---|
| ShareGPT-style conversation | Ordered chat messages | Multi-turn SFT, quick chat corpus conversion, compatibility with many fine-tune recipes | Trace timing, span parentage, tool-call IDs, retries, retrieval lineage, cost, latency, policy decisions, artifacts |
| OTel GenAI semantics | Timed spans/events/metrics with GenAI attributes | Production observability, cost/latency/token metrics, distributed tracing, CloudWatch/OTLP backends | Direct model training rows unless converted and curated |
| AWS AgentCore / CloudWatch GenAI spans | OTel/GenAI spans rendered and queried in AWS | AWS-native agent operations, IAM/CloudWatch integration, AgentCore/Bedrock joins, searchable spans | Cross-vendor training data and local raw replay unless exported/joined |
| OpenInference | OTel-compatible AI semantic spans | LLM/tool/retriever/agent/evaluator taxonomy across Phoenix/Arize and compatible pipelines | Legal training eligibility, dataset splits, raw transcript completeness |
| MCP semantic conventions | Protocol/tool spans and trace context for MCP calls | Tool/resource/prompt server boundaries, cross-process trace propagation | Local approval proof, host execution proof, training labels |
This changes the pipeline recommendation: ShareGPT should be a gold-layer export, not the canonical warehouse schema. Convert traces into ShareGPT only after redaction, validation, label review, and split assignment. Keep OpenInference/OTel rows next to the ShareGPT export so every training example can be traced back to tool calls, retrievals, validators, costs, and failure modes.
TRL’s dataset-format docs separate format from type. Format is standard versus conversational; type is language modeling, prompt-completion, prompt-only, preference, unpaired preference, tokenized language modeling, or stepwise supervision. That maps cleanly to agent traces:
| Agent mining target | Trace-to-training conversion |
|---|---|
| Domain YAML generation | SFT prompt-completion rows: task/context/schema constraints -> validated YAML |
| Better tool-call arguments | SFT or preference rows over tool-call JSON with schema validation |
| Policy or style correction | Preference pairs: rejected answer vs accepted answer, with evaluator/human reason |
| Multi-step reliability | Prompt-only GRPO/RLVR environments with programmatic reward functions |
| Process supervision | Stepwise supervision rows from trajectories where each step has outcome labels |
| KB question discovery | Eval/golden-set rows, not immediately training rows |
For chat models, TRL chat templates are not a cosmetic concern. The TRL docs call out model-family-specific training templates and assistant-only loss masks. For tool-using traces, the template must preserve tool-call structure and mask only the target assistant/tool-call tokens when training. A bad conversion that flattens tool calls into arbitrary text may improve benchmark-looking loss while damaging tool reliability.
AWS Pipeline
AWS is the default if Bedrock/AgentCore is part of the production path.
Bedrock invocation logs
-> CloudWatch Logs for hot operations
-> S3 for durable raw audit
-> Glue catalog / crawler or explicit schema
-> Athena / Iceberg / warehouse tables
Agent app / Strands / Claude SDK / Codex / AG-UI / A2A
-> OTel collector or ADOT
-> CloudWatch GenAI observability, X-Ray-style trace views, or vendor backend
-> S3 Parquet trace tables
-> curated datasets
Prometheus should sit on the metrics branch only:
Agent app / Claude Code / SDK / Strands
-> OTLP metrics
-> OTel collector or Prometheus OTLP metrics receiver
-> Prometheus / managed Prometheus
Bedrock CloudWatch Logs or S3 ModelInvocationLog JSON
-> parser / Lambda / Firehose transform / batch ETL
-> derived low-cardinality metrics
-> Prometheus
Raw prompts, outputs, request IDs, tool bodies, and traces
-> CloudWatch Logs / S3 / warehouse / trace backend
| AWS component | Use | Hard tradeoff |
|---|---|---|
| CloudWatch Logs | Hot troubleshooting, account/region audit, log queries | Ingestion and retained-log costs rise quickly with full prompts/tool bodies |
| S3 | Long-retention raw vault and Parquet lake | You own partitioning, redaction, lifecycle, cataloging, and query ergonomics |
| Firehose | Near-real-time fanout and optional format conversion | Charged by ingested GB and optional features; small records can suffer billing granularity |
| Glue | Catalog, crawlers, ETL, data quality | DPU/crawler/Data Catalog costs; schema drift has to be managed |
| Athena | Serverless SQL over S3 | Charged by scanned data; Parquet, compression, and partitions are mandatory for cost control |
| CloudWatch Application Signals / Transaction Search | Span search and golden metrics | Span ingestion/indexing economics can dominate at high trace volume |
| Bedrock AgentCore | Runtime/evals/memory/gateway/observability | Native control plane is useful but not a complete raw-data and training-rights ledger |
| Prometheus / managed Prometheus | Low-cardinality counters, gauges, histograms, alerts | Metrics only; never store raw prompts, requestId, trace IDs, tool bodies, or full Bedrock invocation JSON as labels |
Recommended derived Prometheus metrics:
agent_model_invocations_total{source,provider,model,operation,status}
agent_input_tokens_total{source,provider,model}
agent_output_tokens_total{source,provider,model}
agent_tool_calls_total{tool_name,tool_type,status}
agent_tool_latency_seconds_bucket{tool_name,tool_type,status}
agent_eval_pass_total{task_type,scorer}
bedrock_invocations_total{region,model_id,operation}
bedrock_input_tokens_total{region,model_id,operation}
bedrock_output_tokens_total{region,model_id,operation}
bedrock_invocation_log_delivery_failures_total{destination}
Do not use Bedrock requestId, prompt hashes, user email, file path, trace ID,
or tool-call ID as Prometheus labels. Keep those as exemplars or lookup keys in
trace/log/warehouse systems. Prometheus is for alerting and rates; the raw
ModelInvocationLog record stays in CloudWatch/S3.
AWS cost modeling is necessary but incomplete. In 2026, the biggest savings may come before logging or storage: context engineering. Track and optimize:
context_cost =
model_input_tokens
+ tool_manifest_tokens
+ retrieval_tokens
+ memory_tokens
+ repeated_tool_output_tokens
+ compaction_summary_tokens
context_savings =
tokens_before_compaction
- tokens_after_compaction
+ tokens_filtered_by_code_execution
+ tokens_avoided_by_artifact_refs
Emit context_events for compaction, tool-output clearing, artifact offload,
memory read/write, retrieval truncation, and code-execution filtering. A cheap
CloudWatch/S3 design can still be expensive if every turn drags stale memory,
large tool manifests, and full tool outputs back into the prompt.
Cost posture:
- Keep hot CloudWatch logs metadata-heavy and short-retention unless compliance requires full content there.
- Put raw full-content logs in S3 with lifecycle tiers and KMS, then convert to partitioned Parquet.
- Store prompt/tool bodies as encrypted object refs and hashes in shared trace tables; reveal content only in gated review queues.
- Query Athena against Parquet partitions, not raw JSON across the whole lake.
- Add cost labels at ingestion:
tenant_id,agent_id,model,provider,workflow,policy_version,prompt_version,rollout_id.
Dagster Pipeline
Dagster is not an observability backend for agent spans. It is useful as the orchestration and lineage system for curation:
raw_trace_batches
-> redact_native_records
-> normalize_to_otel_spans
-> map_to_openinference
-> build_turns_tool_calls_artifacts
-> attach_bedrock_costs_and_invocation_ids
-> run_validators_and_evals
-> route_review_queues
-> emit_curated_hf_dataset / s3_parquet_dataset / langsmith_dataset
The asset graph should encode every irreversible decision: redaction policy, schema version, evaluator version, labeler identity, accepted/rejected examples, and training split. That is where Dagster is strong: materialization history, asset metadata, backfills, retries, schedules, and visible lineage.
Dagster+ cost has a specific implication for this use case. The pricing docs say credits measure asset materializations and ops executed, and Solo/Starter pricing charges per credit plus serverless compute if using Dagster+ Serverless. That means a trace curation graph with tiny per-file assets can become expensive and operationally noisy. Prefer coarser partitions:
| Bad Dagster asset grain | Better asset grain |
|---|---|
| One asset per trace file | One asset per source/date/tenant partition |
| One op per redaction rule | One redaction op that emits rule-level metrics |
| One materialization per row | Batch materialization with row-level counts and sample IDs |
| Recompute all history for schema changes | Backfill only impacted partitions |
Self-hosted Dagster avoids Dagster+ credit charges but moves the cost into infrastructure and operations. Dagster+ Serverless removes more operations but charges serverless compute by minute. Dagster+ Hybrid avoids Dagster serverless compute charges for the user code path, but the compute still runs in your environment and appears on your AWS/Kubernetes bill.
AWS vs Dagster vs Hugging Face
| Choice | Best when | Watchouts |
|---|---|---|
| AWS-native lake | Regulated enterprise, Bedrock/AgentCore, IAM/KMS, private network, CloudWatch/S3/Glue/Athena already standard | More plumbing, more FinOps surfaces, weaker ML-native collaboration unless datasets are exported |
| Dagster on AWS | Need repeatable curation, backfills, approval gates, schema lineage, eval and dataset materialization | Not a trace UI; asset/ops granularity affects cost; still needs S3/HF/LangSmith/Phoenix destinations |
| Hugging Face Hub/Buckets | Need trace viewing, ML dataset hosting, mounted storage, TRL training, model/dataset collaboration | Private data review burden; bucket S3 API gap; cache duplication if used carelessly |
| LangSmith / Phoenix / Arize / Langfuse / Weave | Need app trace debugging, annotation, eval workbench, run-level feedback | Should not be the only raw vault or legal training-rights ledger |
| Local-only vault | Sensitive R&D, small team, offline mining | Harder fleet reliability metrics, sharing, review workflows, and enterprise audit |
The practical combined architecture is:
S3 = durable enterprise raw vault
Dagster = curation/control-plane lineage
OTel collector = live telemetry router
OpenInference or OTel GenAI = AI semantic-convention choice
Phoenix/LangSmith/Arize/Langfuse/Weave = analysis and eval workbenches
Hugging Face = ML-native datasets, mounted buckets, training runs, trace viewer
Semantic-convention choice is a real architecture decision, not a cosmetic attribute rename. OpenInference is strong when Phoenix/Arize-style rendering and LLM/RAG/tool taxonomy are the priority. OTel-community GenAI semantic conventions are the natural fit for AWS/ADOT/CloudWatch/X-Ray and standard OTel backends. If both workbenches matter, dual-emit or translate and record the conversion version.
Canonical Conversion Pipeline
Use a bronze/silver/gold model.
| Stage | Tables/files | Required fields |
|---|---|---|
| Bronze raw | raw_events, native JSONL/SQLite/CloudWatch/S3 files |
source, source_version, raw_ref, sha256, ingested_at, tenant, privacy classification |
| Silver trace | agent_spans, turns, tool_calls, messages, artifacts |
trace_id, span_id, parent_span_id, session_id, turn_id, tool_call_id, timestamps, status |
| Silver semantic | ai_semantic_spans, protocol_events, retrieval_events |
openinference.span.kind or OTel GenAI gen_ai.*, model/tool/retriever attributes, redacted input/output refs, semantic convention version |
| Gold reliability | eval_results, rollout_metrics, tool_reliability, kb_defects |
scorer version, benchmark/golden-set IDs, pass/fail, failure mode, latency/cost/token metrics |
| Gold learning | sft_examples, preference_pairs, rl_env_cases, skill_candidates |
training eligibility, label provenance, validation proof, split, model/prompt policy version |
Minimal stable IDs:
trace_id
span_id
parent_span_id
session_id
turn_id
message_id
tool_call_id
artifact_id
raw_ref
dataset_example_id
eval_id
rollout_id
policy_version
prompt_version
model_version
agent_version
Query and Mining Patterns
| Goal | Query signal | Output artifact |
|---|---|---|
| Self-improving skills | Repeated successful tool/action patterns followed by accepted final answers | Skill draft with trigger, steps, permissions, negative cases |
| Hard KB questions | User asks same unresolved question; retrieval spans show low overlap; final answer corrected later | KB gap ticket, golden question, retrieval corpus update |
| Agent reliability | Trace/task pass rate by model/tool/prompt/version; retries; human interventions; tool errors | Reliability dashboard and release gate |
| Domain YAML generation | YAML artifacts with validator pass/fail, schema errors, repair count | SFT examples and eval set by schema/failure mode |
| Prompt optimization | Same task across prompt versions or GEPA/DSPy candidates | Prompt candidate leaderboard with cost/reliability |
| Tool-call training | Tool span argument errors and later successful corrected calls | Tool-call SFT rows or preference pairs |
| Cost reduction | Node-level token/cost by workflow; simple tasks still using frontier models | Distillation/fine-tuning candidate list |
Do not train directly from these queries. The query output is a candidate queue. Every learning artifact needs redaction, label provenance, validation, split assignment, and exclusion checks.
Training Dataset Shapes
SFT Prompt-Completion
{
"id": "yaml_sft_000123",
"messages": [
{"role": "system", "content": "Generate only valid policy YAML matching schema v4."},
{"role": "user", "content": "Create a policy for read-only finance analysts..."},
{"role": "assistant", "content": "apiVersion: policy/v4\nkind: AccessPolicy\n..."}
],
"metadata": {
"schema_id": "policy-yaml-v4",
"validator": "policy_yaml_validator@1.8.2",
"validation_status": "pass",
"source_trace_ref": "s3://.../trace_id=...",
"redaction_policy": "enterprise-agent-traces-v3"
}
}
ShareGPT-Style SFT Export
Use this only after curation. Preserve provenance in metadata or a sidecar Parquet table because many ShareGPT loaders ignore unknown fields.
{
"id": "yaml_sharegpt_000123",
"conversations": [
{"from": "system", "value": "Generate only valid policy YAML matching schema v4."},
{"from": "human", "value": "Create a policy for read-only finance analysts..."},
{"from": "gpt", "value": "apiVersion: policy/v4\nkind: AccessPolicy\n..."}
],
"metadata": {
"dataset_example_id": "yaml_sft_000123",
"source_trace_id": "trace_hash",
"validation_status": "pass",
"redaction_policy": "enterprise-agent-traces-v3"
}
}
Preference Pair
{
"prompt": [
{"role": "user", "content": "Generate the IAM condition block for..."}
],
"chosen": [
{"role": "assistant", "content": "Condition:\n StringEquals:\n aws:PrincipalTag/department: finance"}
],
"rejected": [
{"role": "assistant", "content": "Condition:\n StringEquals:\n department: finance"}
],
"metadata": {
"reason": "chosen passes schema and policy simulator; rejected uses invalid condition key",
"judge": "human+validator",
"source_tool_call_id": "tool_..."
}
}
GRPO/RLVR Environment Case
Use GRPO/RLVR only when the reward is genuinely verifiable. Domain YAML is a good fit because schema validators, policy simulators, unit tests, and least-privilege checks can produce repeatable rewards. Open-ended agent helpfulness is not a good first target; the bottleneck is reward design and calibrated evaluation, not the choice between GRPO, DAPO, Dr. GRPO, GSPO, or another GRPO-family variant.
{
"env_id": "policy_yaml_env_v4",
"prompt": "Create a least-privilege YAML policy for...",
"tools": ["schema_validate", "policy_simulate"],
"reward": {
"schema_valid": 0.35,
"policy_simulator_pass": 0.45,
"least_privilege_score": 0.20
},
"metadata": {
"golden_set_id": "policy_yaml_golden_2026_06",
"rollout_id": "rollout_...",
"source_trace_hash": "sha256:..."
}
}
Treat the environment as a package, not just a JSON row. A strong package owns task generation, reset state, hidden labels, tool access, validators, reward aggregation, trace export, and synthetic-data generation. That same package can serve as eval harness, reward source, and curriculum generator.
Tracing Formats vs Training Formats
Tracing formats and training formats have different jobs.
| Question | Tracing answer | Training answer |
|---|---|---|
| What happened? | OTel/OpenInference/AWS GenAI span tree | Not the primary purpose |
| What should the model imitate? | Candidate signal only | SFT/chat/prompt-completion row |
| What should the model prefer? | Eval or human-feedback event | Preference pair: prompt, chosen, rejected |
| What should the policy optimize? | Rollout spans plus reward/eval events | Prompt-only RL/GRPO/RLVR environment case |
| What should never be learned? | Redaction/safety/policy spans | Exclusion list and dataset filter |
| Why did it fail? | Tool/retriever/model/evaluator spans | Failure-mode label, not necessarily training text |
The hard edge is loss. A trace records many things that should not be predicted by the model: user secrets, retrieved documents, tool observations, evaluator judgments, policy-denial reasons, internal IDs, and sometimes bad intermediate outputs. A training row decides which tokens receive loss and which tokens are context only. That is why a trace-to-training converter must emit both:
- a training example in the target library/model format; and
- a sidecar provenance row with
trace_id,span_id,tool_call_id, validation result, redaction policy, evaluator version, and split.
Training Format Families
| Format family | Typical fields | Good for | Libraries / models |
|---|---|---|---|
| Raw text / language modeling | text |
Continued pretraining, domain language adaptation | TRL SFTTrainer language modeling, LLaMA-Factory pretraining, Axolotl pretraining, Unsloth continued pretraining |
| Alpaca / instruction | instruction, input, output, optional history |
Single-turn or simple instruction tuning | LLaMA-Factory Alpaca, Axolotl instruction datasets, Unsloth Alpaca-style notebooks |
| OpenAI / ChatML messages | messages: [{role, content}] |
Chat SFT and modern tokenizer chat templates | TRL conversational, Axolotl default keys, LLaMA-Factory OpenAI-format ShareGPT subset |
| ShareGPT | conversations: [{from, value}] |
Multi-turn chat SFT, legacy/local training recipes, some tool-use rows | Axolotl, LLaMA-Factory, Unsloth via standardize_sharegpt |
| Prompt-completion | prompt, completion |
Format compliance, domain YAML generation, completion-only loss | TRL SFT prompt-completion, many hosted fine-tune APIs |
| Preference / DPO | prompt, chosen, rejected |
Style/policy/tool-arg preference, DPO/ORPO/reward modeling | TRL DPO/ORPO-style trainers, LLaMA-Factory preference, Axolotl RLHF |
| KTO / unpaired preference | prompt/completion plus label, or response plus boolean tag |
Feedback when no paired rejected answer exists | TRL unpaired preference/KTO, LLaMA-Factory KTO |
| Prompt-only RL | prompt plus environment/reward config |
GRPO/RLVR, verifiable rewards, tool-use environments | TRL GRPOTrainer, Prime/Verifiers, Axolotl GRPO, AgentCore RL Toolkit |
| Stepwise supervision | prompt plus step labels/scores | Process supervision, verifier training, multi-step reliability | TRL PRM/stepwise supervision, custom verifier pipelines |
| Multimodal chat | messages plus images/videos/audio or content parts |
VLM/tool/computer-use training | TRL VLM, LLaMA-Factory multimodal, Axolotl multimodal |
Model-Family and Architecture Edges
Training format is not only a library choice. It depends on the model’s native chat and tool format.
| Edge | Why it matters | Practical rule |
|---|---|---|
| Chat template | The tokenizer turns messages into model-specific tokens. Llama, Qwen, Gemma, Phi, DeepSeek, GLM, GPT-OSS, and multimodal models can differ materially. |
Always serialize with the target model tokenizer’s chat template or a library-vetted template; do not assume ShareGPT text is enough. |
| Loss masking | Some rows should train only assistant/completion tokens, not user prompts, retrieved docs, or tool observations. | Record loss_target=assistant_only, completion_only, last_assistant_only, or all_tokens in the dataset manifest. |
| Tool-call serialization | Tool calls may be native JSON, OpenAI-style tool_calls, ShareGPT function_call/observation, XML-ish tags, or model-specific templates. |
Convert from canonical tool_calls table into the target model’s known tool template; validate by round-tripping through inference. |
| Reasoning traces | Some models expose summaries, hidden reasoning, or <think>-style text; training on the wrong field can teach brittle artifacts or leak policy-sensitive content. |
Separate assistant_visible, reasoning_summary, and hidden_or_unavailable; train only on approved visible or deliberately curated reasoning data. |
| Multimodal placeholders | VLMs often require the number of image/video/audio placeholders in text to match sidecar media arrays. | Keep media refs in artifacts; generate model-specific content parts/placeholders at export time. |
| Base vs instruct model | Base models expect raw text continuation; instruct/chat models expect role-formatted turns. | Continued pretraining uses text; instruction tuning uses chat/instruction templates; do not mix without a deliberate curriculum. |
| MoE vs dense | The JSON format may be the same, but sequence length, packing, routing stability, and batch economics differ. | Treat architecture as a training-config choice, not a schema change; keep sequence length and packing metadata. |
| Hosted API vs open weights | Hosted APIs may require provider-specific JSONL; open-weight stacks usually accept flexible datasets plus templates. | Keep canonical gold tables provider-neutral; emit provider/library-specific exports late. |
Translation Pipeline
Use a canonical intermediate representation, not direct trace-to-ShareGPT conversion.
raw trace
-> canonical span/message/tool/artifact tables
-> candidate selector
-> redaction and exclusion filters
-> label/eval attachment
-> task-specific training IR
-> library/model-family export
-> tokenizer/template smoke test
-> small overfit test
-> eval gate
The training IR should look like this before any library-specific export:
{
"dataset_example_id": "yaml_000123",
"task_type": "sft_prompt_completion",
"messages": [
{"role": "system", "content_ref": "redacted_ref_system"},
{"role": "user", "content_ref": "redacted_ref_user"},
{"role": "assistant", "content_ref": "redacted_ref_answer", "loss": true}
],
"tool_calls": [
{
"tool_call_id": "tool_abc",
"name": "schema_validate",
"arguments_ref": "redacted_ref_args",
"result_ref": "redacted_ref_result",
"loss": false
}
],
"labels": {
"validation_status": "pass",
"failure_mode": null,
"reward": 1.0
},
"provenance": {
"trace_id": "trace_hash",
"span_ids": ["span_hash_1", "span_hash_2"],
"redaction_policy": "enterprise-agent-traces-v3",
"split": "train"
}
}
Then export late:
| Target | Export transform |
|---|---|
| TRL SFT | messages or prompt/completion; choose language modeling vs prompt-completion deliberately |
| TRL DPO | prompt, chosen, rejected; prefer explicit prompt |
| TRL GRPO/RLVR | prompt plus reward/verifier environment config |
| Axolotl | OpenAI messages by default, or ShareGPT/Alpaca with field_messages, mappings, chat template, and masking |
| LLaMA-Factory | dataset_info.json mapping for Alpaca, ShareGPT, OpenAI-format subset, preference, KTO, or multimodal |
| Unsloth | ChatML/OpenAI-style messages after standardize_sharegpt if needed; apply model-specific chat template |
| Hosted fine-tune API | Provider JSONL, usually chat or prompt-completion; tool-call support must be checked per model/API version |
Hard Edges and Failure Modes
| Failure | Cause | Prevention |
|---|---|---|
| Training on user prompts | Flattened trace into text with no loss mask | Use assistant-only or completion-only masking |
| Training on tool observations | Treating tool result as assistant target | Mark tool observations as context/no-loss unless the model is supposed to emit that format |
| Broken tool calling | Exported generic JSON that does not match model native tool template | Use model-family chat template and tool-call smoke tests |
| Lost provenance | ShareGPT export drops trace/span/tool IDs | Keep sidecar Parquet or metadata manifest keyed by dataset_example_id |
| Bad DPO pairs | Chosen/rejected do not share the same prompt or differ for irrelevant reasons | Build pairs from same turn/task and attach reason labels |
| RL reward leakage | Prompt contains the answer or validator output | Separate prompt, tool observations, reward function, and hidden labels |
| Multimodal mismatch | Placeholder count differs from media refs | Validate content parts/placeholders before training |
| Incompatible model family | Dataset serialized for ChatML but model expects Llama/Qwen/Gemma-specific template | Tokenizer/template smoke test before full run |
| Overfitting tiny examples | Domain YAML set is too small or duplicated | Deduplicate by semantic hash; keep held-out golden set; run small overfit only as sanity check |
Recommendation for Our Corpus
The corpus should standardize on:
- Canonical trace tables for evidence: raw events, spans, turns, messages, tool calls, artifacts, evals, and rollouts.
- Canonical training IR for curation: task type, role messages, loss mask, labels, rewards, validation proofs, provenance.
- Late exports for each training stack: TRL, Axolotl, LLaMA-Factory, Unsloth, hosted APIs, or RL environment runners.
That gives us portability. A YAML-generation example can become TRL prompt-completion today, ShareGPT/OpenAI chat tomorrow, or a GRPO verifier environment later without losing why the example was selected or which trace proved it worked.
For VLM, omni, video/audio, VLA, MoE, and multimodal MoE models, use the separate architecture map: Complex Model Fine-Tuning Formats: VLM, Omni, MoE, and Architecture-Specific Limits 2026. The short rule is: keep media artifacts and model-family processor requirements in the canonical training IR, then export late. A plain ShareGPT or ChatML row is not enough for complex model families.
Recommendation
- Standardize on OTel for causality and explicitly choose an AI semantic convention. Use OpenInference for Phoenix/Arize-first workflows, OTel GenAI for AWS/ADOT and standard OTel backends, or a documented translation layer when both are required. Use native raw logs as evidence and curated datasets as learning artifacts.
- Use AWS S3 as the regulated raw vault when Bedrock/AgentCore is involved. Keep CloudWatch hot and sampled unless full-content logs are legally required there.
- Use Dagster for curation lineage, not for trace storage. Model each redaction, conversion, eval, review, and dataset emission as partitioned assets.
- Use Hugging Face for ML-native datasets and trace review after redaction. Upload raw local traces only to private repos/buckets; publish only curated redacted datasets.
- Export to multiple consumers. Phoenix/LangSmith/Arize/Langfuse/Weave for debugging and evals; S3/warehouse for audit and analytics; HF datasets for training and benchmark sharing.
- Treat training as a separate approval workflow. A trace that is useful for debugging is not automatically legal, safe, or balanced training data.
Open Gaps
- Hugging Face’s trace viewer creates a useful ecosystem standard for local agent JSONL, but it is not an OTel/OpenInference replacement.
- HF buckets are promising for mounted ML storage, but lack S3 API compatibility today, so AWS-native lakes still need native S3 paths.
- Dagster cost behavior pushes teams toward coarse, partitioned assets rather than per-row trace DAGs.
- Bedrock/CloudWatch costs need workload-specific modeling; the right answer changes if prompts/tool bodies are logged, sampled, compressed, or stored only as encrypted refs.
- The highest-value future experiment is to implement one verified converter: Claude/Codex/Strands/Bedrock raw records -> OTel/OpenInference spans -> Parquet tables -> HF SFT/preference/eval datasets, with redaction proofs.
Sources
- Amazon Bedrock model invocation logging: https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html
- Amazon Bedrock monitoring overview: https://docs.aws.amazon.com/bedrock/latest/userguide/monitoring.html
- Prometheus OTLP metrics ingestion: https://prometheus.io/docs/guides/opentelemetry/
- Prometheus remote write specification: https://prometheus.io/docs/specs/prw/remote_write_spec/
- OpenTelemetry Collector components and connectors: https://opentelemetry.io/docs/collector/components/connector/
- OpenTelemetry Collector transforming telemetry: https://opentelemetry.io/docs/collector/transforming-telemetry/
- OpenTelemetry metrics data model: https://opentelemetry.io/docs/reference/specification/metrics/data-model/
- AWS CloudWatch pricing: https://aws.amazon.com/cloudwatch/pricing/
- AWS S3 pricing: https://aws.amazon.com/s3/pricing/
- AWS Data Firehose pricing: https://aws.amazon.com/kinesis/data-firehose/pricing/