n8n:create-instance-ai-eval

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗

Authors a new Instance AI workflow or Agent eval case — written locally as JSON, calibrated against a real build, then pushed to the LangTracer suite CI runs — build cases, behaviour/process cases, credential cases, and seeded (mid-conversation) cases — with intent-driven expectations. Use when adding or changing an Instance AI eval, or debugging why one is flaky.

.agents/skills/create-instance-ai-eval/SKILL.md

Download bundle ↓
master · 8bff5da4 bundle filesScanned 2026-09-15

running-evals.md

3,571 tokens · o200k_base · 13,953 bytes

Source excerpt starting at line 1.
# Running evals A run does four things: **build** (Instance AI builds the workflow on a liveinstance) → **Phase 1** (generate mock data hints) → **Phase 2** (execute withexternal HTTP requests LLM-mocked) → **verify** (LLM grades `successCriteria`).This file describes what the harness offers and how to point it at an instance;the [README](../../../packages/@n8n/instance-ai/evaluations/README.md) has theexhaustive flag list. ## What a run needs - **A running n8n instance with Instance AI enabled**, reachable over HTTP. The  eval is a client — it logs in and drives the normal build flow. Point it with  `--base-url` (defaults to `http://localhost:5678`); use whatever instance you  already run for Instance AI dev.- **A login** — the eval signs in as an existing user. Set the eval login env  vars to a user your instance has; the model and most settings have defaults  that a working Instance AI dev setup already provides.- **A working sandbox** — the build executes its workflow-build code in a  sandbox, so the instance must have one configured (see below).- **A model key for the eval helper** — mock generation, verification,  user-proxy, and the expectations judge call an Anthropic-capable model. ## The sandbox The build runs generated code in a sandbox that must be enabled and reachable onthe instance. How it's provisioned is a property of your instance, not the eval: - **Via the hosted proxy** — the instance vends sandbox access (and can vend the  model) through the AI-assistant proxy.- **Direct** — the instance talks to the sandbox provider (Daytona) and the model  provider with your own keys, bypassing the proxy. Either path has a ceiling a parallel run can hit — the **proxy** enforces aper-tenant quota, and going **direct** shifts that ceiling to your modelprovider's rate limits. Neither is "the" setting; pick per what you're runningand lower `--concurrency` if you hit a limit. Configuration specifics live in theinstance's Instance AI config and the README's environment-variables section. ## Run modes | Mode | How | Produces ||---|---|---|| **Direct driver** | no `LANGSMITH_API_KEY` | `eval-results.json` + HTML report locally — same pipeline and row order as the LangSmith driver (TRUST-261), row concurrency follows `--concurrency` || **LangSmith** | `LANGSMITH_API_KEY` set | also records an experiment and auto-compares against the baseline || **Prebuilt** | `--prebuilt-workflows <manifest>` | skips the build; verifies existing workflows (score MCP/hand-built cohorts on the same verifier) | Narrow any run with `--filter <slug>` (filename substring, comma = OR),`--tier <name>`, and `--exclude`. `--keep-workflows` leaves built workflows forinspection; `--iterations N` runs each case N times for pass@k / pass^k. **Seeded cases and `--keep-workflows`.** A seeded case's live turn addresses itsworkflow the way a user would — by name, often loosely ("the batch imageworkflow"). So a leftover copy is something the agent can rationally pick insteadof its own, and it prefers the one with failed executions when the messagementions a failure; the judge then grades a different workflow than the agentedited. That produces false greens as readily as false reds, so it doesn'tannounce itself. Restore now defends against this on both sides: each restored workflow gets a`[seed <8 hex>]` name suffix so copies are distinguishable, and any leftovercarrying that suffix with the same base name is deleted before the next restore.You'll see `Evicted N leftover seed workflow(s) before restore` when it fires.Workflows without the suffix — real ones, and anything the agent built — are nevertouched. So `--keep-workflows` is safe to use on a seeded case; the leftover iscleaned up by the next run rather than contaminating it. **Seeded agents are not evicted** — they get a fresh id per run but keep theirauthored name, so `--keep-workflows` on an agent-seeding case leaves one behindand they accumulate under the same name. That can't misdirect a later run (thelive turn is bound to its own agent by id), but it does clutter what the `agents`tool lists. Delete them yourself when calibrating:`DELETE /rest/projects/<projectId>/agents/v2/<agentId>`. ## Case source: disk vs langtracer | Source | When to use it ||---|---|| **`disk`** (default) | **Preferred for local development** — authoring and calibrating the case in front of you: drop the JSON into `data/workflows/`, `--filter` it, iterate. Also the only home of the `agents` tier and of a `replay`-seeded case (reconstructed from a trace at run time, so no suite can hold it); since the corpus migration the directory holds only those, not the full suite. || **`langtracer`** (`--source langtracer --suite baseline`) | Bigger runs (the full corpus or a whole tier), re-running specific cases that already live in the suite, and CI — which always runs this way. Needs `LANGTRACER_URL`/`LANGTRACER_API_KEY` in your env. | ## Configuration & secrets The harness reads its configuration from environment variables — how you supplythem is up to you. A common setup is a gitignored local env file loaded with`dotenvx` (`.env.eval.example` is a starting template), but any env mechanismworks. The pieces, regardless of how they're loaded: - the **model key** the eval helper uses (mock-gen / verifier / user-proxy /  judge);- the **login** the eval signs in with;- optionally `LANGSMITH_API_KEY` to record experiments and compare against a  baseline (note: setting this locally also writes your run into the shared  dataset — leave it unset for throwaway exploration);- optionally `CONTEXT7_API_KEY` to improve mock realism for less-common services. Describe-what-you-need, not a fixed recipe: on a dev instance you already use,the login and model are usually already set, and you only add the eval-specifickeys. ## Run locally against a dev instance The pieces above assume a configured instance; this is the concrete recipe thatworks end-to-end (direct Daytona mode, no proxy), plus the footguns that don'tsurface until you hit them. **Point the run with the `--base-url` flag, not the `N8N_EVAL_BASE_URL` env var.**If you load env via `dotenvx` / `.env.local` (a common dev setup), the file'svalue silently overrides the `N8N_EVAL_BASE_URL` you export, and the runauthenticates against the wrong instance (a confusing 401). The CLI `--base-url`flag wins — use it. **Direct-mode env combo** (bypass the proxy; your own Daytona + Anthropic keys): - `N8N_AI_ASSISTANT_BASE_URL=` **empty** — direct mode is only selected when the  proxy base URL is unset.- `DAYTONA_API_KEY` + `DAYTONA_API_URL` — sandbox auth; without them every build  crashes at `DaytonaAuthManager requires exactly one of staticApiKey or  getAuthToken`.- `ANTHROPIC_API_KEY` — the non-proxy orchestrator reads this (not just  `N8N_AI_ANTHROPIC_KEY`); the eval helper (mock-gen / verify / judge) reads  either. **You usually don't need a separate key: `.env.eval` already carries  `N8N_AI_ANTHROPIC_KEY`** — mirror it rather than hunting for another one  (`ANTHROPIC_API_KEY="$(grep '^N8N_AI_ANTHROPIC_KEY=' .env.eval | cut -d= -f2-)"`,  or just export it inside the `dotenvx` child). Check the file before concluding  a key is missing — and grep its names with `^[A-Za-z0-9_]+=`, since a  `^[A-Z_]*=` pattern silently drops every `N8N_*` var (the digit).- `E2E_TESTS=true` — exposes `POST /rest/e2e/reset` so you can seed a known owner. **Seed an owner** (a fresh instance has none → login 401s). Full payload shape inthe [README](../../../packages/@n8n/instance-ai/evaluations/README.md) quickstart: ```bashcurl -sf -X POST <base>/rest/e2e/reset -H 'Content-Type: application/json' \  -d '{"owner":{"email":"nathan@n8n.io","password":"PlaywrightTest123","firstName":"Eval","lastName":"Owner"},"admin":{"email":"admin@n8n.io","password":"PlaywrightTest123","firstName":"Admin","lastName":"User"},"members":[],"chat":{"email":"chat@n8n.io","password":"PlaywrightTest123","firstName":"Chat","lastName":"User"}}'``` **Run isolated alongside an already-running dev instance** (rather than killingit): a running instance holds both its main port *and* the task-broker port(default 5679), and the default DB is one shared SQLite file in `~/.n8n`. Give thesecond instance its own everything: ```bash# .env.eval alone is enough — it carries N8N_AI_*, the sandbox/Daytona keys and# N8N_AI_ANTHROPIC_KEY. Skip .env.local: its staging base-url / port-5678# defaults fight the settings below.N8N_PORT=5680 N8N_RUNNERS_BROKER_PORT=5681 N8N_USER_FOLDER=/tmp/n8n-eval-run \E2E_TESTS=true N8N_AI_ASSISTANT_BASE_URL= \  npx dotenvx run -f .env.eval -- \  sh -c 'ANTHROPIC_API_KEY="$N8N_AI_ANTHROPIC_KEY" exec pnpm start'# then seed the owner (above), and run the eval with: --base-url http://localhost:5680``` **Don't reach for `DB_SQLITE_POOL_SIZE=0`** if you find it in an older note. Itcan't disable pooling: the schema is `.int().gte(1)`, so `0` is rejected and`@Env` warns (`Invalid value for DB_SQLITE_POOL_SIZE … Falling back to defaultvalue.`) and keeps the default of 3. There is no non-pooled path to selectanyway — `getSqliteConnectionOptions()` always returns `type: 'sqlite-pooled'`.`POST /rest/e2e/reset` seeds the owner fine under the pooled driver. `pnpm start` (built dist) is enough — no need for `pnpm dev:ai`. Case JSON is readfrom source at run time, so new/edited cases need no rebuild. **Two WARNs are benign, not failures:** `Run debug capture skipped … Run debug isnot enabled` (a 404 from an optional debug endpoint) and workflow-checks`errored, excluded from scoring` — both are expected locally and don't affectyour case's pass/fail. ## Parallel lanes The **build** is the slow step and is capped at **4 concurrent builds perinstance**, so throughput scales with the number of instances, not just`--concurrency`. **Watch for false timeouts under contention:** a batch larger than the cap canqueue a *healthy* case behind that limit until it hits the per-iteration timeoutand reports `BUILD FAILED: Run timed out` — a run-capacity artifact, not a casedefect (a case that builds in ~3 min solo can "time out" at 900s in a crowdedbatch). Re-run the suspect solo (`--concurrency 1`) to confirm it builds in time,and for batches beyond ~a dozen cases fan out across lanes rather than justraising `--concurrency` on one instance. Two ways to fan out: - **`scripts/run-eval-lanes.sh`** spins up N lanes as **docker containers**,  seeds a user on each, and runs the eval with the base-URLs wired together.  It needs the **local image built first** (`INCLUDE_TEST_CONTROLLER=true pnpm  build:docker`); pass `--build` to (re)build it, which you must do after any  code change (the image is a snapshot). Extra eval args pass through after `--`.   ```bash  # from packages/@n8n/instance-ai/  ./scripts/run-eval-lanes.sh --instance-count 5 --tier pr  ./scripts/run-eval-lanes.sh --instance-count 3 --build -- --filter contact-form  ``` - **Comma-separated `--base-url`** to fan across instances you're already  running; a work-stealing allocator dispatches each build to a free lane.   ```bash  pnpm eval:instance-ai --base-url http://localhost:5678,http://localhost:6678  ``` ## Tiers Each case declares a `datasets` array (default `["full"]`) — free-form logicalgroupings, propagated to LangSmith as example splits so `--tier <name>` maps to aserver-side filter. The two that matter for CI: - **`full`** — every case; nightly / full-suite runs.- **`pr`** — curated thin set for the PR gate: high baseline reliability +  capability diversity. Other values group cases logically (e.g. `behaviour` for conversation-behaviourcases, `seeded` for transient `replay` cases kept out of CI). For a newlocal case, put the value in its `datasets` array before pushing; for a casealready in LangTracer, edit `datasets` there — `eval:langtracer-push`deliberately does not re-sync tier-only edits to an existing case. **Onlypromote to `pr` after `--iterations 5+` shows it's reliably green** — a flakycase in the gate poisons it. ## Baselines & regression When `LANGSMITH_API_KEY` is set, every run auto-compares against the most recentexperiment named `instance-ai-baseline-*` and writes `eval-pr-comment.md`.Regression tiers are computed statistically (`comparison/statistics.ts`) sosmall-N PR runs don't flag noise. Comparison is best-effort — it never fails arun. **Refresh the baseline** explicitly (no auto-refresh), on `master`, with high Nfor low noise: ```bash# with your env loaded and LANGSMITH_API_KEY set, from packages/@n8n/instance-ai/# (--dataset/--baseline-prefix mirror CI's pins — langtracer mode otherwise# derives suite-scoped names and later runs would never find this baseline)pnpm eval:instance-ai --source langtracer --suite baseline \  --dataset instance-ai-workflow-evals --baseline-prefix instance-ai-baseline- \  --experiment-name instance-ai-baseline --iterations 10``` LangSmith appends a random suffix; the most-recently-started `instance-ai-baseline-*`becomes the next comparison target. In CI, the same is a workflow dispatch: ```bashgh workflow run test-evals-instance-ai.yml -f experiment-name=instance-ai-baseline -f iterations=10gh workflow run ci-instance-ai-evals.yml -f pr=<number>   # re-run evals against a PR's head``` An isolated cohort (e.g. MCP) must override **both** `--dataset` and`--baseline-prefix` — overriding one still touches shared Instance AI data (theCLI warns). ## Reading the result The `workflow-eval-report.html` in the run's `.data/` dir is the fastestdebugger — full transcript, per-node traces, intercepted requests + mockresponses, and the verifier's reasoning. `eval-results.json` is themachine-readable companion. (See the SKILL's "Outputs of a run".) 
Referenced from SKILL.md