trodo-cli 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -9
- package/lib/args.js +1 -1
- package/lib/commands/agents.js +8 -1
- package/lib/commands/api.js +37 -0
- package/lib/commands/auth.js +67 -9
- package/lib/commands/conversations.js +49 -0
- package/lib/commands/datasets.js +12 -4
- package/lib/commands/evals.js +265 -1
- package/lib/commands/issues.js +40 -0
- package/lib/commands/prompts.js +125 -0
- package/lib/commands/runs.js +90 -13
- package/lib/commands/setup.js +34 -0
- package/lib/commands/spans.js +38 -0
- package/lib/commands/traces.js +70 -4
- package/lib/commands/users.js +14 -0
- package/lib/common.js +69 -0
- package/lib/config.js +47 -6
- package/lib/http.js +26 -7
- package/lib/main.js +63 -21
- package/lib/output.js +12 -1
- package/package.json +3 -2
- package/skills/trodo/SKILL.md +138 -0
- package/skills/trodo-datasets/SKILL.md +116 -0
package/lib/main.js
CHANGED
|
@@ -9,31 +9,65 @@ const { ApiError } = require('./http');
|
|
|
9
9
|
|
|
10
10
|
const pkg = require('../package.json');
|
|
11
11
|
|
|
12
|
-
const HELP = `trodo ${pkg.version} — traces, datasets and agents from the terminal
|
|
12
|
+
const HELP = `trodo ${pkg.version} — traces, evals, datasets, prompts and agents from the terminal
|
|
13
13
|
|
|
14
14
|
trodo login [--url https://api.trodo.ai] [--no-browser] sign in through the app
|
|
15
15
|
trodo login --key trodo_mk_… or with a key (CI)
|
|
16
|
-
trodo whoami
|
|
16
|
+
trodo whoami
|
|
17
|
+
trodo teams the teams this terminal is signed in to
|
|
18
|
+
trodo switch TEAM use another one (login adds teams; --team T for one command)
|
|
19
|
+
trodo logout [TEAM] [--all]
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
trodo traces count [filter]
|
|
20
|
-
trodo traces
|
|
21
|
-
trodo
|
|
22
|
-
trodo
|
|
21
|
+
Traces
|
|
22
|
+
trodo traces count [filter] how many runs / spans / conversations / verdicts match
|
|
23
|
+
trodo traces stats [filter] [--compare] errors, latency, tokens, cost, feedback, evals, by agent
|
|
24
|
+
trodo traces agents | fields | values FIELD what --agent and --where can name
|
|
25
|
+
trodo traces export [filter] [--include-trace] [--format trodo|openai|dpo] [--target output|expected]
|
|
26
|
+
[-o file | --dir DIR] JSONL, or one JSON file per run / span / conversation
|
|
27
|
+
trodo runs list [filter] [--limit 50] [--offset N]
|
|
28
|
+
trodo runs search TEXT runs whose input, output or spans mention TEXT
|
|
29
|
+
trodo runs get RUN_ID [--tree] the run, spans, messages, feedback, evaluations
|
|
30
|
+
trodo runs tree RUN_ID the span tree
|
|
31
|
+
trodo runs feedback RUN_ID [--thumbs up|down] [--rating 1-5] [--comment TEXT]
|
|
32
|
+
trodo spans list [filter] | search TEXT | get SPAN_ID
|
|
33
|
+
trodo conversations list [filter] [--search TEXT] | get ID [--messages] (alias: threads)
|
|
34
|
+
trodo users get DISTINCT_ID one user's runs, cost, evals and feedback
|
|
23
35
|
|
|
36
|
+
Evals
|
|
37
|
+
trodo evals list | get EVAL names, steps (STEP.FIELD), 30-day stats
|
|
38
|
+
trodo evals explain EVAL [--table] what it checks, each step, answers and options, outcomes, filters
|
|
39
|
+
trodo evals steps EVAL [--since 30d] [--table] the paths verdicts took through the steps, with outcomes
|
|
40
|
+
trodo evals verdicts EVAL [--failed|--passed] [--since 7d] [--version N]
|
|
41
|
+
trodo evals verdicts --run ID | --span ID | --conversation ID
|
|
42
|
+
trodo evals verdict VERDICT_ID every step and why
|
|
43
|
+
trodo evals mark VERDICT_ID --right | --wrong --should pass|fail --reason TEXT
|
|
44
|
+
trodo evals queue [--eval EVAL] | review ITEM_ID | grade ITEM_ID CHOICE verdicts waiting on a person
|
|
45
|
+
|
|
46
|
+
Datasets
|
|
24
47
|
trodo datasets list | get DATASET | versions DATASET
|
|
25
|
-
trodo datasets create NAME [--kind runs|spans|conversations|verdicts [filter] [--live] [--include-trace]]
|
|
48
|
+
trodo datasets create NAME [-f rows.jsonl] [--kind runs|spans|conversations|verdicts [filter] [--live] [--include-trace]]
|
|
26
49
|
trodo datasets add DATASET --kind KIND [filter] [--live] [--include-trace]
|
|
27
|
-
trodo datasets append DATASET [-f rows.jsonl]
|
|
50
|
+
trodo datasets append DATASET [-f rows.jsonl] {input, output?, expected?} or {run_id}/{span_id}/{conversation_id} lines
|
|
28
51
|
trodo datasets update DATASET [-f updates.jsonl] {id, expected?, output?, metadata?} lines, one version
|
|
29
52
|
trodo datasets export DATASET [--rows passed|failed|expected|no-expected|marked-wrong|all]
|
|
30
53
|
[--eval NAME] [--min-score N] [--format trodo|openai|dpo] [--target ...] [--version N] [-o file]
|
|
31
54
|
|
|
32
|
-
|
|
55
|
+
Prompts
|
|
56
|
+
trodo prompts list | get PROMPT [--version N | --label L] | versions PROMPT
|
|
57
|
+
trodo prompts pull PROMPT [--label production] [-o prompt.json]
|
|
58
|
+
trodo prompts push PROMPT -f prompt.json [--message "why"] [--label staging]
|
|
59
|
+
trodo prompts label PROMPT VERSION LABEL [--remove]
|
|
60
|
+
|
|
61
|
+
Issues and agents
|
|
62
|
+
trodo issues list [--status open,regression] | get ID | failures ID | close ID | reopen ID
|
|
63
|
+
trodo agents list | get AGENT | executions AGENT | execution ID
|
|
33
64
|
trodo agents run AGENT [--input JSON] [--wait]
|
|
34
65
|
|
|
35
|
-
|
|
36
|
-
--
|
|
66
|
+
trodo api GET|POST|PATCH|DELETE /path [--param k=v] [--data JSON] any /api/v1 route
|
|
67
|
+
trodo setup claude [--global] install the Trodo skills for Claude Code (or --dir DIR)
|
|
68
|
+
|
|
69
|
+
Filter (traces, runs, spans, conversations, datasets create/add):
|
|
70
|
+
--kind spans|runs|conversations|verdicts (traces and datasets; default runs)
|
|
37
71
|
--since 24h|7d|30d|3m|today or --from DATE --to DATE (default 7d)
|
|
38
72
|
--agent NAME repeatable
|
|
39
73
|
--where "status=error" = != ~ > >= < <= on any Traces property:
|
|
@@ -50,25 +84,33 @@ Training data:
|
|
|
50
84
|
trodo datasets export "Good refunds" --rows passed --format openai --target output -o train.jsonl
|
|
51
85
|
firectl dataset create good-refunds train.jsonl
|
|
52
86
|
|
|
53
|
-
Auth: TRODO_API_KEY / TRODO_API_URL, or \`trodo login\` (~/.trodo/config.json).
|
|
87
|
+
Auth: TRODO_API_KEY / TRODO_API_URL, or \`trodo login\` (~/.trodo/config.json, one key per team).
|
|
54
88
|
A key is a Trodo API key (Settings → MCP); it acts as the person who made it, on its team, with its scopes.
|
|
55
|
-
|
|
89
|
+
The CLI reads everything and only adds: nothing it does deletes, archives or replaces data.
|
|
90
|
+
Output: JSON by default; --table for a table, --csv for CSV; lists take --all [--max-items N]. Exit codes: 0 ok, 1 API error, 2 usage.
|
|
56
91
|
`;
|
|
57
92
|
|
|
58
93
|
const COMMANDS = {
|
|
59
|
-
login: ['auth', 'login'], whoami: ['auth', 'whoami'], logout: ['auth', 'logout'],
|
|
94
|
+
login: ['auth', 'login'], whoami: ['auth', 'whoami'], logout: ['auth', 'logout'], api: ['api', 'call'], setup: ['setup', 'setup'], teams: ['auth', 'teams'], switch: ['auth', 'switch'],
|
|
60
95
|
};
|
|
96
|
+
const ALIASES = { threads: 'conversations', thread: 'conversations', run: 'runs', span: 'spans', dataset: 'datasets', prompt: 'prompts', issue: 'issues', agent: 'agents', eval: 'evals', trace: 'traces' };
|
|
61
97
|
const GROUPS = {
|
|
62
|
-
evals: ['list'],
|
|
63
|
-
traces: ['count', 'export'],
|
|
64
|
-
runs: ['list', 'get'],
|
|
65
|
-
|
|
66
|
-
|
|
98
|
+
evals: ['list', 'get', 'explain', 'steps', 'verdicts', 'verdict', 'mark', 'queue', 'review', 'grade'],
|
|
99
|
+
traces: ['count', 'stats', 'export', 'agents', 'fields', 'values'],
|
|
100
|
+
runs: ['list', 'search', 'get', 'tree', 'feedback'],
|
|
101
|
+
spans: ['list', 'search', 'get'],
|
|
102
|
+
conversations: ['list', 'get'],
|
|
103
|
+
datasets: ['list', 'get', 'create', 'add', 'append', 'update', 'export', 'rows', 'download', 'versions'],
|
|
104
|
+
prompts: ['list', 'get', 'versions', 'pull', 'push', 'label'],
|
|
105
|
+
issues: ['list', 'get', 'failures', 'close', 'reopen'],
|
|
106
|
+
agents: ['list', 'get', 'run', 'executions', 'execution'],
|
|
107
|
+
users: ['get'],
|
|
67
108
|
};
|
|
68
109
|
|
|
69
110
|
async function main(argv) {
|
|
70
111
|
const { flags, positional } = parse(argv);
|
|
71
|
-
const [
|
|
112
|
+
const [cmd0, sub, ...rest] = positional;
|
|
113
|
+
const cmd = ALIASES[cmd0] || cmd0;
|
|
72
114
|
// `trodo --version` alone is the CLI's version; `datasets export X --version 3` is a dataset's.
|
|
73
115
|
if (flags.version === true && !cmd) { process.stdout.write(`${pkg.version}\n`); return 0; }
|
|
74
116
|
if (!cmd || flags.help || cmd === 'help') { process.stdout.write(HELP); return 0; }
|
package/lib/output.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
const fs = require('fs');
|
|
8
8
|
|
|
9
9
|
function print(data, flags = {}, columns = null) {
|
|
10
|
+
if (flags.csv && Array.isArray(data)) return process.stdout.write(csv(data, columns));
|
|
10
11
|
if (flags.table && columns && Array.isArray(data)) return process.stdout.write(table(data, columns));
|
|
11
12
|
const pretty = process.stdout.isTTY && !flags.json;
|
|
12
13
|
return process.stdout.write(`${JSON.stringify(data, null, pretty ? 2 : 0)}\n`);
|
|
@@ -20,6 +21,16 @@ function table(rows, columns) {
|
|
|
20
21
|
return `${[line(columns.map(([, label]) => label)), ...rows.map((r) => line(columns.map(([key]) => cell(r[key]))))].join('\n')}\n`;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
/** RFC 4180 CSV: the table's columns when the command has them, every key otherwise. */
|
|
25
|
+
function csv(rows, columns) {
|
|
26
|
+
const keys = columns ? columns.map(([k]) => k) : [...new Set(rows.flatMap((r) => (r && typeof r === 'object' ? Object.keys(r) : [])))];
|
|
27
|
+
const cell = (v) => {
|
|
28
|
+
const s = v == null ? '' : typeof v === 'object' ? JSON.stringify(v) : String(v);
|
|
29
|
+
return /[",\r\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
|
|
30
|
+
};
|
|
31
|
+
return `${[keys.join(','), ...rows.map((r) => keys.map((k) => cell(r[k])).join(','))].join('\n')}\n`;
|
|
32
|
+
}
|
|
33
|
+
|
|
23
34
|
/** Write lines to --out or stdout; returns { write(obj), close() }. */
|
|
24
35
|
function sink(out) {
|
|
25
36
|
const stream = out ? fs.createWriteStream(out) : process.stdout;
|
|
@@ -47,4 +58,4 @@ async function readRows(file) {
|
|
|
47
58
|
});
|
|
48
59
|
}
|
|
49
60
|
|
|
50
|
-
module.exports = { print, table, sink, readRows };
|
|
61
|
+
module.exports = { print, table, csv, sink, readRows };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trodo-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Trodo from the terminal:
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Trodo from the terminal: traces, evals, datasets, prompts, issues and agents for people, scripts and coding agents",
|
|
5
5
|
"bin": {
|
|
6
6
|
"trodo": "bin/trodo.js"
|
|
7
7
|
},
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"bin/",
|
|
11
11
|
"lib/",
|
|
12
|
+
"skills/",
|
|
12
13
|
"README.md"
|
|
13
14
|
],
|
|
14
15
|
"scripts": {
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: trodo
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
cli_version: ">=0.3.0"
|
|
5
|
+
last_updated: 2026-11-03
|
|
6
|
+
description: >-
|
|
7
|
+
Read and act on an AI agent's production traces in Trodo with the `trodo` CLI:
|
|
8
|
+
find failing runs, read a run's span tree or a whole conversation, see why an
|
|
9
|
+
eval failed step by step, check traffic stats against last week, triage and
|
|
10
|
+
close issues, pull and push prompt versions, give feedback, and turn traces
|
|
11
|
+
into datasets and fine-tuning files. Use for "why did this run fail", "what
|
|
12
|
+
broke since yesterday", "show me the conversation", "which evals fail most",
|
|
13
|
+
"fix this Trodo issue", "update the prompt", "build a dataset from my traces".
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Trodo from the terminal
|
|
17
|
+
|
|
18
|
+
Every command prints JSON (pipe it to `jq`), `--table` for a person, `--csv` for a
|
|
19
|
+
sheet. Exit codes: 0 ok, 1 the API said no, 2 a usage mistake (the message says which).
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm i -g trodo-cli
|
|
25
|
+
trodo login # opens the app: check the code, choose the team, Connect
|
|
26
|
+
trodo whoami
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Without a browser (CI): `TRODO_API_KEY=trodo_mk_…` from Settings → MCP.
|
|
30
|
+
|
|
31
|
+
Everything is per team. `trodo teams` lists the teams this terminal is signed in
|
|
32
|
+
to, `trodo switch TEAM` changes the current one, `--team TEAM` picks one for a
|
|
33
|
+
single command. Check `trodo whoami` before writing anything.
|
|
34
|
+
|
|
35
|
+
## Understand the evals first
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
trodo evals list --table
|
|
39
|
+
trodo evals explain "EVAL" --table # what it checks, each step, answer options, outcomes, working filters
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Read `explain` before writing an `--eval` filter. A decision-model question with
|
|
43
|
+
levels answers a weighted score (1.8 is mostly the top level): use a threshold
|
|
44
|
+
such as `STEP.field<1.5`, never `<2`. A filter matches a unit when any of its
|
|
45
|
+
verdicts matches, so a unit re-scored later can appear under both failed and passed.
|
|
46
|
+
|
|
47
|
+
## Find what went wrong
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
trodo traces stats --since 24h --compare # errors, latency, cost, evals vs the day before
|
|
51
|
+
trodo runs list --since 24h --where "status=error" --table
|
|
52
|
+
trodo runs list --eval "any:failed" --agent support --table
|
|
53
|
+
trodo issues list --status open,regression --table
|
|
54
|
+
trodo runs search "refund for order 4821" # free text over inputs, outputs and spans
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The filter is the Traces page's: `--since 24h|7d|30d`, `--agent NAME`,
|
|
58
|
+
`--where "field op value"` (`= != ~ > >= < <=` on any property:
|
|
59
|
+
`total_cost>0.05`, `span.model~gpt-4o`, `metadata.tier=pro`) and
|
|
60
|
+
`--eval "NAME:COND"` (`failed`, `passed`, `score<0.5`, `reason=CODE`,
|
|
61
|
+
`STEP.FIELD=value`; `trodo evals list` names the evals and their steps).
|
|
62
|
+
`trodo traces agents`, `trodo traces fields` and `trodo traces values FIELD`
|
|
63
|
+
say what `--agent` and `--where` can name.
|
|
64
|
+
|
|
65
|
+
## Read one
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
trodo runs tree RUN_ID # the span tree: names, models, time, tokens, errors
|
|
69
|
+
trodo runs get RUN_ID # everything: spans, messages, feedback, evaluations
|
|
70
|
+
trodo spans get SPAN_ID # one span's full input and output
|
|
71
|
+
trodo conversations get ID --messages # the thread as user / assistant turns
|
|
72
|
+
trodo evals verdicts --run RUN_ID # every eval's verdict on it
|
|
73
|
+
trodo evals verdict VERDICT_ID # each step the eval took and why
|
|
74
|
+
trodo evals steps EVAL --table # which step decides most failures
|
|
75
|
+
trodo users get DISTINCT_ID # one user's runs, cost, evals and feedback
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Read the deepest failing span before deciding the cause: what failed above it is
|
|
79
|
+
what the user saw, not why.
|
|
80
|
+
|
|
81
|
+
## Fix and verify
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
trodo issues get ID # root cause, evidence, timeline
|
|
85
|
+
trodo issues failures ID # recorded inputs to replay against the fix
|
|
86
|
+
trodo traces count --since 1h --eval "NAME:failed" # after the fix ships: should fall to 0
|
|
87
|
+
trodo issues close ID # a new failure reopens it as a regression
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Prompts
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
trodo prompts pull support-triage --label production -o prompt.json
|
|
94
|
+
# edit prompt.json
|
|
95
|
+
trodo prompts push support-triage -f prompt.json --message "why" --label staging
|
|
96
|
+
trodo prompts label support-triage 5 production # agents fetching by label switch on their next call
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Moving `production` changes what live agents run. Do it only when asked.
|
|
100
|
+
|
|
101
|
+
## Feedback
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
trodo runs feedback RUN_ID --thumbs down --comment "quoted the wrong plan"
|
|
105
|
+
trodo evals mark VERDICT_ID --wrong --should pass --reason "the refund was within policy"
|
|
106
|
+
trodo evals queue --table ; trodo evals grade ITEM_ID CHOICE
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Datasets and training data
|
|
110
|
+
|
|
111
|
+
Do the thinking in your own script: export with the filter, process the JSONL
|
|
112
|
+
locally (each line has input, output, and every verdict with each step's
|
|
113
|
+
answer), then write rows back with `datasets create NAME -f rows.jsonl` or
|
|
114
|
+
`datasets update`. Nothing of yours runs on Trodo.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
trodo traces export --kind spans --eval any:passed --eval any:not-failed --format openai -o sft.jsonl
|
|
118
|
+
trodo traces export --kind runs --since 7d --include-trace --dir ./runs # one JSON file per run
|
|
119
|
+
trodo datasets create "Refund failures" --kind runs --eval "Refund policy:failed" --include-trace
|
|
120
|
+
trodo datasets rows "Refund failures" -o rows.jsonl
|
|
121
|
+
# write better answers: {"id": "...", "expected": "..."} per line
|
|
122
|
+
trodo datasets update "Refund failures" -f updates.jsonl
|
|
123
|
+
trodo datasets export "Refund failures" --rows expected --format openai --target expected -o train.jsonl
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`trodo datasets append NAME -f rows.jsonl` takes `{"input": "…", "output": "…", "expected": "…"}`
|
|
127
|
+
lines, or `{"run_id": "…"}` / `{"span_id": "…"}` / `{"conversation_id": "…"}` to copy traffic.
|
|
128
|
+
|
|
129
|
+
## What the CLI will not do
|
|
130
|
+
|
|
131
|
+
It reads everything and only adds. Nothing deletes, archives, replaces or
|
|
132
|
+
reverts data, and traces cannot be changed. If a task needs that, tell the
|
|
133
|
+
person to do it in the app.
|
|
134
|
+
|
|
135
|
+
## Anything else
|
|
136
|
+
|
|
137
|
+
`trodo api GET /runs/conversations --param q=alice` calls any `/api/v1` route with the
|
|
138
|
+
signed-in key. `trodo help` lists every command.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: trodo-datasets
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
cli_version: ">=0.2.0"
|
|
5
|
+
last_updated: 2026-11-03
|
|
6
|
+
description: >-
|
|
7
|
+
Turn an agent's production traces into datasets and fine-tuning files with the
|
|
8
|
+
`trodo` CLI: pick traces by what the team's evals said about them (passed,
|
|
9
|
+
failed, a score, one step's answer), keep whole runs with their span trees,
|
|
10
|
+
process rows locally, write Expected back, and export OpenAI / Fireworks /
|
|
11
|
+
Together chat JSONL or DPO pairs. Use for "build a training set from my
|
|
12
|
+
traces", "export the runs that passed", "label these rows", "make a dataset of
|
|
13
|
+
failures", "fine-tune on what went well", and for running a Trodo labeling agent.
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Trodo datasets from the terminal
|
|
17
|
+
|
|
18
|
+
The team's evals already say which traces went well. A supervised fine-tune
|
|
19
|
+
wants exactly those: their own Output is the target, nothing to label. Rows
|
|
20
|
+
that failed need a better answer first (Expected). Work in that order.
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm i -g trodo-cli
|
|
26
|
+
trodo login # opens the app: check the code, choose the team, Connect
|
|
27
|
+
trodo whoami
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
In CI or anywhere without a browser: `TRODO_API_KEY=trodo_mk_…` (Settings → MCP).
|
|
31
|
+
Every command prints JSON; add `--table` to read it yourself.
|
|
32
|
+
|
|
33
|
+
## 1. Know the evals
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
trodo evals list --table
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`--eval "NAME:COND"` takes an eval's name (or any unique part of it, or `any`):
|
|
40
|
+
`failed`, `passed`, `not-failed`, `marked-wrong`, `not-marked-wrong`,
|
|
41
|
+
`marked-right`, `score<0.5`, `reason=CODE`, or one step's answer
|
|
42
|
+
`STEP.FIELD=value` / `STEP.FIELD<3` (STEP is the step's id or the start of its
|
|
43
|
+
name). Several `--eval` flags AND together. "Passed every eval" is
|
|
44
|
+
`--eval any:passed --eval any:not-failed`. People's corrections count: a
|
|
45
|
+
verdict someone marked wrong is read the other way round.
|
|
46
|
+
|
|
47
|
+
## 2. Look before you pull
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
trodo traces count --kind runs --since 30d --agent support --eval "any:passed" --eval "any:not-failed"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Kinds: `spans` (one model call), `runs` (one task, add `--include-trace` for
|
|
54
|
+
every span), `conversations` (a whole thread), `verdicts` (eval results, for
|
|
55
|
+
training the eval itself). Narrow with `--where "status=error"`,
|
|
56
|
+
`--where "total_cost>0.05"`, `--where "span.model~gpt-4o"`, `--where "metadata.tier=pro"`.
|
|
57
|
+
|
|
58
|
+
## 3a. Straight to a training file
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
trodo traces export --kind spans --since 30d --eval any:passed --eval any:not-failed \
|
|
62
|
+
--format openai --target output -o sft.jsonl
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 3b. Or keep it as a dataset (versioned, shared with the team, labelable)
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
trodo datasets create "Refunds that went well" --kind runs --since 30d \
|
|
69
|
+
--agent support --eval "Refund policy:passed" --include-trace [--live]
|
|
70
|
+
trodo datasets export "Refunds that went well" --rows passed --format openai --target output -o train.jsonl
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`--live` keeps adding new matches every 15 minutes.
|
|
74
|
+
|
|
75
|
+
## 4. Process rows locally, write them back
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
trodo datasets export "Refund failures" > rows.jsonl # each line has its "id"
|
|
79
|
+
python label.py < rows.jsonl > updates.jsonl # your logic: {"id", "expected", "metadata"?}
|
|
80
|
+
trodo datasets update "Refund failures" -f updates.jsonl --label derived --name "Expected from label.py"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
One call is one dataset version (restorable in the app). `--label derived`
|
|
84
|
+
records that a rule wrote Expected, not a person. Add rows with
|
|
85
|
+
`trodo datasets append NAME -f rows.jsonl`: plain rows `{input, output?, expected?}`
|
|
86
|
+
or references `{run_id}` / `{span_id}` / `{conversation_id}` that Trodo fills in.
|
|
87
|
+
|
|
88
|
+
## 5. Or let a Trodo agent label in the product
|
|
89
|
+
|
|
90
|
+
The dataset page's **Label** menu (or asking Lucid) makes a labeling agent:
|
|
91
|
+
models that must agree, a model with your rules, a stronger model rewriting
|
|
92
|
+
failures, or two models compared. Run one from here:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
trodo agents list --table
|
|
96
|
+
trodo agents run "Label Expected where models agree" --wait
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## 6. Train
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
trodo datasets export "Refunds" --rows expected --format openai --target expected -o train.jsonl
|
|
103
|
+
firectl dataset create refunds train.jsonl
|
|
104
|
+
firectl sftj create --base-model accounts/fireworks/models/qwen3-8b --dataset refunds --output-model refunds-v1
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
DPO: `--format dpo` writes Expected as preferred and Output as rejected, for
|
|
108
|
+
rows that have both and differ.
|
|
109
|
+
|
|
110
|
+
## Rules
|
|
111
|
+
|
|
112
|
+
- Count first, then pull with a `--limit`. Exports stream; use `-o file`.
|
|
113
|
+
- Never write Expected from a guess. Expected is a person's answer or the
|
|
114
|
+
output of a rule the team agreed on.
|
|
115
|
+
- The key acts as the person who made it, on one team. A 403 `missing_scope`
|
|
116
|
+
means the key needs that scope; make a new one with `trodo login`.
|