Przejdź do głównej zawartości

API z Codex: najpierw kontrakt, weryfikacja po stronie maszyn

Budowanie API z Codex działa najlepiej od kontraktu: człowiek przegląda krótki plik OpenAPI 3.1, Codex implementuje jeden wycinek endpointów na zadanie we własnym Git worktree, a bramki maszynowe (Redocly lint, testy, fuzzing Schemathesis i codex review) dowodzą, że handlery zgadzają się z kontraktem. Recenzent czyta kontrakt i wynik bramek, nie każdy handler.

Poprosiłeś Codex o „API zaproszeń” i w jednym podejściu dostałeś 1400 linii w 19 plikach. Testy są zielone, ale Codex napisał je w tej samej sesji co handlery, więc zgadzają się z kodem, a nie z tym, czego oczekuje zespół frontendu, i nikt bez czytania handlera nie powie, czy duplikat zaproszenia zwraca 409 czy 422. Ta strona jest dla programisty, który buduje endpointy, i dla tech leada, który ma je zatwierdzić bez czytania wszystkich 19 plików.

Wersję tej metody dla wszystkich narzędzi, z GraphQL, gRPC, wersjonowaniem i testami obciążeniowymi, opisuje strona rozwój API z AI. Tutaj znajdziesz to, co specyficzne dla Codex: jak podzielić pracę na zadania Codex, które polecenia Codex obsługują każdy krok i gdzie piaskownica Codex zmienia plan.

  • Sekcję AGENTS.md, która przekazuje Codex twoje konwencje API i dokładne polecenia bramek.
  • Pętlę w pięciu krokach: kontrakt, commit, jedno zadanie w worktree na wycinek, bramki, review.
  • Trzy prompty do skopiowania: szkic kontraktu, implementacja wycinka zgodnie z kontraktem i naprawa błędu wykrytego przez fuzzing kontraktu.
  • Skrypt bramki, który sprawdza implementację względem specyfikacji bez czytania handlerów.
  • Typowe awarie API budowanego przez agenta i sposób wyjścia z każdej z nich.

Sens podejścia od kontraktu polega na przeniesieniu uwagi na najmniejszy artefakt, który definiuje zachowanie. Plik OpenAPI na 150 linii dla pięciu endpointów da się rzetelnie przejrzeć. 1400 linii kodu za nim już nie.

ArtefaktKto sprawdzaJak
api/openapi.yaml (kontrakt)Ty, linia po linii, oraz właściciel API przez CODEOWNERSReview małego diffu w pull requeście
Poprawność kontraktuMaszynanpx @redocly/cli lint api/openapi.yaml
Handlery, walidacja, zapytaniaMaszynaSprawdzanie typów, testy jednostkowe i integracyjne
Zgodność handlerów z kontraktemMaszynaschemathesis run na działającym serwerze
Ryzykowna logika (autoryzacja, pieniądze, usuwanie danych)Recenzent Codex, potem ty, tylko w oznaczonych plikachcodex review --base main, sterowany wytycznymi review z AGENTS.md

Ktoś nadal podpisuje się pod wynikiem: programista, do którego należy gałąź, czyta diff kontraktu i wynik bramek, a właściciel API zatwierdza każdą zmianę w api/openapi.yaml. Nikt natomiast nie czyta każdego handlera, żeby dowiedzieć się, co robi API.

Codex czyta AGENTS.md, zanim zacznie pracę, więc zapisane tam konwencje obowiązują w każdym zadaniu bez powtarzania ich w promptach. Najpierw zainstaluj linter kontraktu jako zależność deweloperską poleceniem npm install -D @redocly/cli, żeby sesja Codex w piaskownicy mogła go uruchomić bez dostępu do sieci. Następnie dodaj taką sekcję do AGENTS.md w katalogu głównym repozytorium. Stos w przykładzie to Express, TypeScript, Zod, Drizzle ORM i Vitest z supertest; podmień polecenia na swoje.

## API conventions
- The contract is api/openapi.yaml (OpenAPI 3.1). It is the source of truth.
Implementation tasks never edit it. If the contract looks wrong, stop and say so.
- Handlers live in src/routes/<resource>/, business logic in src/services/,
queries in src/lib/db/queries/. Handlers stay thin: parse, call the service, map errors.
- Validate every request body and query with Zod before it reaches a service.
- Error body is always { "error": { "code": string, "message": string, "details"?: object } }.
400 = malformed request, 401 = no or bad credentials, 403 = authenticated but not allowed,
404 = not found or not visible to this caller, 409 = conflict with current state, 422 = valid shape, invalid values.
- List endpoints use cursor pagination: ?cursor=&limit= (default 20, max 100), response { items, nextCursor }.
- No console.log; use the logger from src/lib/logger.ts.
## API gates (run all before saying a task is done)
- npm run typecheck
- npm run lint
- npm test # Vitest, including supertest integration tests
- npx @redocly/cli lint api/openapi.yaml
## Review guidelines
- Check every changed handler against api/openapi.yaml: status codes, error body shape,
required fields, auth on each route and pagination limits.
- Flag any endpoint without integration tests for its 401, 403 and 404 cases,
and any list or read endpoint without a cross-team access test.

Większość pracy wykonują w tym bloku trzy elementy. Pierwsza reguła czyni kontrakt tylko do odczytu dla zadań implementacyjnych, więc agent nie dopasuje specyfikacji do swojego kodu. Lista kodów statusu kończy zgadywanie „409 czy 422”, które inaczej różni się między endpointami. Codex czyta własne reguły review z AGENTS.md, który wczytuje przy każdym review, także przy codex review w terminalu i @codex review na GitHubie; nagłówek ## Review guidelines tylko trzyma te reguły w jednym miejscu. Jak utrzymać ten plik w budżecie instrukcji Codex, gdy rośnie, opisuje strona optymalizacja AGENTS.md i skilli dla Codex.

Opcjonalnie możesz dać Codex aktualną dokumentację bibliotek przez serwer MCP, żeby pisał kod Zod 4 i Drizzle pod dzisiejsze API, a nie pod starsze wersje, które pamięta. Jednym z takich serwerów jest Context7 (@upstash/context7-mcp 4.1.1 w npm, 2026-09-26):

Okno terminala
codex mcp add context7 -- npx -y @upstash/context7-mcp
codex mcp list

Każdy podłączony serwer dokłada definicje narzędzi do kontekstu, więc dodaj go wtedy, gdy nieaktualne API bibliotek to realny problem, a nie domyślnie. Zawężanie i weryfikację serwerów opisują strony konfiguracja serwerów MCP w Codex i przewodnik po Context7.

Przykład to API zaproszeń do zespołu z pięcioma endpointami. Każdy krok mówi, które polecenie Codex go wykonuje.

  1. Naszkicuj kontrakt w sesji interaktywnej. Utwórz gałąź, na przykład api/invitations-contract, uruchom codex w repozytorium i wklej pierwszy prompt poniżej. Codex zapisuje wyłącznie api/openapi.yaml, sprawdza go linterem i wypisuje otwarte pytania. Odpowiadasz na nie i poprawiasz plik, aż opisuje API, którego chcesz. To jedyny plik, który czytasz linia po linii.

  2. Zatwierdź kontrakt w osobnym pull requeście. Otwórz pull request, który zawiera tylko kontrakt. Zespół frontendu i inni konsumenci API przeglądają go na tym etapie, kiedy zmiana kosztuje minuty. Scal go przed rozpoczęciem implementacji, żeby każde zadanie implementacyjne startowało od zatwierdzonego kontraktu.

  3. Implementuj jeden wycinek na zadanie w worktree. Wycinek to jeden lub dwa endpointy wdrażane razem, na przykład „tworzenie i lista zaproszeń”. Każdy wycinek zaczynaj od scalonego kontraktu we własnym worktree, żeby równoległe wycinki nie nadpisywały się nawzajem:

    Okno terminala
    git fetch origin
    git worktree add -b api/invitations-create-list ../myapp-inv-create-list origin/main
    cd ../myapp-inv-create-list
    npm ci # instaluj we własnym terminalu: piaskownica workspace-write nie ma sieci
    codex

    codex --worktree tworzy zamiast tego zarządzany worktree, ale startuje on na odłączonym HEAD, bez twoich plików .env i bez node_modules. Kompromisy i skrypt przygotowujący worktree znajdziesz na stronie izolowane zadania Codex w Git worktrees. Wklej drugi prompt poniżej i podaj w nim nazwę wycinka.

  4. Uruchom bramki samodzielnie. Gdy Codex zgłosi, że wycinek jest gotowy, uruchom w worktree skrypt bramki z następnej sekcji. Podsumowanie Codex to deklaracja, kody wyjścia to dowód.

  5. Zrób review względem kontraktu i otwórz pull request. Uruchom review gałęzi w Codex. Czyta ono AGENTS.md, w tym powyższe reguły review, więc sprawdza handlery względem kontraktu:

    Okno terminala
    codex review --base main

    W Codex CLI 0.157.1 flagi --base nie da się połączyć z argumentem z własnymi instrukcjami (codex review --base main "..." kończy się błędem argumentów), dlatego kontrole zgodności z kontraktem zapisujesz w AGENTS.md, a nie w wierszu poleceń. Czytaj tylko pliki oznaczone w review, napraw lub odrzuć każde zgłoszenie, a potem wypchnij gałąź i otwórz pull request. CI uruchamia te same bramki, jak opisano w CI/CD z Codex. Warstwową konfigurację review (hook pre-push, @codex review na GitHubie) opisuje strona code review z Codex.

Zdanie „najpierw testy, pokaż, że nie przechodzą” ma znaczenie. Testy pisane po handlerze zwykle sprawdzają to, co handler robi; testy pisane z kontraktu, które najpierw widziałeś czerwone, sprawdzają to, co mówi kontrakt. Dlaczego dzięki temu zestawowi testów można ufać, wyjaśnia strona jak silna jest twoja wyrocznia?.

Jak zweryfikować wycinek API bez czytania każdego handlera?

Dział zatytułowany „Jak zweryfikować wycinek API bez czytania każdego handlera?”

Uruchom ten skrypt w worktree wycinka, gdy Codex skończy, oraz w CI przy każdym pull requeście; w CI pobieraj repozytorium z pełną historią (na przykład fetch-depth: 0), żeby origin/main...HEAD dało się rozwiązać. Zatrzymuje się na pierwszym błędzie. Najpierw uruchom serwer na jednorazowej testowej bazie danych w osobnym terminalu (na przykład npm run dev:test), bo na serwerze uruchomionym w piaskownicy agenta nie warto polegać. Przed fuzzingiem skrypt odpytuje $BASE_URL/health, więc daj serwerowi endpoint liveness albo wskaż istniejący w zmiennej HEALTH_URL.

#!/usr/bin/env bash
# api-gate.sh: dowód, że wycinek API zgadza się z api/openapi.yaml. Uruchamiaj w katalogu głównym worktree.
set -euo pipefail
BASE_URL="${BASE_URL:-http://localhost:3000}"
# 1. Gałąź zmienia kontrakt albo implementację, nigdy jedno i drugie.
CHANGED=$(git diff --name-only origin/main...HEAD)
if grep -qx 'api/openapi.yaml' <<<"$CHANGED" && grep -q '^src/' <<<"$CHANGED"; then
echo "contract and implementation changed on one branch: split the contract into its own PR" >&2
exit 1
fi
# 2. Kontrakt jest poprawny, a kod się buduje, przechodzi lint i własne testy.
npx @redocly/cli lint api/openapi.yaml
if [[ "$CHANGED" == "api/openapi.yaml" ]]; then
echo "contract-only change: no handlers to test yet, stopping after the lint"
exit 0
fi
npm run typecheck
npm run lint
npm test
# 3. Działający serwer zgadza się z kontraktem dla operacji tego wycinka: wygenerowane żądania, wszystkie kontrole.
OPERATIONS="${OPERATIONS:?set OPERATIONS to the slice operationIds, e.g. createInvitation,listInvitations}"
INCLUDE=()
IFS=',' read -ra IDS <<<"$OPERATIONS"
for id in "${IDS[@]}"; do INCLUDE+=(--include-operation-id "$id"); done
HEALTH_URL="${HEALTH_URL:-$BASE_URL/health}"
curl -sf "$HEALTH_URL" > /dev/null || { echo "server not answering at $HEALTH_URL" >&2; exit 1; }
schemathesis run api/openapi.yaml \
--url "$BASE_URL" \
"${INCLUDE[@]}" \
--checks all \
--header "Authorization: Bearer ${TEST_API_TOKEN:?set TEST_API_TOKEN to a test-user token}" \
--report junit --report-dir reports/schemathesis

Co wyłapuje każdy etap:

  • Etap 1 blokuje częsty sposób, w jaki agent „spełnia” kontrakt: edycję kontraktu na tej samej gałęzi co kod. Pull requesty z kontraktem (krok 2) zmieniają tylko api/openapi.yaml, więc przechodzą etap 1, a skrypt kończy pracę po lincie Redocly: pull request z samym kontraktem nie ma jeszcze handlerów, więc etapy 2 i 3 nie mają czego sprawdzać. Gałąź implementacyjna, która dotyka kontraktu, odpada. Strona ochrona wyroczni wyjaśnia, dlaczego ta kontrola musi leżeć poza zasięgiem agenta, na przykład jako wymagany job CI, którego agent nie może edytować.
  • Etap 2 wyłapuje błędy typów, naruszenia lintera i błędy w testach napisanych przez Codex. Nie wyłapie testu, który sprawdza niewłaściwą rzecz.
  • Etap 3 to niezależna kontrola. Schemathesis (4.28.0 w PyPI, 2026-09-26; instalacja przez pip install schemathesis albo uruchomienie przez uvx schemathesis) czyta specyfikację, generuje poprawne i niepoprawne żądania i sprawdza względem niej kody statusu, schematy odpowiedzi, typy treści i nagłówki. Kontrola ignored_auth wykrywa endpointy, które nadal odpowiadają sukcesem, gdy pominiesz dane uwierzytelniające wymagane przez specyfikację, a negative_data_rejection wskazuje handlery przyjmujące dane, których specyfikacja zabrania. Tych kontroli nie napisał Codex, więc nie mają tych samych martwych punktów co on. Zmienna OPERATIONS zawęża przebieg do recenzowanego wycinka: jedna flaga --include-operation-id na każdy identyfikator (Schemathesis 4.28.0 przyjmuje też --include-path, --include-method i --include-tag). Bez niej Schemathesis testuje każdą operację z kontraktu i każdy pull request z wycinkiem odpada na endpointach innych wycinków, które do czasu implementacji zwracają 404. W CI ustawiaj OPERATIONS osobno dla każdego pull requesta, na przykład na podstawie etykiety albo wiersza w opisie pull requesta.

Trzymaj TEST_API_TOKEN w powłoce albo w magazynie sekretów CI, nigdy w skrypcie. Kieruj BASE_URL wyłącznie na środowisko lokalne lub jednorazowe: Schemathesis wysyła dużo wygenerowanych żądań, w tym wywołania POST, które tworzą i zmieniają dane.

Gdy etap 3 zawiedzie, nie naprawiaj błędu ręcznie i nie pozwól Codexowi poluzować kontroli. Przekaż Codexowi raport:

Która powierzchnia Codex pasuje do którego kroku API?

Dział zatytułowany „Która powierzchnia Codex pasuje do którego kroku API?”

Wszystkie kroki da się wykonać w Codex CLI (0.157.1 na 2026-09-26). Pozostałe powierzchnie pasują do konkretnych kroków.

KrokDobry wybórDlaczego
Szkic kontraktucodex (interaktywnie) albo aplikacja desktopowaPytania i poprawki iterujesz razem z agentem
Implementacja wycinkacodex w katalogu z git worktree add albo codex --worktreeIzolacja na wycinek; zob. worktrees
Kilka wycinków narazJeden worktree na wycinek, scalane po koleiKoordynację opisuje strona wieloagentowe przepływy pracy w Codex
Reviewcodex review --base main albo /review w sesjiStosuje własne reguły review z AGENTS.md
Skryptowe kontrole w CIcodex exec z --output-schemaWynik zgodny ze schematem, który job może odczytać; zob. Codex w trybie nieinteraktywnym
Wątki w aplikacji desktopowejcodex app (macOS i Windows)Opcja worktree dla każdego wątku; zob. aplikacja desktopowa Codex dla zaawansowanych

Zacznij od domyślnego modelu Codex, zwiększ wysiłek rozumowania, zanim zmienisz model, i zmieniaj go dopiero wtedy, gdy przemawiają za tym twoje własne wyniki. Aktualny model domyślny i alternatywy znajdziesz w przeglądzie modeli.

Codex edytuje api/openapi.yaml, żeby jego handlery przeszły. Etap 1 bramki zawodzi. Przywróć zatwierdzony kontrakt poleceniem git checkout origin/main -- api/openapi.yaml, uruchom ponownie testy i przekaż Codexowi błędy z przypomnieniem, że kontrakt jest tylko do odczytu. Jeśli kontrakt naprawdę jest błędny, popraw go w osobnym pull requeście z kontraktem i zrób rebase wycinka na tę zmianę.

Schematy Zod rozjeżdżają się z kontraktem. Handlery walidują przez Zod, kontrakt mówi co innego, a etap 3 zgłasza błędy negative_data_rejection albo positive_data_acceptance. Wybierz jedno źródło prawdy. Albo generuj schematy Zod z kontraktu, albo generuj kontrakt z Zod biblioteką taką jak zod-openapi i porównuj wynik w CI. Nie utrzymuj obu ręcznie.

Testy przechodzą w twoim katalogu roboczym, a w worktree nie. Nowy worktree nie ma node_modules, ignorowanych przez Git plików .env ani testowej bazy danych. Uruchom npm ci i przygotowanie bazy we własnym terminalu przed startem Codex; piaskownica workspace-write nie ma sieci, więc instalacja zlecona Codex się nie powiedzie. Zarządzany worktree z codex --worktree startuje dodatkowo na odłączonym HEAD: utwórz gałąź, zanim Codex zrobi commit, inaczej commity nie będą należały do żadnej gałęzi.

Codex ignoruje konwencje z AGENTS.md. Od Codex 0.150.0 niezaufany projekt nie dostarcza swojego projektowego AGENTS.md. Upewnij się, że projekt jest zaufany, a potem sprawdź, co faktycznie się wczytało, poleceniem codex debug prompt-input, jak pokazuje strona optymalizacja AGENTS.md i skilli dla Codex.

Luki w autoryzacji, których nie łapie żaden test. Codex testuje role, które wymieniłeś, i pomija te, których nie wymieniłeś. Klasyczne przeoczenie to administrator zespołu A czytający zaproszenia zespołu B. Kontrola ignored_auth w Schemathesis wyłapuje brak uwierzytelnienia, a nie błędną autoryzację, więc proś wprost o testy dostępu między zespołami (prompt wycinka powyżej to robi) i trzymaj tę kontrolę w wytycznych review w AGENTS.md.

Testy limitów zapytań są niestabilne. Testy, które czekają na prawdziwe okno czasowe, losowo zawodzą na wolnych runnerach CI. Każ Codexowi wstrzykiwać zegar i limit przez konfigurację, tak żeby test ustawiał limit na 3, wysyłał 4 żądania i oczekiwał 429 z nagłówkiem Retry-After, bez usypiania.

Schemathesis pada na pierwszym żądaniu z kodem 401. Tokenu brakuje, wygasł albo należy do użytkownika bez dostępu. Sprawdź TEST_API_TOKEN jednym wywołaniem curl na chronionym endpoincie, zanim zaczniesz podejrzewać handlery.

Dokąd dalej po pierwszym wycinku API zbudowanym z Codex

Dział zatytułowany „Dokąd dalej po pierwszym wycinku API zbudowanym z Codex”