What you need
Three things, and no agent of your own — this page generates the traces it trains on.
That is the whole list through step 5, where you get a dataset file. Two later steps need more, and each says so where it applies: the hosted fine-tune in step 6 needs an OpenAI, Together.AI, or Gemini key (and a paid plan — Free cannot launch one), and pushing to HuggingFace in step 7 needs
pip install huggingface_hub datasets.
You do not need a framework adapter, an LLM API key, litellm, or a running agent to complete steps 1–5.
The one rule that decides whether this works
A dataset row is assembled from a trace’s LLM calls — the rendered prompt that went to the model and the completion that came back. Spans, tool timings, and status are all recorded, but they are not what a training row is made of. So a trace with no LLM call contributes nothing. A build over nothing but such traces returns a 0-row version and an HTTP 200 — it does not raise. If a build ever comes back empty, this is the first thing to check.Why this page emits its own traces instead of running
decimalai demo regression.
The demo seeds a realistic agent in under a second and it is genuinely useful — if what
you want is a populated dashboard to click around in, run it and go look at
Traces. It is the wrong opener here for three
reasons. It hands you rows without ever naming the rule above, which is exactly the
knowledge you need when your own agent’s build comes back empty. It seeds an agent
called [Demo] support-agent, not support-agent. And it already builds a dataset for
you, which deletes step 4 — the step this page exists to teach. Twenty lines that you
run yourself buy the mental model; one command buys a screenshot.1
Emit traces that contain LLM calls
Install the SDK and point it at your workspace:Now generate a small support-agent corpus. Save this as In production you would not write
seed_traces.py and run it:log_llm_call by hand — decimalai.init(openai=True)
or a framework adapter captures the same calls automatically. Writing them out once
makes the mapping visible, and it is the mapping that decides what your training rows
look like:log_tool_call does not put tool messages in the row. A tool message is
emitted only when the LLM call itself reports tool calls, which the framework
adapters capture and the manual log_llm_call does not expose. The rows you build
here are system / user / assistant; the tool still shows on the timeline and
in the manifest. Instrument with an adapter if you want tool-calling trajectories.You should now see: six traces in the workspace, all under the agent name
support-agent. Confirm from the terminal before moving on —
decimalai traces list --limit 6 — or on the
Traces page. If decimalai.init() raised, your key
is missing or wrong; if the script printed but nothing arrives, you dropped the
decimalai.flush(). A 429 Too Many Requests straight after the send is the
per-key rate limiter, not a failure — the ingest already retried and succeeded;
wait a few seconds and list again.2
See what the SDK registered for you
You never declared an agent, a model, or a tool list. The SDK derived all three from
the calls you logged and registered a manifest — the versioned record of what your
agent is, which later becomes the filter your dataset is built from.Open Manifests (or
Agents → support-agent) and
you’ll find one manifest, v1, marked active, with two components: the model
gpt-4o-mini and the tool search_docs.You should now see: exactly one manifest for
support-agent. More than one
means your traces disagreed about the model, the system prompt, or the tool list —
each distinct combination registers its own version, and a dataset built from one
version won’t contain traces from the others.3
Score the traces
Attach a quality score to each trace. Scores show up on each trace’s Evaluation Breakdown and on the
Evaluate page. In a real pipeline the score comes
from a judge rather than a literal — an LLM evaluator, a regex check, a thumbs-down
from a user, a support ticket that got reopened. The shape is the same: a number
between 0 and 1, attached to a trace id.
seed_traces.py already wrote them to
trace_scores.json; push them:4
Build a dataset
Go to Datasets in the sidebar and click + New Dataset:DecimalAI converts each trace into one chat-completion example:The
- Dataset Name —
support-agent SFT - Dataset Type —
Fine-tuning (SFT) - Target Agent —
support-agent - Target Manifest — pick the
v1 (active)row; it shows its trace count - Click Create & Build
keep or repair. There is no
eval-verdict picker in this dialog, by design — compatibility and quality are separate
axes, and this dialog only sets the first one.You land on the dataset detail page with version 1 built:tools block comes from the manifest, so the fine-tuned model learns the tool
surface it will be given at inference time. Its parameters are a placeholder here —
a manual log_tool_call carries a name but no JSON Schema. Drop the tools key if
your trainer validates it.Keep only your best traces.
All six rows are in there, including the answer you scored 0.20. Quality is the
second axis, and the filter that works with SDK-pushed scores is an explicit trace
list — you already have the scores in trace_scores.json:The dashboard’s own quality knob is
Min Eval Score, on the dataset detail
page’s Build new version form — not a verdict picker in the create dialog. It
reads the trace’s aggregate eval_score, which is written by a server-side
Evaluator and not by decimalai.score(). Configure an
evaluator first, or filter by trace id as above.You should now see: a version with a non-zero row count. A 0-row build is
reported as
version_status: "failed" on the API response and as a failed version
in the UI — it is never a silent success. The three causes, in the order they bite:
the traces carry no LLM calls; the agent name on the build doesn’t match the agent
name on the traces; or a quality filter is gating on an eval_score nothing wrote.5
Pull the data
Download the version you just built:The SDK equivalent, if you’d rather stay in Python:
You should now see: a non-empty
training_data.jsonl, one JSON object per line,
each with a messages array. wc -l training_data.jsonl should print the row count
the build reported.6
Launch a hosted fine-tune
From the dataset detail page, click Train:
- Select provider: OpenAI, Together.AI, or Gemini
- Enter credentials: an API key for that provider — this is the first step that needs one
- Configure: base model, training epochs
- Launch
Plan limits: hosted fine-tune launches are metered per plan — Free 0 / Core 2 /
Pro 5 / Enterprise custom (see Pricing). An over-quota launch
returns
429; a launch only counts once it succeeds. On the Free tier the hosted
launcher is unavailable — skip to the next step and train on the file you pulled.7
Or train it yourself
You already have Then use it in any framework:
training_data.jsonl, which is enough for any trainer that reads
chat-format JSONL. To go through HuggingFace Hub instead:- Axolotl
- Unsloth
- TRL
- In-Memory (No File)
8
Deploy and iterate
Point your agent at the fine-tuned model. Because the model name is part of the
manifest, DecimalAI will:
- Detect the manifest change and register a new version
- Generate a compatibility report for existing traces
- Keep evaluating traces from the fine-tuned model
- Let you build the next dataset from the improved outputs
If a build came back empty
An empty build is reported (version_status: "failed", 0 rows) but it does not raise, so
it is easy to walk past. Three causes account for nearly all of them:
The traces have no LLM calls
The traces have no LLM calls
A training row is built from a trace’s LLM calls. A trace that recorded only spans,
only tool timings, or only a status contributes zero rows. Open one trace and check
that its LLM Calls section is non-empty; if it isn’t, the instrumentation never
captured a model call — see the silent no-ops below.
The agent name doesn't match
The agent name doesn't match
The build filters on the manifest’s agent name and, on the by-agent path, on
agent_name directly. support-agent, Support Agent, and [Demo] support-agent are
three different agents, and a mismatch matches nothing without erroring. Run
decimalai traces list and use the name exactly as it prints.A quality filter is gating on a score nothing wrote
A quality filter is gating on a score nothing wrote
min_eval_score and verdict filters read the trace’s aggregate eval_score /
eval_verdict, which are written by server-side Evaluators.
Scores pushed with decimalai.score() are recorded and displayed but do not set them,
so a build gated that way returns 0 rows. Filter by explicit trace_ids instead, or
configure an evaluator first.1. A registry skill is never offered to your agent
1. A registry skill is never offered to your agent
Browsing or previewing a skill on the public registry doesn’t make it routable — you have to adopt it into your org first. Either way works — Install (the Install button, or
router.use("name") in the SDK) creates a linked pointer that tracks the author’s updates, and Fork (the Fork a copy button, or router.fork("name"), or router.install("name") to also write it to disk) creates an editable copy you own. The Skill Router offers both. If you use per-agent assignments, also assign it to the requesting agent. Until you install or fork it, the skill never appears in your agent’s menu, with no warning anywhere.3. The load_skill tool never appears
3. The load_skill tool never appears
The on-demand body loader is opt-in: pass
enable_skill_loader=True to instrument() on the openai_agents or pydantic_ai adapters. On the anthropic adapter there is no tool loop — enable_skill_loader=True there injects the skill menu into system (the offered rung only); full bodies are injected by default once the loader is on (0.12.0+; init(inject_skill_body=False) turns that off), and note enable_load_skill_tool is accepted but dormant. Kill-switch: init(load_skill_tool=False) or DECIMALAI_LOAD_SKILL_TOOL=0.4. An integration flag whose package is missing
4. An integration flag whose package is missing
decimalai.init(langchain=True) (and every other framework flag) logs a warning and continues untraced when the framework package isn’t importable — your agent runs, nothing is recorded. The same applies to DECIMAL_AUTO_TRACE (auto-init warns and skips) and to the raw-provider flags (openai=True etc.), which soft-skip when the matching OpenInference instrumentor is absent. Fix: for a framework flag, install the matching extra, e.g. pip install "decimalai[langchain]"; for a raw-provider flag, install the instrumentor package the startup warning names, e.g. pip install openinference-instrumentation-openai (the [openai] extra covers only the provider SDK, not the instrumentor). Then re-check startup logs.5. Skill injection skips callable instructions and prebuilt prompts
5. Skill injection skips callable instructions and prebuilt prompts
Adapters only inject skills into prompt shapes they can safely rewrite. On
openai_agents, an agent whose instructions is a user-supplied callable is left untouched; on langchain, a prebuilt PromptValue (or any unrecognized prompt shape) passes through unchanged. The agent runs normally — with zero skills injected and no error raised.6. The impact report says 0 traces (or 'first run')
6. The impact report says 0 traces (or 'first run')
The regression check needs two things before it can say anything real: a baseline manifest (recorded automatically on the Action’s first run, or by
decimalai.init() running in production) and ingested traces to measure blast radius against. A fresh workspace legitimately reports “first run — no baseline” and then near-zero affected traces. That’s honesty, not breakage — reports gain weight over days as production trace volume accumulates.You’ve done it
Emitted traces carrying real LLM calls, with no agent and no LLM key
Watched the SDK register the agent’s manifest from those calls
Scored the traces and understood what a score does and does not gate
Built a versioned SFT dataset, then rebuilt it filtered to the good traces
Pulled a non-empty JSONL file ready for any trainer
Closed the loop — a deployed model produces traces for the next iteration
What makes this different
Most platforms stop at evaluation. DecimalAI connects:- Manifest compatibility — training data matches a specific, versioned agent config
- Automatic format conversion — multi-turn, tool-using traces become chat rows, tool calls and results intact
- HuggingFace Hub integration — one step to every open-source trainer
- The loop repeats — each fine-tuned model feeds the next iteration
Next steps
Datasets Guide
Filter strategies, version pinning, and export formats in depth.
Replay Guide
Regenerate training data by replaying historical inputs against the new model.
Evaluations
Configure server-side evaluators so quality filters actually gate a build.
Manifests
How compatibility is computed when you change the agent.