Ewaluacja agentów, promptów i zmian w CLAUDE.md: promptfoo, Inspect SWE, Langfuse i Braintrust
Ewaluacja agenta kodującego polega na uruchomieniu stałego zestawu prawdziwych zadań na dwóch konfiguracjach i porównaniu wyników, które da się sprawdzić kodem. promptfoo uruchamia Claude Code i Codex przez ich SDK, Inspect SWE uruchamia je w sandboksach Dockera, a Langfuse lub Braintrust śledzą każdą sesję, żeby dało się wyjaśnić, dlaczego zadanie się nie udało.
Ktoś z zespołu otwiera pull request, który skraca CLAUDE.md z 400 do 120 linii i dodaje dwie nowe reguły. W wątku review jest sześć opinii i zero danych: jedna osoba twierdzi, że po dniu z nowym plikiem agent „wydaje się bystrzejszy”, druga, że przestał uruchamiać testy. Za chwilę scalisz zmianę, którą przeczyta każda sesja agenta w repozytorium, i nikt nie potrafi powiedzieć, czy pomaga. Ta strona jest dla programisty, który buduje ewaluację, i dla tech leada, który decyduje, czy zmiana reguł trafi do main.
Co daje ci ewaluacja reguł agenta
Dział zatytułowany „Co daje ci ewaluacja reguł agenta”- Konfigurację promptfoo, która robi test A/B dwóch wariantów
CLAUDE.mdna tych samych zadaniach, tym samym commicie i tym samym przypiętym modelu, z deterministycznymi kontrolami (testy przechodzą, diff mieści się w zakresie, testy zostały uruchomione) przed jakąkolwiek oceną przez model. - Ten sam eksperyment dla Codeksa i
AGENTS.mdoraz drogę dla Cursora, dla którego promptfoo nie ma providera. - Zadanie Inspect SWE na wypadek, gdy każde uruchomienie ma działać w jednorazowym sandboksie Dockera, a klucz do modelu ma zostać na hoście.
- Regułę decyzyjną do czytania wyników, żeby zmianę reguł scalać na podstawie dowodów, a nie wrażeń.
- Miejsce platform śledzenia: Langfuse, Braintrust, Opik i Phoenix wyjaśniają, dlaczego zadanie się nie udało; nie zastępują stałego zestawu zadań.
- Trzy prompty do skopiowania i tabelę awarii, czyli sposobów, na które takie eksperymenty po cichu nic nie mierzą.
Każde polecenie i klucz konfiguracji poniżej sprawdziliśmy 2026-09-26 na promptfoo 0.123.1, inspect-ai 0.3.269 z inspect-swe 0.2.71, Claude Code 2.1.283 i Codex CLI 0.157.1. Ogólną metodę budowania zestawu ewaluacyjnego do wyboru modelu opisuje strona jak czytać benchmarki i budować własne ewaluacje; ta strona dotyczy ewaluacji zmian w twoim harnessie: plikach reguł, promptach, skillach i pluginach.
Które narzędzie odpowiada na które pytanie?
Dział zatytułowany „Które narzędzie odpowiada na które pytanie?”Zacznij od pytania. Pierwsze trzy wiersze uruchamiają agenta; pozostałe go obserwują albo testują coś, co sam dostarczasz.
| Pytanie | Narzędzie | Uruchamia agenta? | Gdzie działa |
|---|---|---|---|
Czy nowy CLAUDE.md lub AGENTS.md jest lepszy na naszych zadaniach? | promptfoo (anthropic:claude-agent-sdk, openai:codex-sdk) | Tak, przez SDK dostawcy | Twoja maszyna lub runner CI |
| To samo, ale każde uruchomienie w osobnym kontenerze, kilku agentów w jednym harnessie | Inspect AI + Inspect SWE (claude_code(), codex_cli()) | Tak, w sandboksie; wywołania modelu idą przez Inspect | Docker lub Kubernetes |
| Czy ten plugin lub skill pomaga w porównaniu z brakiem pluginu? | claude plugin eval (Claude Code 2.1.283) | Tak, z ramieniem bazowym bez pluginu | Twoja maszyna |
| Dlaczego ta sesja się nie udała i ile kosztowała? | Plugin Langfuse, Braintrust bt trace, Opik | Nie, śledzi prawdziwe sesje | SaaS lub self-hosted |
| Lokalny interfejs śladów OpenTelemetry bez konta | Arize Phoenix | Nie | Twoja maszyna |
| Czy funkcja LLM, którą dostarczamy, ma regresję albo wycieka dane? | DeepEval, garak, OpenLLMetry | Nie, testuje twoją aplikację | CI, twoja aplikacja |
Popularność na 2026-09-26, według GitHuba i rejestrów pakietów: promptfoo 25,5 tys. gwiazdek (npm 0.123.1; README podaje, że projekt „is now part of OpenAI” i pozostaje na licencji MIT), Langfuse 35,1 tys. (samo repozytorium pluginu do Claude Code: 24), Opik 22,2 tys., DeepEval 18,4 tys., Arize Phoenix 11,6 tys., garak 9,4 tys., OpenLLMetry 7,4 tys., Inspect AI 2,9 tys. i Inspect SWE 33. Monorepo pluginów Braintrust dla agentów kodujących miało 2 gwiazdki (npm braintrust 3.35.0). Platformy są dojrzałe; ich pluginy do agentów kodujących mają po kilka miesięcy.
Test A/B zmiany w CLAUDE.md w promptfoo
Dział zatytułowany „Test A/B zmiany w CLAUDE.md w promptfoo”Eksperyment ma jedną zmienną. Oba ramiona dostają ten sam commit repozytorium, te same zadania, ten sam model i te same uprawnienia narzędzi; różni się tylko plik reguł. promptfoo uruchamia każde zadanie w każdym ramieniu, odpala twoje kontrole i pokazuje obok siebie odsetek zaliczonych zadań, koszt i czas dla każdego ramienia.
-
Zbuduj stały zestaw 10–20 prawdziwych zadań. Weź je ze scalonych pull requestów, które przyszły z testami: poprawka błędu, mała funkcja, refaktoryzacja, dopisanie testów. Każde zadanie potrzebuje promptu, jaki programista naprawdę by napisał, i kontroli, którą da się uruchomić kodem. Zamroź listę; zmiana zadań między przebiegami psuje porównanie.
-
Utwórz dwa worktree poza repozytorium, oba na tym samym commicie, i zacommituj proponowane reguły w drugim. Claude Code czyta pliki
CLAUDE.mdtakże z katalogów nadrzędnych, więc worktree wewnątrz repozytorium wczytałby do ramienia „proposed” również obecny plik. W terminalu, z katalogu głównego repozytorium:Okno terminala BASE=$(git rev-parse origin/main)mkdir -p ../rules-abgit worktree add --detach ../rules-ab/current "$BASE"git worktree add --detach ../rules-ab/proposed "$BASE"git show origin/trim-claude-md:CLAUDE.md > ../rules-ab/proposed/CLAUDE.mdgit -C ../rules-ab/proposed add CLAUDE.md && git -C ../rules-ab/proposed commit -qm "eval: proposed CLAUDE.md"(cd ../rules-ab/current && npm ci) && (cd ../rules-ab/proposed && npm ci)cd ../rules-ab && npm install --save-dev promptfoo@0.123.1 @anthropic-ai/claude-agent-sdktrim-claude-mdoznacza gałąź ocenianego pull requesta. Zacommitowanie proponowanego pliku pozwala hookowi resetu przywrócić każde ramię do czystego stanu przezgit reset --hardbez utraty testowanych reguł. -
Napisz konfigurację. Zapisz ją jako
../rules-ab/promptfooconfig.yaml. Oba providery są identyczne pozalabeliworking_dir:rules-ab/promptfooconfig.yaml description: CLAUDE.md A/B on a fixed task setprompts:- '{{task}}'providers:- id: anthropic:claude-agent-sdklabel: currentconfig:working_dir: ./currentsetting_sources: ['project'] # load CLAUDE.md from working_dir; no user-level filesmodel: claude-opus-5-5 # pin it: a default that moves mid-experiment ruins the A/Btools: ['Read', 'Grep', 'Glob', 'Write', 'Edit', 'Bash'] # what the agent can seepermission_mode: dontAsk # anything not pre-approved below is denied, never promptedappend_allowed_tools: ['Write', 'Edit', 'Bash(npm test:*)', 'Bash(npx tsc:*)']disallowed_tools: ['WebFetch', 'WebSearch']max_turns: 40max_budget_usd: 3- id: anthropic:claude-agent-sdklabel: proposedconfig:working_dir: ./proposedsetting_sources: ['project']model: claude-opus-5-5tools: ['Read', 'Grep', 'Glob', 'Write', 'Edit', 'Bash'] # what the agent can seepermission_mode: dontAsk # anything not pre-approved below is denied, never promptedappend_allowed_tools: ['Write', 'Edit', 'Bash(npm test:*)', 'Bash(npx tsc:*)']disallowed_tools: ['WebFetch', 'WebSearch']max_turns: 40max_budget_usd: 3extensions:- file://reset.js:extensionHookdefaultTest:options:provider: openai:responses:gpt-6-sol # the judge comes from another vendor than the agentassert:- type: javascriptvalue: file://checks.js:testsPassmetric: tests_pass- type: javascriptmetric: ran_testsvalue: |const calls = context.providerResponse?.metadata?.toolCalls || [];return calls.some(t => t.name === 'Bash' && t.input?.command?.includes('npm test'));- type: llm-rubricmetric: conventionsvalue: >-The final message states what changed and why, and names the tests it ran.You see only this message, not the diff.tests:- description: invoice rounding bug (from PR 1841)vars:task: >-Invoice totals are one cent off when a line has quantity 3 and unit price 0.10.Fix it in src/billing and add a regression test.assert:- type: javascriptmetric: in_scopevalue: file://checks.js:diffInScopeconfig: { allowedPrefixes: ['src/billing/', 'test/billing/'] }# ...9 to 19 more tasks in the same shapeW providerze promptfoo
setting_sourcesjest domyślnie wyłączone, więc bez tego klucza żadne ramię nie czytaCLAUDE.mdi oba ramiona są tym samym eksperymentem powtórzonym dwa razy. Ustaw też jawnietools: przy podanymworking_diri brakutoolspromptfoo 0.123.1 wyprowadza listę narzędzi z wpisów o dozwolonych narzędziach, a wzorzec w rodzajuBash(npm test:*)to reguła uprawnień, nie nazwa narzędzia.toolsdecyduje, co agent w ogóle może wywołać;append_allowed_tools– co wykona się bez pytania;dontAskodrzuca całą resztę. Aktualny identyfikator modelu weź z porównania modeli w dniu, w którym uruchamiasz test. -
Dodaj kontrole i hook resetu obok konfiguracji. Kontrole zaglądają do katalogu roboczego ramienia po zakończeniu pracy agenta; hook przywraca oba ramiona do ich commita po każdym teście.
rules-ab/checks.js const { execFileSync } = require('node:child_process');const path = require('node:path');const dirOf = (context) => path.join(__dirname, context.provider.label);const run = (cmd, args, cwd) => {try {return { ok: true, out: execFileSync(cmd, args, { cwd, encoding: 'utf8', stdio: 'pipe', timeout: 600000 }) };} catch (err) {return { ok: false, out: `${err.stdout || ''}${err.stderr || ''}` };}};module.exports.testsPass = (output, context) => {const r = run('npm', ['test', '--silent'], dirOf(context));return { pass: r.ok, score: r.ok ? 1 : 0, reason: r.ok ? 'npm test passed' : r.out.slice(-800) };};module.exports.diffInScope = (output, context) => {const cwd = dirOf(context);const changed = run('git', ['diff', '--name-only', 'HEAD'], cwd).out;const added = run('git', ['ls-files', '--others', '--exclude-standard'], cwd).out;const files = `${changed}\n${added}`.split('\n').filter(Boolean);const outside = files.filter((f) => !context.config.allowedPrefixes.some((p) => f.startsWith(p)));return { pass: outside.length === 0, score: outside.length ? 0 : 1, reason: outside.length ? `outside scope: ${outside.join(', ')}` : `${files.length} files, all in scope` };};rules-ab/reset.js const { execFileSync } = require('node:child_process');const path = require('node:path');function reset() {for (const arm of ['current', 'proposed']) {const cwd = path.join(__dirname, arm);execFileSync('git', ['reset', '--hard', '--quiet', 'HEAD'], { cwd });execFileSync('git', ['clean', '-fdq'], { cwd }); // keeps ignored files such as node_modules}}module.exports.extensionHook = async (hookName) => {if (hookName === 'beforeAll' || hookName === 'afterEach') reset();}; -
Uruchamiaj sekwencyjnie, trzy razy na zadanie, z wyłączonym cache. Sekwencyjnie, bo oba ramiona dzielą hook resetu; trzy powtórzenia, bo jedno uruchomienie agenta na zadanie daje za dużo szumu do porównań; bez cache, bo odpowiedź z cache nie jest nowym uruchomieniem.
Okno terminala cd ../rules-ab# Load ANTHROPIC_API_KEY (the agent) and OPENAI_API_KEY (the judge) into the environment# from your secret manager; never type a key on the command line. To use your local# Claude Code login instead of an API key, add apiKeyRequired: false to both providers.npx promptfoo eval -j 1 --repeat 3 --no-cache -o results.jsonnpx promptfoo viewpromptfoo evalkończy się kodem100, gdy choć jeden test nie przejdzie, więc to samo polecenie posłuży później jako bramka w CI.promptfoo viewotwiera macierz w przeglądarce: kolumna na ramię, wiersz na zadanie, z nazwanymi metrykami (tests_pass,ran_tests,conventions,in_scope) i kosztem w każdej komórce.
Ten sam eksperyment w Claude Code, Codeksie i Cursorze
Dział zatytułowany „Ten sam eksperyment w Claude Code, Codeksie i Cursorze”Zestaw zadań, kontrole i reguła decyzyjna się nie zmieniają. Zmienia się provider i plik reguł, który czyta dany agent.
Użyj konfiguracji powyżej. Identyfikatory providera to anthropic:claude-agent-sdk i alias anthropic:claude-code; anthropic:claude-code-sdk nie istnieje. promptfoo 0.123.1 instaluje @anthropic-ai/claude-agent-sdk 0.3.263 jako opcjonalną zależność; jawna instalacja, jak w kroku 2, daje bieżące wydanie (npm 0.3.283 na 2026-09-26) i obejmuje instalacje pomijające opcjonalne zależności.
Do testu A/B skilla lub pluginu zamiast pliku reguł Claude Code 2.1.283 ma wbudowany runner. Czyta przypadki z katalogu evals/ pluginu i sam dodaje ramię bazowe bez pluginu:
claude plugin eval ./plugins/release-notes --runs 3 --threshold 0.8 --no-publishPierwsze uruchomienie w nowym katalogu pluginu prosi o potwierdzenie zaufania; w CI przekaż --trust-plugin, i to tylko dla pluginów, które sam byś uruchomił. --threshold sprawia, że polecenie kończy się kodem 1, gdy którykolwiek przypadek wypadnie poniżej progu, a --max-cost-usd ustawia twardy limit kosztu przebiegu. Kod pluginu działa z twoimi uprawnieniami, więc oceniaj tylko pluginy, którym ufasz. Format przypadków opisuje strona budowa i dystrybucja pluginu.
Codex czyta AGENTS.md, więc warianty różnią się tym plikiem. Zamień oba providery na providera Codex SDK; openai:codex to alias. promptfoo 0.123.1 deklaruje @openai/codex-sdk ^0.153.2 jako opcjonalną zależność (npm 0.157.1 na 2026-09-26).
providers: - id: openai:codex-sdk label: current config: working_dir: ./current model: gpt-6-astra sandbox_mode: workspace-write # writes stay inside working_dir approval_policy: never network_access_enabled: false - id: openai:codex-sdk label: proposed config: working_dir: ./proposed model: gpt-6-astra sandbox_mode: workspace-write approval_policy: never network_access_enabled: falseUsuń asercję ran_tests: czyta wywołania narzędzi w formacie Claude. Kontrole testsPass i diffInScope działają bez zmian. Od Codeksa 0.150.0 niezaufane projekty nie dostarczają projektowego AGENTS.md; oznacz obie ścieżki worktree jako zaufane i zanim uwierzysz w remis, uruchom regułę-kanarka na ramionach Codeksa.
promptfoo 0.123.1 nie ma providera dla Cursora (sprawdzone w indeksie providerów na tagu 0.123.1). Zachowaj zestaw zadań i kontrole, a uruchom je przez agenta cursor-cli w Harborze (Harbor 0.23.0, 2026-09-12). Instaluje on Cursor CLI w kontenerze każdego zadania i steruje nim w trybie print z automatycznym zatwierdzaniem. Przygotuj dwa katalogi zadań, które różnią się wyłącznie plikami reguł wbudowanymi w obraz zadania, i uruchom oba. Załaduj CURSOR_API_KEY do środowiska z menedżera sekretów; Harbor przekazuje go do kontenera zadania.
harbor run -p evals/tasks-current -a cursor-cli -m "$CURSOR_MODEL" -k 3 -n 4harbor run -p evals/tasks-proposed -a cursor-cli -m "$CURSOR_MODEL" -k 3 -n 4CURSOR_MODEL podajesz w formacie Harbora provider/model; Harbor przekazuje Cursorowi część po ukośniku, więc użyj nazwy modelu dostępnej w twoim planie Cursora. -k 3 to trzy próby na zadanie, -n 4 – cztery równolegle. Harbor zatwierdza każde polecenie automatycznie, więc jedyną granicą jest kontener zadania: nie wkładaj do niego żadnych poświadczeń poza kluczem Cursora. Układ zadań, przebiegi kontrolne oracle i nop oraz pozostałe flagi opisuje strona o benchmarkach.
Listy modeli Cursora i sposobu wczytywania reguł nie dało się zweryfikować 2026-09-26 (cursor.com był nieosiągalny ze środowiska, w którym powstawał tekst). Przed pierwszym przebiegiem dodaj do obu ramion regułę-kanarka, np. „zakończ każdą końcową wiadomość słowem CANARY”, i sprawdź, czy się pojawia. Plik reguł, który się nie wczytuje, daje idealny remis.
Test A/B w sandboksie z Inspect SWE
Dział zatytułowany „Test A/B w sandboksie z Inspect SWE”Wybierz Inspect SWE, gdy każde uruchomienie ma działać w świeżym kontenerze albo gdy chcesz jednego harnessu dla kilku agentów: agenci claude_code() i codex_cli() działają w sandboksie próbki, a ich wywołania modelu wracają przez Inspect. Dzięki temu limity tokenów i czasu oraz transkrypty działają jak w każdej ewaluacji Inspect, a klucz API nigdy nie trafia do kontenera.
from pathlib import Path
from inspect_ai import Task, taskfrom inspect_ai.dataset import json_datasetfrom inspect_ai.scorer import CORRECT, INCORRECT, Score, Target, accuracy, scorer, stderrfrom inspect_ai.solver import Generate, TaskState, solverfrom inspect_ai.util import sandboxfrom inspect_swe import claude_code
@solverdef install_rules(rules_file: str): async def solve(state: TaskState, generate: Generate) -> TaskState: await sandbox().write_file("/repo/CLAUDE.md", Path(rules_file).read_text()) return state return solve
@scorer(metrics=[accuracy(), stderr()])def tests_pass(): async def score(state: TaskState, target: Target) -> Score: result = await sandbox().exec(["npm", "test", "--silent"], cwd="/repo") return Score(value=CORRECT if result.success else INCORRECT, explanation=result.stderr[-800:]) return score
@taskdef rules_ab(rules: str = "rules/current.md") -> Task: return Task( dataset=json_dataset("tasks.jsonl"), # one {"id", "input", "target"} per line setup=install_rules(rules), solver=claude_code(cwd="/repo", disallowed_tools=["WebSearch", "WebFetch"]), scorer=tests_pass(), sandbox=("docker", "compose.yaml"), # image with the repository at /repo, deps installed, no secrets epochs=3, )Uruchom każde ramię, a potem porównaj je w przeglądarce logów:
pip install inspect-ai==0.3.269 inspect-swe==0.2.71inspect eval rules_ab.py --model anthropic/claude-opus-5-5 -T rules=rules/current.mdinspect eval rules_ab.py --model anthropic/claude-opus-5-5 -T rules=rules/proposed.mdinspect viewDla Codeksa zaimportuj codex_cli i zapisuj AGENTS.md. W Inspect SWE 0.2.71 codex_cli() domyślnie używa sandbox_mode="danger-full-access" (własny sandbox Codeksa wyłączony) i web_search="live". Pierwsze jest do przyjęcia tylko dlatego, że granicą jest kontener Inspect, więc nie trzymaj w nim żadnych poświadczeń. Obu ramionom przekaż web_search="disabled" – odpowiednik disallowed_tools=["WebSearch", "WebFetch"] po stronie Claude Code – żeby żadne nie mogło wyszukać odpowiedzi w sieci. Pakiet z PyPI instalujesz przez pip install inspect-swe; polecenie z README projektu instaluje wersję deweloperską z gita.
Jak podjąć decyzję na podstawie wyników?
Dział zatytułowany „Jak podjąć decyzję na podstawie wyników?”Zapisz regułę przed uruchomieniem, żeby wyniku nie dało się dopasować do odpowiedzi, której ktoś chciał.
| Wynik | Decyzja |
|---|---|
tests_pass dla proposed co najmniej taki jak dla current, in_scope i ran_tests nie gorsze, koszt na zadanie w granicach 20% | Scal zmianę reguł i wklej tabelę z wynikami obu ramion do pull requesta |
| Proposed wygrywa na części zadań, a na innych przegrywa | Przeczytaj zadania, w których ramiona różnią się we wszystkich trzech powtórzeniach; to jest sygnał, pojedyncze przeskoki to szum. Popraw regułę, która spowodowała przegraną, i uruchom ponownie |
| Równy odsetek zaliczeń, proposed tańszy lub szybszy | Scal: krótszy plik, który zachowuje zachowanie agenta, oszczędza tokeny w każdej sesji |
Proposed gorszy na tests_pass w którymkolwiek zadaniu we wszystkich trzech powtórzeniach | Nie scalaj. Znajdź regułę, którą miał stary plik, a nowy zgubił |
Różni się tylko ocena sędziego conventions | Traktuj to jako wskazówkę, a nie werdykt, dopóki sędzia nie zostanie skalibrowany na twoich etykietach (kontrole oceniane przez model) |
Wiersz 4 ma pierwszeństwo przed wierszem 1: stała przegrana w którymkolwiek zadaniu blokuje scalenie, nawet gdy ogólny odsetek zaliczeń jest taki sam lub wyższy.
Kontrole deterministyczne mają pierwszeństwo przed sędzią. Sędzia, który lubi dłuższe końcowe wiadomości, nagrodzi rozwlekły plik reguł, i tak właśnie regresja trafia do main z lepszym wynikiem.
Gdzie w pętli pasują platformy śledzenia
Dział zatytułowany „Gdzie w pętli pasują platformy śledzenia”Stały zestaw zadań mówi, czy zmiana pomaga. Ślad mówi, dlaczego jedno zadanie się nie udało: który plik agent przeczytał jako pierwszy, którą regułę zacytował, w którym miejscu się poddał. Dodaj śledzenie, gdy ewaluacja pokazuje przegraną, której nie da się wyjaśnić z końcowej wiadomości.
Oficjalny plugin śledzi prompty, tury, generacje modelu z użyciem tokenów i kosztem, wywołania narzędzi, skille i subagentów dla CLI claude i aplikacji desktopowej w trybie Code. Wymaga uv w PATH.
claude plugin marketplace add langfuse/Claude-Observability-Pluginclaude plugin install langfuse-observability@langfuse-observabilityPotem skonfiguruj klucze z wnętrza sesji poleceniem /plugin configure langfuse-observability@langfuse-observability; klucz tajny trafia do systemowego pęku kluczy, nie do pliku. Uruchom Claude Code ponownie. Jeśli ślad się nie pojawia, przeczytaj ~/.claude/state/langfuse_hook.log. Na śledzonych sesjach Langfuse może potem uruchamiać zbiory danych i ewaluacje typu LLM-as-judge.
CLI bt instaluje plugin i lokalnego demona śledzenia dla Claude Code, Codeksa, OpenCode, Pi, Groka i Antigravity. Każda sesja staje się jednym śladem ze spanami tur, wywołań modelu, narzędzi i subagentów.
curl -fsSL https://bt.dev/cli/install.sh | bash # Windows and mise installs: README of braintrustdata/btbt loginbt trace enable claude --project rules-abbt trace doctor claudebt trace run --project rules-ab --additional-metadata '{"arm":"proposed"}' claude -- -p "Fix the invoice rounding bug in src/billing"Plugin nie redaguje lokalnie promptów, wejścia i wyjścia narzędzi ani promptów systemowych. Skonfiguruj redakcję w Braintrust, zanim włączysz śledzenie na prawdziwym repozytorium.
Opik (Comet, Apache-2.0, możliwy self-hosting) łączy się z Claude Code, Codeksem, Cursorem i innymi przez MCP, więc możesz poprosić agenta o ocenę jego ostatnich śladów:
pip install opik && opik configureuvx opik mcp configureArize Phoenix daje lokalny interfejs śladów OpenTelemetry i ewaluacji bez konta: pip install arize-phoenix && phoenix serve. Podłączenia sesji samego Claude Code do Phoenixa nie dało się zweryfikować 2026-09-26; używaj go do śladów emitowanych przez twoją aplikację.
Koszt kontekstu: promptfoo, Inspect i bt trace run działają poza twoimi interaktywnymi sesjami i nic nie dodają do ich kontekstu. Pluginy Langfuse i Braintrust działają przez hooki; po instalacji uruchom claude plugin details <plugin>, żeby zobaczyć prognozowany koszt tokenów każdego dodanego komponentu. Serwer MCP Opika dodaje definicje narzędzi do każdej sesji, która go wczytuje, więc zmierz go przez /context przed i po.
Do funkcji LLM we własnej aplikacji, a nie do agenta kodującego, służą inne narzędzia: DeepEval (deepeval test run test_chatbot.py) blokuje funkcję w CI asercjami w stylu pytest, garak (pip install garak) sonduje endpoint modelu pod kątem jailbreaków, prompt injection i wycieków, a OpenLLMetry (pip install traceloop-sdk, potem Traceloop.init()) instrumentuje aplikację przez OpenTelemetry. Żadne z tych trzech nie śledzi agenta kodującego. Starsze repozytorium openai/evals odsyła teraz do ewaluacji w panelu OpenAI; jego pakiet PyPI evals ostatnio wydano w maju 2024.
Prompty do skopiowania dla ewaluacji agentów
Dział zatytułowany „Prompty do skopiowania dla ewaluacji agentów”Skąd wiadomo, że sama ewaluacja działa?
Dział zatytułowany „Skąd wiadomo, że sama ewaluacja działa?”Ewaluacja, która nie może oblać, to tautologia z pozycją kosztową. Zanim zaufasz wynikowi, udowodnij, że harness wykrywa różnicę:
- Reguła-kanarek. Dodaj nieszkodliwą regułę tylko do jednego ramienia („zakończ końcową wiadomość słowem CANARY-B”) i uruchom jedno zadanie. Jeśli znacznik się nie pojawi, plik reguł się nie wczytuje.
- Wariant celowo zły. Uruchom raz z proponowanym plikiem, który każe agentowi nie uruchamiać testów.
ran_tests, a zwykle takżetests_pass, muszą spaść. Jeśli nie spadają, kontrole są za słabe; zobacz siłę wyroczni. - Sędzia od innego dostawcy. Ramię agenta nigdy nie ocenia samo siebie: konfiguracja powyżej wysyła
llm-rubricdo modelu innego dostawcy. Skalibruj go na 20 ręcznie oznaczonych wynikach, zanim pozwolisz mu blokować scalenie. - Powtarzaj przy każdej zmianie modelu. Plik reguł dostrojony do jednego modelu może pogorszyć wyniki na następnym. Plan oceny nowego modelu zaczyna się właśnie od ponownego uruchomienia tego zestawu zadań.
Odpowiedzialność: programista, który proponuje zmianę reguł, uruchamia test A/B i dołącza tabelę wyników obu ramion do pull requesta jako część pakietu dowodów. Tech lead jest właścicielem zestawu zadań, przegląda tabelę zamiast prozy nowego pliku i zatwierdza scalenie.
Co się psuje przy ewaluacji reguł agenta?
Dział zatytułowany „Co się psuje przy ewaluacji reguł agenta?”| Objaw | Przyczyna | Naprawa |
|---|---|---|
| Oba ramiona mają identyczne wyniki w każdym zadaniu | Brak setting_sources, więc żadne ramię nie czyta CLAUDE.md | Dodaj setting_sources: ['project']; potwierdź regułą-kanarkiem |
| Ramię proposed nadal stosuje regułę, którą usunąłeś | Worktree wewnątrz repozytorium: Claude Code wczytuje też CLAUDE.md z katalogu nadrzędnego | Umieść oba worktree poza repozytorium, jak w kroku 2 |
| Prywatne preferencje zmieniają wyniki na jednym laptopie | user w setting_sources wczytuje ~/.claude/CLAUDE.md | Używaj tylko ['project'] |
| Drugi przebieg kończy się w kilka sekund z tymi samymi wynikami | promptfoo podało odpowiedzi z cache | Przy ewaluacji agentów zawsze dodawaj --no-cache |
| Testy przechodzą w jednym ramieniu dzięki edycjom z drugiego | Równoległe przebiegi albo brak resetu między testami | -j 1 i hook reset.js |
| Wyniki tego samego zadania skaczą między przebiegami | Jedno uruchomienie na zadanie albo mniej niż 10 zadań | --repeat 3 i więcej zadań; decyduj tylko na podstawie powtarzalnych różnic |
Ramię Codeksa ignoruje AGENTS.md | Ścieżka worktree niezaufana (Codex 0.150.0 i nowsze) | Oznacz obie ścieżki ewaluacji jako zaufane; potwierdź regułą-kanarkiem |
| Jedno zadanie przepala budżet | Pętla nieudanych wywołań narzędzi | max_turns i max_budget_usd na providera; --max-cost-usd dla claude plugin eval |
| Wyniki różnią się między poniedziałkiem a piątkiem | Zmienił się model domyślny | Przypnij model w obu ramionach i uruchamiaj oba ramiona razem |
| Ślady pokazują klucze API i zawartość plików w interfejsie dostawcy | Braintrust i Langfuse zapisują prompty i wyjście narzędzi | Najpierw skonfiguruj redakcję; śledź oczyszczone repozytorium testowe |
Co dalej z ewaluacją agentów
Dział zatytułowany „Co dalej z ewaluacją agentów”Żeby uruchamiać ten zestaw zadań przy każdej zmianie harnessu, a nie raz na PR, zobacz ciągłe ewaluacje.
Zanim zmienisz plik reguł, przeczytaj, jak pisać i odchudzać CLAUDE.md; ta strona powie ci, czy odchudzona wersja nadal działa. Produkcyjną stronę tych samych danych opisuje obserwowalność agentów. Hub sekcji, mierzenie inżynierii agentowej, zestawia ewaluacje z telemetrią, śledzeniem kosztów, botami do review i bramkami bezpieczeństwa.