evals 2.4.0 → 2.6.0

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.
@@ -6,15 +6,14 @@ Work through the flow below in order. Installing the AX CLI and Arize skills, au
6
6
 
7
7
  ## Step 0: Welcome and confirm
8
8
 
9
- Greet the user and show the plan, then ask before doing anything:
9
+ Greet the user and show the plan, then ask before doing anything. Send this block as written and nothing else: no added steps, no parentheticals on the ones here (not "browser OAuth", not a folder path), and no preamble about the network check or the approval gate. Both come later in the flow, and explaining them before the user has agreed to anything is noise.
10
10
 
11
11
  ```text
12
12
  Welcome to Arize AX. I'll get you set up with tracing. Here's what I'll do:
13
13
 
14
14
  1. Install the AX CLI and Arize skills
15
15
  2. Create a free Arize AX account or sign you in
16
- 3. Instrument this project or a new app
17
- 4. Capture traces from your app
16
+ 3. Add tracing to an existing app, a new starter app, or this coding agent itself
18
17
 
19
18
  Shall I proceed?
20
19
  ```
@@ -23,6 +22,26 @@ Do not proceed until the user approves.
23
22
 
24
23
  ## Prerequisites
25
24
 
25
+ **Check network access first.** Every step below needs it: the CLI comes from PyPI, and auth and traces go to Arize. Agent sandboxes often block network by default, and it fails as a hang rather than an error:
26
+
27
+ ```bash
28
+ for h in pypi.org registry.npmjs.org api.arize.com app.arize.com; do
29
+ code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 "https://$h")
30
+ [ "$code" != "000" ] && echo "$h ok" || echo "$h BLOCKED"
31
+ done
32
+ ```
33
+
34
+ `000` is a DNS or connect failure — your sandbox, not the user's connection.
35
+
36
+ If anything is blocked, ask your harness to escalate: request network or elevated permissions for the commands that need them, rather than retrying silently or waiting. If escalation is refused or your harness doesn't offer it, stop — with no network this flow cannot complete, so don't retry and don't look for a workaround:
37
+
38
+ ```text
39
+ My sandbox is blocking network access, so I can't install the CLI or reach
40
+ Arize. Restart me with network access enabled and I'll pick this up.
41
+ ```
42
+
43
+ Later in the flow, treat a connection or DNS error from any command the same way: it means network, not authentication, so stop and report rather than re-authenticating or recreating a profile.
44
+
26
45
  The AX CLI must be **arize-ax-cli `0.29.0` or newer** (Step 1 installs the latest) and needs **Python 3.11+** — a hard requirement. If Python is missing, stop and have the user install it from https://www.python.org/downloads/ and re-run. **Node.js 18+ with npx** is optional but installs the Arize skills; without it, don't stop — continue and use the docs paths in Step 6 (the Vercel AI SDK v7 starter needs Node.js 22+).
27
46
 
28
47
  ## Step 1: Install or update the AX CLI and Arize skills
@@ -35,7 +54,7 @@ pipx install arize-ax-cli # already installed: pipx upgrade arize-ax-cli
35
54
  python3 -m pip install --upgrade arize-ax-cli
36
55
  ```
37
56
 
38
- If npx is available, install the Arize agent skills; otherwise skip and continue (Step 6 falls back to the docs paths):
57
+ If npx is available, install the Arize agent skills; otherwise skip and continue (Step 6 falls back to the docs paths). If the install errors or doesn't finish promptly, skip it and continue rather than waiting — the same fallback applies:
39
58
 
40
59
  ```bash
41
60
  npx skills add Arize-ai/arize-skills --skill '*' --yes
@@ -72,7 +91,7 @@ If a `default` profile exists but the probe failed, it's signed out or expired,
72
91
  ax profiles create default --auth-method api-key --api-key "$ARIZE_API_KEY"
73
92
  ```
74
93
 
75
- Reuse this key throughout — do **not** create a new one in Step 6.
94
+ Reuse this key throughout — do **not** create a new one in Step 6. Only if the probe passes, though: a stale or wrong-org `ARIZE_API_KEY` still looks present. If it fails, `ax profiles delete default`, take the OAuth path below, and let Step 6 create a key as normal.
76
95
 
77
96
  - **No key anywhere** — sign up or sign in with browser OAuth:
78
97
 
@@ -80,7 +99,7 @@ If a `default` profile exists but the probe failed, it's signed out or expired,
80
99
  ax profiles create default --auth-method oauth --utm-params "utm_source=npmevals&utm_medium=cli&utm_campaign=prompt-first-onboarding"
81
100
  ```
82
101
 
83
- The `--utm-params` flag tags a new sign-up with onboarding attribution. It's already included on the three browser OAuth commands that take it — the two `ax profiles create --auth-method oauth` calls and the `ax auth login` fallback. Pass those verbatim; don't drop it, change the values, or add the flag to the api-key `profiles create` or any other `ax` command.
102
+ Pass `--utm-params` verbatim on the two browser OAuth commands that carry it (`profiles create --auth-method oauth` and the `ax auth login` fallback) and add it to no other `ax` command it tags a new sign-up with onboarding attribution.
84
103
 
85
104
  Always pass the positional profile name `default`. Without it, the CLI prompts `profile name [default]:`, receives EOF from an agent-run command, and exits with `Goodbye!` without creating a profile.
86
105
 
@@ -88,39 +107,23 @@ The rest of this step applies only to the **browser OAuth** branch.
88
107
 
89
108
  Creating an OAuth profile **is** the browser login flow. Treat it as an interactive browser handoff: it opens a browser, starts a localhost callback server such as `127.0.0.1:<port>/callback`, and waits for the browser redirect. The command must stay alive until the redirect lands and the CLI exits on its own.
90
109
 
91
- While the OAuth command is waiting, do not close its stdin, send Ctrl-C, `pkill` the AX process, start a second auth command, or run an auth probe. Any of these aborts the in-progress browser flow. There is one deliberate exception — the new email/password signup case described below, where the callback never lands and the command must be restarted.
110
+ While the OAuth command is waiting, do not close its stdin, send Ctrl-C, `pkill` the AX process, start a second auth command, or run an auth probe. Any of these aborts the in-progress browser flow. There is no exception: every sign-in path existing account, Google/SSO, existing or brand-new email/password completes through the same callback, so the command always gets there on its own.
92
111
 
93
112
  After launching the OAuth command, tell the user:
94
113
 
95
114
  ```text
96
115
  A browser window is opening for Arize AX sign-in.
97
116
 
98
- - Already have an account, or signing in with Google/SSO or an existing
99
- email/password? Just finish in the browser and I'll continue automatically.
100
- - Creating a BRAND-NEW account with email and password? Arize emails you a
101
- validation link. That link does NOT complete the CLI login, so this command
102
- will hang. Click the link to finish creating your account, then tell me.
117
+ Sign in or create a new account in the browser. I'll continue
118
+ automatically once it completes.
103
119
 
104
- Did you just sign up for a new account with email and password?
120
+ Creating a BRAND-NEW account with email and password? Arize emails you a
121
+ validation link. Click it and finish in the browser; I'll wait.
105
122
  ```
106
123
 
107
- **If the user says yes (new email/password signup):** the localhost callback will never fire and the command will wait forever, so this is the one time you break the "keep it alive" rule. Once they confirm they've clicked the validation link and their account exists, terminate the waiting OAuth command (send Ctrl-C / kill that process), then re-run it:
108
-
109
- ```bash
110
- ax profiles create default --auth-method oauth --utm-params "utm_source=npmevals&utm_medium=cli&utm_campaign=prompt-first-onboarding"
111
- ```
112
-
113
- The second run is now a plain sign-in for the validated account. Its callback lands normally, so handle it with all the standard rules below — keep it alive and wait for it to exit on its own.
114
-
115
- **Otherwise (existing account, SSO, or existing email/password):** wait for the command to exit on its own. Treat exit code `0`, or CLI success output such as `Configuration saved to profile 'default'` or `Active profile set`, as the primary completion signal.
124
+ Then wait for the command to exit on its own. Treat exit code `0`, or CLI success output such as `Configuration saved to profile 'default'` or `Active profile set`, as the primary completion signal. A new email/password sign-up can sit waiting for a while the user has to find the validation email so a long wait is not a hang; leave it alone.
116
125
 
117
- Only after the OAuth command completes, verify authentication with a non-secret probe:
118
-
119
- ```bash
120
- ax spaces list --limit 1 --output json
121
- ```
122
-
123
- If the probe succeeds, continue. If the default OAuth profile already existed and the probe returns an authentication error, the profile is signed out or expired — run the fallback:
126
+ Only after the OAuth command completes, re-run the probe from the top of this step. If it succeeds, continue. If the default OAuth profile already existed and the probe returns an authentication error, the profile is signed out or expired — run the fallback:
124
127
 
125
128
  ```bash
126
129
  ax auth login --utm-params "utm_source=npmevals&utm_medium=cli&utm_campaign=prompt-first-onboarding"
@@ -144,9 +147,27 @@ If `ARIZE_SPACE_ID` is already set (environment or `.env` / `.env.local`), use i
144
147
 
145
148
  Capture the space's **ID** (not its display name) for `ARIZE_SPACE_ID`. The `arize-otel` tracing config requires the space ID; a name will silently fail to route traces.
146
149
 
147
- ## Step 4: Inspect the folder and choose a path
150
+ ## Step 4: Choose what to trace
151
+
152
+ Ask what the user wants to trace before inspecting anything — the third option has nothing to do with what is in the current folder:
153
+
154
+ ```text
155
+ What would you like to trace?
156
+
157
+ 1. An existing app — in this folder or at another path
158
+ 2. A new starter app I create for you
159
+ 3. This coding agent itself — every session you run, in any project
160
+
161
+ Which one?
162
+ ```
163
+
164
+ If they pick **3**, go to [Step 4A](#step-4a-trace-this-coding-agent) and skip the folder inspection entirely. If they pick **2**, go straight to "Create a starter app" below — don't inspect anything. For **1**, continue.
165
+
166
+ For options **1** and **2**, one directory ends up being **the app folder**: the app you instrument, which is not always the folder you were launched in. Establish it in this step and use it for every path in Steps 5 to 7.
167
+
168
+ ### Detecting an app
148
169
 
149
- Inspect the current folder to decide whether an app already exists. Do not change files during inspection. Look for:
170
+ Inspect a candidate folder to decide whether an app already exists. Do not change files during inspection. Look for:
150
171
 
151
172
  - Python: `pyproject.toml`, `requirements.txt`, `setup.py`, `Pipfile`, imports.
152
173
  - TypeScript/JavaScript: `package.json`, lockfiles, `src`, `app`, `pages`, provider imports.
@@ -154,24 +175,48 @@ Inspect the current folder to decide whether an app already exists. Do not chang
154
175
  - Existing observability: `opentelemetry`, `TracerProvider`, `ARIZE_*`, `OTEL_*`, `OTLP_*`, Datadog, Honeycomb, Sentry, or other tracing.
155
176
  - Agent framework: identify it by its import/package — e.g. `langchain` / `langgraph`, `llama_index`, `crewai`, `autogen`, `semantic_kernel`, `pydantic_ai`, `google.adk`, `dspy`, `agent_framework`, and others. **Route on the framework, not the provider client it wraps** — an `openai` or `anthropic` import inside a framework app is not the thing to instrument; the framework almost certainly has its own integration (see Step 6).
156
177
 
157
- In a monorepo, check the git root to get oriented, but only instrument apps in or below the current working directory. If the project spans more than one language, instrument each one (route each through its own integration page in Step 6).
178
+ In a monorepo, check the git root to get oriented, but only instrument apps in or below the folder you are scanning. If the project spans more than one language, instrument each one (route each through its own integration page in Step 6).
158
179
 
159
- Then branch on what you found:
180
+ Run this detection on the current folder first, then branch on what you found.
160
181
 
161
182
  ### If an app exists in the current folder
162
183
 
163
- Do not offer the starter-app path. Summarize the detected stack and offer to instrument it:
184
+ Summarize the detected stack and offer both routes — declining the local app must not be a dead end, because the user may well have run this from a folder above the app they care about:
164
185
 
165
186
  ```text
166
- I found a <language>/<framework> app in this folder. Want me to add Arize AX
167
- tracing to it?
187
+ I found a <language>/<framework> app in this folder. I can trace that, or an
188
+ app somewhere else.
189
+
190
+ 1. Trace the app in this folder
191
+ 2. Trace an app at a different path — tell me where
192
+
193
+ Which one?
168
194
  ```
169
195
 
170
- If the user declines, stop here rather than falling back to a starter app.
196
+ On **1**, the app folder is the current folder; continue to Step 5. On **2**, follow "If the user gives a path" below. Don't offer the starter-app path here — they already have an app.
171
197
 
172
198
  ### If no app exists in the current folder
173
199
 
174
- Go straight to the starter-app choice — do not ask whether to instrument the empty folder. Ask which folder to create it in, then offer these choices:
200
+ Do not ask whether to instrument the empty folder, and do not assume a starter app is what they want. Ask for a path first:
201
+
202
+ ```text
203
+ I don't see an app in this folder. Give me the path to the app you want to
204
+ trace, and I'll instrument it — or say "starter" and I'll create a new app
205
+ for you instead.
206
+ ```
207
+
208
+ On a path, follow the next section. On "starter", go to "Create a starter app".
209
+
210
+ ### If the user gives a path
211
+
212
+ - Expand `~` and resolve a relative path against the current folder, then confirm the resolved absolute path back to the user before you scan it. A typo caught here beats an API key written into the wrong repo.
213
+ - Run the detection checklist on that folder. If it holds an app, that folder is the app folder from now on — summarize the stack you found there and continue to Step 5.
214
+ - If the path doesn't exist, or exists but has no app in it, say what you actually found and ask for another path. Don't quietly fall through to a starter app.
215
+ - If your own permission or sandbox layer won't let you read and write outside the folder you were launched in, say so plainly instead of half-instrumenting the app. Give the two ways out: the user grants access to that path, or they re-run `npx evals` from inside the app folder.
216
+
217
+ ### Create a starter app
218
+
219
+ For option 2, or when the user asks for a starter app after the questions above. Ask which folder to create it in — that folder becomes the app folder — then offer these choices:
175
220
 
176
221
  - OpenAI — Python or TypeScript (with a tool call)
177
222
  - Anthropic — Python (with a tool call; official AX auto-instrumentation)
@@ -180,15 +225,157 @@ Go straight to the starter-app choice — do not ask whether to instrument the e
180
225
 
181
226
  If the user picks an unsupported pairing, explain the supported options and ask again.
182
227
 
228
+ ## Step 4A: Trace this coding agent
229
+
230
+ Only for option 3. This traces the **agent harness**, not an app: every session the user runs, in every project on this machine. It edits files under their home directory, nothing in the current repo. When done, go to Step 8 — Steps 5 to 7 are app-only.
231
+
232
+ Installer harness names: `claude`, `codex`, `cursor`, `copilot`, `gemini`, `kiro`, `opencode`, `omp` — note Cursor is `cursor`, not `cursor-agent`. Default to the agent you are running inside: state which you are and confirm, rather than asking.
233
+
234
+ Per-agent setup, including the Claude Code and Cursor marketplace-plugin routes, is at `https://arize.com/docs/ax/integrations/platforms/<agent>/<agent>-tracing` (e.g. `.../claude-code/claude-code-tracing`) — the source of truth if anything below fails.
235
+
236
+ ### Check the home directory is writable first
237
+
238
+ Everything below writes under `~/.arize` — the credentials file, then the harness itself. Confirm that works before asking for approval, so a read-only or restricted home fails here rather than halfway through an install the user already said yes to:
239
+
240
+ ```bash
241
+ mkdir -p ~/.arize/onboarding && touch ~/.arize/onboarding/.probe && rm -f ~/.arize/onboarding/.probe
242
+ ```
243
+
244
+ If that fails, say so and stop this path — agent tracing needs a writable home and there is no workaround from inside the session. Instrumenting an app (options 1 and 2) does not, so offer that instead. If the launcher already told the user it couldn't use `~/.arize/onboarding`, this is the same cause; don't re-diagnose it.
245
+
246
+ ### Get approval — this needs its own explicit yes
247
+
248
+ Wider scope than an app install, so disclose it and wait:
249
+
250
+ ```text
251
+ This traces <agent> itself. Three things first:
252
+
253
+ - It applies to EVERY session you run, in every project on this machine.
254
+ - Unless you say otherwise I'll turn on all three capture categories: your
255
+ prompts, what tools were asked to do (commands, file paths, URLs), and what
256
+ tools returned (file contents, command output).
257
+ - It writes to ~/.arize/harness and <agent>'s settings file. Nothing in this
258
+ project changes.
259
+
260
+ Want to skip any capture category — prompts, tool commands, or tool output?
261
+ Shall I go ahead?
262
+ ```
263
+
264
+ Do not proceed without a yes. Note which categories they accepted — you enable those explicitly below, and anything you leave out stays off.
265
+
266
+ ### Write the config file
267
+
268
+ The installer reads credentials from a dotenv file, keeping the API key out of the command line, shell history, and this chat. Write it outside the project so it cannot be committed:
269
+
270
+ ```bash
271
+ : > ~/.arize/onboarding/harness.env && chmod 600 ~/.arize/onboarding/harness.env
272
+ ```
273
+
274
+ Add the Step 3 space ID as file contents, plus one `true` line per category the user **accepted**. Unattended installs capture nothing unless asked to, so a category you omit is off — omit the line for anything they declined:
275
+
276
+ ```dotenv
277
+ ARIZE_SPACE_ID=<space-id-from-step-3>
278
+ ARIZE_LOG_PROMPTS=true
279
+ ARIZE_LOG_TOOL_DETAILS=true
280
+ ARIZE_LOG_TOOL_CONTENT=true
281
+ ```
282
+
283
+ Do **not** set `ARIZE_PROJECT_NAME` — each harness defaults to its own project (`claude-code`, `codex`, …), which keeps two traced agents apart, and you read the real name back after installing. Then create the key into the same file, written atomically and never printed:
284
+
285
+ ```bash
286
+ ax api-keys create --name "Coding agent tracing" --env-file ~/.arize/onboarding/harness.env
287
+ ```
288
+
289
+ **Skip that if `ARIZE_API_KEY` already existed in Step 2** — copy the existing value in without echoing it. At most one key, ever.
290
+
291
+ ### Install, then delete the file
292
+
293
+ If a directory named `arize-offline/` sits beside this prompt file, install from it — no download, no remote script, so it is faster and far less likely to be refused:
294
+
295
+ ```bash
296
+ # keep `< /dev/null`: an installer too old for --non-interactive then fails
297
+ # fast instead of hanging on a prompt you cannot answer
298
+ ARIZE_ENV_FILE=~/.arize/onboarding/harness.env \
299
+ bash <prompt-dir>/arize-offline/harness-install.sh \
300
+ <harness> --wheel-dir <prompt-dir>/arize-offline --non-interactive < /dev/null
301
+ ```
302
+
303
+ Otherwise fetch it (the harness name must come first, before any flag):
304
+
305
+ ```bash
306
+ ARIZE_ENV_FILE=~/.arize/onboarding/harness.env \
307
+ bash <(curl -fsSL https://raw.githubusercontent.com/Arize-ai/coding-harness-tracing/main/install.sh) \
308
+ <harness> --non-interactive < /dev/null
309
+ ```
310
+
311
+ Delete the env file only once the install has actually run — a retry needs it, and so does the user if they end up running the command:
312
+
313
+ ```bash
314
+ rm -f ~/.arize/onboarding/harness.env
315
+ ```
316
+
317
+ On Windows, use `harness-install.bat` from the same directory — `cmd` cannot run the `.sh`:
318
+
319
+ ```powershell
320
+ $env:ARIZE_ENV_FILE = "$HOME\.arize\onboarding\harness.env"
321
+ & "<prompt-dir>\arize-offline\harness-install.bat" <harness> --wheel-dir "<prompt-dir>\arize-offline" --non-interactive
322
+ ```
323
+
324
+ Without `arize-offline/`, use the install command from the agent's docs page with `$env:ARIZE_ENV_FILE` set first.
325
+
326
+ An `EOFError` or hang means the installer predates `--non-interactive`: have the user run it without that flag and without `< /dev/null`, answering its prompts. On any other failure, report what it printed and stop — never retry with a different backend or type the key into a prompt.
327
+
328
+ ### If your permission layer refuses to run it
329
+
330
+ Expected on the fetched command — auto-approval modes hold back piping a downloaded script into a shell. Retry **once** with the installer downloaded to a file first; if still refused, stop and do not hunt for a phrasing that slips through. Hand it over instead:
331
+
332
+ ```text
333
+ My permission settings won't let me run the installer. It creates
334
+ ~/.arize/harness and adds hooks to <harness>'s settings file. Either run it
335
+ yourself — prefix with ! so I see the output — or tell me to go ahead and
336
+ I'll retry.
337
+
338
+ <the command, one line>
339
+ ```
340
+
341
+ A go-ahead authorizes that one command, nothing wider. **Never** frame this as bypassing a safety check, and never suggest an approval flag on the agent. **Keep the env file** until they confirm — they need those credentials.
342
+
343
+ ### Verify before asking the user for anything
344
+
345
+ ```bash
346
+ ~/.arize/harness/install.sh status --json
347
+ ```
348
+
349
+ Exit `0` means configured **and** hooks wired up; `1` nothing configured; `2` configured but hooks missing (the `unregistered` list names which to re-install). Continue only on `0`. Take the project name for polling from `harnesses[].project_name` in the payload rather than guessing it. The payload holds no secrets.
350
+
351
+ ### Get the first traces
352
+
353
+ Hooks load at session start, so **this session will never emit traces**. Do not restart or kill yourself — that would end the setup. Use a second session so you stay alive to poll:
354
+
355
+ ```text
356
+ Tracing is installed. This session won't be traced — it started before the
357
+ hooks existed. So:
358
+
359
+ 1. Open a new terminal and start <agent> there.
360
+ 2. Ask it something small, like "list the files in this folder".
361
+ 3. Tell me when you have, and I'll check for traces.
362
+ ```
363
+
364
+ Then poll with the Step 7 command and counter, passing that project name and space ID, every ~15 seconds for up to ~3 minutes. On a non-zero count go to Step 8. On timeout say so plainly and give the likely causes: the new session started before the install finished, the agent was never asked to do anything, `ARIZE_TRACE_ENABLED` is `false` in the agent's settings, or the wrong space.
365
+
183
366
  ## Step 5: Present the plan and get approval
184
367
 
185
- Before creating any remote resource, writing files, or installing dependencies, present one consolidated plan and wait for approval. This is the gate the intro refers to nothing so far has modified the app or created AX resources.
368
+ Steps 5 to 7 are for the app paths only; if you took Step 4A, go straight to Step 8.
369
+
370
+ Before creating any remote resource, writing files, or installing dependencies, present one consolidated plan and wait for approval.
186
371
 
187
372
  For an existing app, cover: detected language and framework, package manager, LLM provider or agent framework, any existing tracing to preserve, the env file that will be updated, the instrumentation packages and files that will change, whether a new AX user API key will be created or the existing `ARIZE_API_KEY` reused, and the project name that will be used.
188
373
 
189
374
  For a starter app, cover: the chosen provider and language, the target folder, the packages that will be installed, and the project name.
190
375
 
191
- Choose a default project name from the current folder or app name: lowercase it, replace spaces and unsupported punctuation with hyphens, and append `-arize-tracing` if it is too generic. Do not create an AX project explicitly it is created on first trace ingestion.
376
+ **State the app folder's absolute path in the plan whenever it isn't the folder you were launched in** every file you touch lands there, and it's the one detail the user cannot verify from context.
377
+
378
+ Choose a default project name from the app folder or app name: lowercase it, replace spaces and unsupported punctuation with hyphens, and append `-arize-tracing` if it is too generic. Do not create an AX project explicitly — it is created on first trace ingestion.
192
379
 
193
380
  ```text
194
381
  Here's my plan. Shall I proceed?
@@ -202,7 +389,7 @@ Only after approval, execute the plan in this order.
202
389
 
203
390
  ### Choose the env file
204
391
 
205
- Pick the env file to match the app and use it for every variable below:
392
+ The env file lives in the **app folder** from Step 4. Pick its name to match the app and use that one file for every variable below:
206
393
 
207
394
  - Next.js, Vite, or browser-adjacent TypeScript apps: `.env.local`
208
395
  - Python apps, Node scripts, backend services, or unknown type: `.env`
@@ -210,7 +397,7 @@ Pick the env file to match the app and use it for every variable below:
210
397
 
211
398
  Do not read existing env file contents into chat. Preserve unrelated variables and never reveal their values.
212
399
 
213
- Make sure the env file is git-ignored before writing the API key to it — if the repo has a `.gitignore`, confirm it covers the file (add `.env` / `.env.local` if not); for a starter app you create, add one. The API key must never be committed to version control.
400
+ Make sure the env file is git-ignored before writing the API key to it — check the `.gitignore` of the app folder's own repo. If it has one, confirm it covers the file (add `.env` / `.env.local` if not); for a starter app you create, add one. The API key must never be committed to version control.
214
401
 
215
402
  ### Write the non-secret variables
216
403
 
@@ -221,9 +408,11 @@ ARIZE_SPACE_ID=<space-id>
221
408
  ARIZE_PROJECT_NAME=<chosen-project-name>
222
409
  ```
223
410
 
411
+ An exported variable beats this file — both `dotenv` implementations leave an existing environment variable alone by default. Check `env | grep ARIZE_`; if anything you just wrote is exported, tell the user to `unset` it in the shell they'll run the app from, or to load with `override=True`. Your Step 7 check reads the CLI profile, not the app's environment, so it would pass regardless.
412
+
224
413
  ### Create the API key
225
414
 
226
- **Skip this entirely if `ARIZE_API_KEY` was already present in Step 2** — reuse it and leave its env value untouched. Only create a key when you authenticated with browser OAuth and the app has no key yet.
415
+ **Skip this entirely if `ARIZE_API_KEY` was already present and validated in Step 2** — reuse it and leave its env value untouched. Only create a key when you authenticated with browser OAuth and the app has no key yet.
227
416
 
228
417
  Create the key and write it into the env file in one step:
229
418
 
@@ -231,11 +420,11 @@ Create the key and write it into the env file in one step:
231
420
  ax api-keys create --name "Local Arize AX tracing" --env-file .env
232
421
  ```
233
422
 
234
- `--env-file` writes `ARIZE_API_KEY` atomically and **never prints it** — no temp file, no secret in your terminal or chat. Use `.env.local` if that's the app's convention; the file is created if missing, an existing `ARIZE_API_KEY` is replaced in place, and other variables are preserved.
423
+ `--env-file` writes `ARIZE_API_KEY` atomically and **never prints it** — no temp file, no secret in your terminal or chat. Use `.env.local` if that's the app's convention, and always pass the app folder's path (`--env-file /path/to/app/.env`) — a bare `.env` would leave a stray key file in the wrong directory. The file is created if missing, an existing `ARIZE_API_KEY` is replaced in place, and other variables are preserved.
235
424
 
236
- **Create the key exactly once** — a second `ax api-keys create` just orphans a still-active key. Git-ignore the env file (see above) *before* running this so the key is never committed.
425
+ **Create the key exactly once** — a second `ax api-keys create` just orphans a still-active key, and the env file must already be git-ignored.
237
426
 
238
- If key creation fails, have the user create one in the Arize AX UI and add it to the env file without exposing it in chat. Either way, create only one key.
427
+ If key creation fails, have the user create one in the Arize AX UI and add it to the env file without exposing it in chat.
239
428
 
240
429
  Handle the LLM provider's own key (e.g. `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`) in the same env file — the app can't make a call or produce traces without it:
241
430
 
@@ -261,7 +450,7 @@ Common shortcuts:
261
450
 
262
451
  1. Use a framework-specific OpenInference instrumentor if one exists (`openinference-instrumentation-<name>` / `@arizeai/openinference-instrumentation-<name>`), wired up with `arize-otel` per the manual-instrumentation guide; install it unpinned.
263
452
  1. Instrument the underlying provider (OpenAI, Anthropic, Bedrock, …) with its instrumentor **only if the framework calls the provider SDK directly**. Many agent frameworks instead drive the model through their own client layer and emit their own OpenTelemetry spans — a provider instrumentor captures **no traces** for those. Never reach for the provider instrumentor as a blind fallback just because you recognize an `openai`/`anthropic` client.
264
- 1. Otherwise instrument manually via `arize-otel` (see https://arize.com/docs/ax/instrument/manual-instrumentation), or stop and ask the user if you still can't determine a setup.
453
+ 1. Otherwise instrument manually by code follow https://arize.com/docs/ax/instrument/manual-instrumentation#by-code or stop and ask the user if you still can't determine a setup. `arize-otel` gives you a tracer, not LLM spans: **set the OpenInference span kind on every span you create** (`LLM` for a model call, `TOOL` for a tool, `AGENT` for the loop, `CHAIN` for a step), **and set the span status** — `ERROR` with the exception recorded on failure, `OK` otherwise. Without the kind, spans arrive as generic spans that AX cannot read as LLM calls: Step 7's span count comes back non-zero and looks like success while the trace shows no input, output, model, or token counts. Without the status, failed calls look like successful ones and errors never surface in AX.
265
454
 
266
455
  For existing apps:
267
456
 
@@ -281,7 +470,7 @@ For starter apps:
281
470
 
282
471
  ### Package guidance
283
472
 
284
- Install into the app's existing environment (its virtualenv if it has one) exactly the packages the detected framework's integration page lists — instrumentor names and peer dependencies differ per framework, so follow that page rather than copying from another stack or guessing versions.
473
+ Install into the app's existing environment — the one in the app folder, using its virtualenv if it has one exactly the packages the detected framework's integration page lists — instrumentor names and peer dependencies differ per framework, so follow that page rather than copying from another stack or guessing versions.
285
474
 
286
475
  ## Step 7: Run the app and poll for the first trace
287
476
 
@@ -293,11 +482,12 @@ If you created a starter app in this flow, offer to run it for the user:
293
482
  Your starter app is ready. Want me to run it for you?
294
483
  ```
295
484
 
296
- If they say yes, run it yourself with the run command, then poll. If they say no — or if you instrumented their existing app rather than creating a starter — tell them the exact run command and ask them to run it:
485
+ If they say yes, run it yourself with the run command, then poll. If they say no — or if you instrumented their existing app rather than creating a starter — tell them the exact run command and ask them to run it. When the app folder isn't the folder they're sitting in, lead with the `cd` so the command works as pasted:
297
486
 
298
487
  ```text
299
488
  Run your app with:
300
489
 
490
+ cd <app folder>
301
491
  <run command>
302
492
 
303
493
  It should make at least one LLM call. I'll poll Arize AX and let you know as
@@ -318,20 +508,22 @@ A non-zero count confirms traces are arriving. If you need to inspect a span to
318
508
  This uses the CLI profile from Step 2 (OAuth or api-key) — it works the same either way. If the export errors with an authentication failure, the profile isn't valid; re-run the Step 2 probe and re-authenticate, or fall back to having the user open the project in the Arize AX UI to confirm traces.
319
509
 
320
510
  - When spans come back, stop polling and continue to Step 8.
321
- - On timeout, do not fail silently. Tell the user no traces arrived yet, and give likely causes: app didn't make an LLM call, tracing initialized after the client was created, a short-lived script exited before flushing spans, or the wrong space/project/env file. Offer to re-check once they've run it again.
511
+ - On timeout, do not fail silently. Tell the user no traces arrived yet, and give likely causes: app didn't make an LLM call, tracing initialized after the client was created, a short-lived script exited before flushing spans, the wrong space/project/env file, or **an exported `ARIZE_*` variable overriding the env file** (`env | grep ARIZE_`). Offer to re-check once they've run it again.
322
512
 
323
513
  Do not fabricate trace results. Only report traces the export command actually returned.
324
514
 
325
515
  ## Step 8: Report the first traces with a link
326
516
 
327
- Once spans arrive, report the span count and give the user a link into Arize AX for the project. Point them at the UI to explore the trace contents rather than printing span bodies into chat.
517
+ Once spans arrive, report the span count and give the user a deep link to the project in Arize AX. Point them at the UI to explore the trace contents rather than printing span bodies into chat.
518
+
519
+ Build that link with the **Arize link skill**: if you installed the skills in Step 1, load it now by reading `arize-link/SKILL.md` from your agent's skills directory (same paths as Step 6) and follow it. It owns the URL format and the `ax` commands that discover the organization and project IDs; you already have the project name and the space ID from Step 3.
328
520
 
329
521
  ```text
330
522
  Your first traces are in Arize AX. Open project `<ARIZE_PROJECT_NAME>` here:
331
- https://app.arize.com/
523
+ <project link>
332
524
  ```
333
525
 
334
- If a space- or project-specific URL is known from the CLI or docs, prefer that deep link over the app root. Do not invent a URL structure you are not sure of; fall back to `https://app.arize.com/` plus instructions to select the project.
526
+ If that skill file doesn't exist (e.g. npx was missing in Step 1), don't invent a URL structure: fall back to `https://app.arize.com/` plus instructions to select the project.
335
527
 
336
528
  ## Step 9: Point at docs
337
529
 
@@ -345,13 +537,25 @@ You're set up. To go further:
345
537
  - AX CLI: https://arize.com/docs/api-clients/cli/overview
346
538
  ```
347
539
 
540
+ If you took Step 4A, add the controls that matter for agent tracing:
541
+
542
+ ```text
543
+ - Your agent's tracing page: https://arize.com/docs/ax/integrations/platforms/<agent>/<agent>-tracing
544
+ - Check it's still wired up: ~/.arize/harness/install.sh status
545
+ - Pause it: set ARIZE_TRACE_ENABLED=false in <agent>'s settings
546
+ - Remove it: ~/.arize/harness/install.sh uninstall <installer-name>
547
+ ```
548
+
348
549
  ## Critical rules
349
550
 
350
551
  - Get the user's approval (Step 5) before creating AX resources, editing files, or installing dependencies.
351
- - Authenticate the CLI before any other `ax` call — every command, including the final trace check, uses the active profile; env vars alone don't authenticate it. On the browser OAuth branch, keep the command alive until its localhost callback completes (never close stdin, Ctrl-C, `pkill`, or probe while it waits) sole exception: a brand-new email/password signup, whose link never calls back, so ask the user, then kill and re-run as a sign-in.
552
+ - Authenticate the CLI (Step 2) before any other `ax` call; env vars alone don't. Never interrupt a waiting OAuth command no stdin close, Ctrl-C, `pkill`, or probe. A slow wait is not a hang.
352
553
  - Never print, log, or summarize secrets in chat — API keys, env-file contents/values, or span bodies (prompts, completions, tool args, user data) — and never read env files into chat. Only report traces a command actually returned.
353
- - Create at most one AX API key: skip if `ARIZE_API_KEY` already exists (reuse it), otherwise a **single** `ax api-keys create --env-file <file>`. Git-ignore that file before creating the key; never create a second key.
554
+ - One AX API key, ever: reuse a **validated** `ARIZE_API_KEY`, else a **single** `ax api-keys create --env-file <file>` into an already-git-ignored file.
555
+ - Ambient `ARIZE_*` variables are claims to verify, not facts to adopt: probe a found API key before reusing it, and remember that an exported variable overrides the env file you write.
556
+ - Everything you write goes in the **app folder** (Step 4), which may not be the folder you were launched in. Name its absolute path in the plan; pass it explicitly to `--env-file` and the run command.
354
557
  - Write the space **ID** (not its name) to `ARIZE_SPACE_ID`, or traces won't route; never create an AX project explicitly (it's made on first ingestion).
355
- - Initialize tracing before LLM clients are created, and flush/shut down the tracer before short-lived scripts exit. Vercel AI SDK v7 also needs Node.js 22+, `@ai-sdk/otel` registered, and `experimental_telemetry: { isEnabled: true }` per call.
558
+ - Initialize tracing before LLM clients exist; flush before short-lived scripts exit. Vercel AI SDK v7 also needs Node.js 22+, `@ai-sdk/otel` registered, and per-call `experimental_telemetry`.
559
+ - Step 4A needs its own explicit yes, never folded into another approval — machine-wide, captures prompts and tool output. Run its installer with `--non-interactive` and `< /dev/null`, verify with `status --json`, and never restart the session you're in.
356
560
 
357
561
  Docs: https://arize.com/docs/llms.txt
package/package.json CHANGED
@@ -1,13 +1,18 @@
1
1
  {
2
2
  "name": "evals",
3
- "version": "2.4.0",
3
+ "version": "2.6.0",
4
4
  "description": "Arize AX onboarding — instrument your app with tracing via your coding agent",
5
5
  "type": "module",
6
6
  "main": "cli.js",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
7
10
  "scripts": {
8
11
  "postinstall": "node -e \"console.log('Arize evals installed — run: npx evals')\"",
9
12
  "start": "node cli.js",
10
- "test": "node --test"
13
+ "test": "node --test",
14
+ "build:wheel": "node scripts/build-harness-wheel.mjs",
15
+ "prepack": "npm run build:wheel"
11
16
  },
12
17
  "dependencies": {
13
18
  "ink": "^6.0.0",
@@ -15,13 +20,15 @@
15
20
  "react": "^19.0.0"
16
21
  },
17
22
  "bin": {
18
- "evals": "./cli.js"
23
+ "evals": "./bin.js"
19
24
  },
20
25
  "files": [
26
+ "bin.js",
21
27
  "cli.js",
22
28
  "onboarding-prompt.md",
23
29
  "start.sh",
24
- "start.ps1"
30
+ "start.ps1",
31
+ "vendor/"
25
32
  ],
26
33
  "keywords": [
27
34
  "arize",