Przejdź do głównej zawartości

Codex w CI/CD z GitHub Action

Codex GitHub Action, czyli openai/codex-action@v1, instaluje Codex CLI na runnerze GitHub Actions i uruchamia codex exec z promptem zapisanym w repozytorium. Nadaje się do czterech zadań CI: komentarzy z review PR, bramki na ustrukturyzowanych wynikach, szkicu release notes i automatycznej naprawy CI. Bezpieczeństwo zapewniają safety-strategy, profil uprawnień oraz rozdzielenie uprzywilejowanych kroków na osobne joby.

Ta strona jest dla dewelopera lub tech leada, który odpowiada za pipeline. Twoje CI uruchamia już lint, sprawdzanie typów i testy. Nie wyłapie jednak endpointu bez uwierzytelniania, zapytania sklejanego ze stringów ani 400-liniowej funkcji, o którą nikt nie prosił, więc recenzenci wciąż szukają tego ręcznie. Chcesz, żeby Codex przejrzał każdy PR, zanim zrobi to człowiek, ale bez oddawania agentowi tokena z prawem zapisu do repozytorium.

  • Cztery workflowy do skopiowania: komentarz z review PR, bramkę, która oblewa build przy znaleziskach P0, szkic release notes oraz auto-fix CI otwierający draft PR.
  • Pliki promptów i schematów w .github/codex/, dzięki czemu kryteria review są wersjonowane i przeglądane jak kod.
  • Utwardzoną konfigurację: drop-sudo, profil uprawnień, persist-credentials: false, niezaufane wartości przekazywane przez env: i wynik agenta przekazywany do osobnego joba, zanim cokolwiek zostanie zapisane.
  • Sposób na decyzję, kiedy znaleziska Codex mogą blokować merge — na podstawie zmierzonej precyzji, a nie zaufania.

Wybieraj według tego, co job może zmienić. Im więcej może zapisać, tym większą część pipeline’u rozdzielasz na osobne joby.

JobWyzwalaczProfil uprawnieńCo Codex może zmienićKto zatwierdza
Komentarz z review PRpull_request:read-onlyNic; komentarz publikuje drugi jobRecenzent PR
Bramka na znaleziskachpull_request:read-onlyNic; drugi job oblewa build przy P0Właściciel .github/codex/ w CODEOWNERS
Release notespush tagu:read-onlyNic; drugi job tworzy szkic wydaniaRelease manager, który je publikuje
Auto-fix CIworkflow_run:workspaceTylko checkout; drugi job otwiera draft PRRecenzent draft PR

Jeśli chcesz tylko komentarzy z review i nie potrzebujesz kontroli nad promptem, README akcji odsyła do zarządzanego code review w Codex cloud; zobacz code review z Codex. W systemach CI innych niż GitHub Actions wywołuj codex exec bezpośrednio, jak opisuje strona tryb headless i nieinteraktywny.

  1. Utwórz klucz API OpenAI przeznaczony wyłącznie dla CI i zapisz go jako sekret repozytorium OPENAI_API_KEY (Settings > Secrets and variables > Actions). Osobny klucz możesz zrotować albo ograniczyć bez ruszania czyjegokolwiek laptopa.

  2. Utwórz .github/codex/prompts/ i .github/codex/schemas/, a potem dodaj je do CODEOWNERS. Przy uruchomieniach wyzwalanych przez pull_request plik workflow, prompt i schemat pochodzą z merge commita PR-a, więc PR może osłabić własne review, jeśli zmiany w tych plikach nie wymagają zgody właściciela. Następnie włącz Require review from Code Owners w regule ochrony gałęzi albo w rulesecie dla gałęzi domyślnej; bez tego CODEOWNERS tylko prosi o review:

    # .github/CODEOWNERS
    /.github/ @your-org/platform
  3. Na początek zostaw model i effort puste. Akcja użyje wtedy domyślnych ustawień Codex CLI: GPT-6 Astra z poziomem rozumowania (effort) low w CLI 0.157.1 (zobacz przegląd modeli). Jeśli review są płytkie, najpierw podnieś effort, a dopiero potem zmieniaj model.

  4. Nie przypinaj codex-version poniżej 0.138.0. Profile uprawnień, których używa każdy workflow na tej stronie, wymagają tej wersji lub nowszej.

Ten workflow ma kształt przykładu z README akcji, z kilkoma zmianami: prompt leży w pliku, tytuł i opis PR-a nie trafiają do promptu, a Codex działa z profilem :read-only zamiast :workspace, bo review nigdy nie musi niczego zapisywać. Krok wstępnego pobierania refów z README zastępuje tu fetch-depth: 2, do zdarzenia opened z README dochodzą synchronize, reopened i ready_for_review, a workflow ma też grupę concurrency, pomijanie draftów i timeout-minutes (zobacz typowe awarie niżej). Przykład z README wciąż używa actions/checkout@v5 i actions/github-script@v7; ta strona używa aktualnych wersji głównych: actions/checkout@v7, actions/github-script@v9 i odpowiadających im akcji artefaktów (sprawdzone 2026-10-03). Zanim skopiujesz workflow, zastąp je wersjami przypiętymi w twojej organizacji.

.github/workflows/codex-review.yml
name: Codex PR review
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
concurrency:
group: codex-review-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
codex:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
outputs:
final_message: ${{ steps.run_codex.outputs.final-message }}
steps:
- uses: actions/checkout@v7
with:
ref: refs/pull/${{ github.event.pull_request.number }}/merge
fetch-depth: 2
persist-credentials: false
- name: Run Codex
id: run_codex
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/review.md
permission-profile: ":read-only"
post_feedback:
runs-on: ubuntu-latest
needs: codex
if: needs.codex.outputs.final_message != ''
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/github-script@v9
env:
CODEX_FINAL_MESSAGE: ${{ needs.codex.outputs.final_message }}
with:
github-token: ${{ github.token }}
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: process.env.CODEX_FINAL_MESSAGE,
});

Bezpieczeństwo opiera się na trzech szczegółach. Job codex ma tylko contents: read, a job z prawem zapisu nigdy nie uruchamia Codex. persist-credentials: false trzyma token poza .git/config, skąd Codex mógłby go odczytać. Żadna niezaufana wartość nie trafia do skryptu: tytuł i opis PR-a zostają poza promptem, a komentarz Codex dociera do github-script przez env: (CODEX_FINAL_MESSAGE), bo GitHub rozwija ${{ }} przed uruchomieniem skryptu i wkleiłby ten tekst wprost w kod.

Zablokuj build przy znaleziskach P0 dzięki ustrukturyzowanemu wynikowi

Dział zatytułowany „Zablokuj build przy znaleziskach P0 dzięki ustrukturyzowanemu wynikowi”

Komentarz ma charakter doradczy. Żeby znaleziska mogły blokować merge, Codex musi zwrócić JSON, który sprawdzi skrypt. Input output-schema-file przekazuje plik JSON Schema do codex exec --output-schema, więc końcowa wiadomość ma stały kształt. (Flaga --output-schema przyjmuje ścieżkę do pliku, a nie JSON wpisany bezpośrednio w wywołanie; jeśli chcesz trzymać schemat w samym workflow, użyj osobnego inputu output-schema).

Zapisz schemat jako .github/codex/schemas/findings.json:

{
"type": "object",
"additionalProperties": false,
"required": ["findings"],
"properties": {
"findings": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["severity", "file", "line", "title", "fix"],
"properties": {
"severity": { "type": "string", "enum": ["P0", "P1", "P2"] },
"file": { "type": "string" },
"line": { "type": "integer" },
"title": { "type": "string" },
"fix": { "type": "string" }
}
}
}
}
}

Następnie uruchamiaj skan na ścieżkach, gdzie przeoczenie kosztuje najwięcej, a wynik sprawdzaj w drugim jobie, którego token nie ma żadnych uprawnień:

.github/workflows/codex-security.yml
name: Codex security gate
on:
pull_request:
paths:
- 'src/routes/**'
- 'src/middleware/**'
- 'src/lib/db/**'
- 'package.json'
jobs:
scan:
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
outputs:
findings: ${{ steps.codex.outputs.final-message }}
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
fetch-depth: 2
- id: codex
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/security.md
output-schema-file: .github/codex/schemas/findings.json
permission-profile: ":read-only"
gate:
runs-on: ubuntu-latest
needs: scan
permissions: {}
steps:
- name: Summarize and fail on P0
env:
FINDINGS: ${{ needs.scan.outputs.findings }}
run: |
echo "$FINDINGS" | jq -r '.findings[] | "- **\(.severity)** `\(.file):\(.line)` \(.title)"' >> "$GITHUB_STEP_SUMMARY"
echo "$FINDINGS" | jq -e '[.findings[] | select(.severity == "P0")] | length == 0'

jq -e kończy się kodem niezerowym, gdy wyrażenie jest fałszywe, więc job gate pada dokładnie wtedy, gdy istnieje znalezisko P0. Jeśli Codex zwróci coś, co nie jest poprawnym JSON-em, jq również zakończy się błędem — i to jest bezpieczny kierunek.

Release notes to dobry pierwszy job, który coś tworzy, bo wynikiem jest szkic publikowany przez człowieka. Codex czyta historię z profilem :read-only, a drugi job z contents: write tworzy szkic wydania z końcowej wiadomości Codex.

.github/workflows/codex-release-notes.yml
name: Codex release notes
on:
push:
tags: ['v*']
jobs:
notes:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
notes: ${{ steps.codex.outputs.final-message }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
persist-credentials: false
- id: codex
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
permission-profile: ":read-only"
prompt: |
Write release notes for tag ${{ github.ref_name }}.
Find the previous tag with `git describe --tags --abbrev=0 HEAD^`
and read `git log --no-merges PREVIOUS..HEAD`, opening diffs where
a commit message is unclear.
Output Markdown only, in Keep a Changelog groups: Added, Changed,
Fixed, Security. One user-facing line per change, no commit hashes.
End with one line: "Suggested bump: major|minor|patch" and why.
draft-release:
runs-on: ubuntu-latest
needs: notes
if: needs.notes.outputs.notes != ''
permissions:
contents: write
steps:
- env:
GH_TOKEN: ${{ github.token }}
NOTES: ${{ needs.notes.outputs.notes }}
run: gh release create "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --draft --title "$GITHUB_REF_NAME" --notes "$NOTES"

Auto-fix to jedyny job, w którym Codex edytuje pliki, dlatego jest podzielony na trzy części: wyzwalacz, który ignoruje forki i własne gałęzie auto-fixu, job Codex, który może pisać tylko w checkoucie, oraz job, który zamienia patch w draft PR, nie uruchamiając żadnego kodu z repozytorium.

.github/workflows/codex-autofix.yml
name: Codex CI autofix
on:
workflow_run:
workflows: ["CI"]
types: [completed]
jobs:
propose-fix:
if: >-
github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_repository.full_name == github.repository &&
!startsWith(github.event.workflow_run.head_branch, 'codex/fix-')
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
actions: read
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.workflow_run.head_sha }}
persist-credentials: false
- name: Save the failing log
env:
GH_TOKEN: ${{ github.token }}
RUN_ID: ${{ github.event.workflow_run.id }}
run: |
mkdir -p .codex-ci && echo ".codex-ci/" >> .git/info/exclude
gh run view "$RUN_ID" --repo "$GITHUB_REPOSITORY" --log-failed > .codex-ci/failure.log
- run: npm ci # the :workspace profile has no network, so install first
- uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
permission-profile: ":workspace"
prompt: |
CI failed. The failing job log is in .codex-ci/failure.log.
Find the root cause and make the smallest change that fixes it.
Do not edit tests to make them pass, do not touch .github/, and do
not refactor unrelated code. Run the failing test command to prove
the fix and leave the change uncommitted in the working tree.
If you cannot fix it with confidence, change nothing and explain
why in your final message.
- name: Build the patch outside Codex
run: |
git add -A
git diff --cached --quiet || git diff --cached --binary --no-renames > "$RUNNER_TEMP/fix.patch"
- uses: actions/upload-artifact@v7
with:
name: codex-fix
path: ${{ runner.temp }}/fix.patch
if-no-files-found: ignore
open-draft-pr:
runs-on: ubuntu-latest
needs: propose-fix
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.workflow_run.head_sha }}
- uses: actions/download-artifact@v8
continue-on-error: true
with:
name: codex-fix
path: ${{ runner.temp }}/codex-fix
- env:
GH_TOKEN: ${{ github.token }}
BASE_BRANCH: ${{ github.event.workflow_run.head_branch }}
RUN_URL: ${{ github.event.workflow_run.html_url }}
run: |
PATCH="$RUNNER_TEMP/codex-fix/fix.patch"
[ -s "$PATCH" ] || { echo "Codex proposed no fix"; exit 0; }
if git apply --numstat "$PATCH" | cut -f3 | grep -q '\.github/'; then
echo "Patch touches .github/; refusing" >&2; exit 1
fi
git apply --check "$PATCH" && git apply "$PATCH"
git switch -c "codex/fix-$GITHUB_RUN_ID"
git add -A
git -c user.name="codex-ci" -c user.email="codex-ci@users.noreply.github.com" commit -m "fix: repair CI failure from $RUN_URL"
git push origin HEAD
gh pr create --draft --base "$BASE_BRANCH" --title "Codex: fix CI failure on $BASE_BRANCH" --body "Proposed by Codex for $RUN_URL. Review the diff and CI before merging."

Patch buduje zwykły krok po zakończeniu pracy Codex, a job open-draft-pr odrzuca każdy patch dotykający .github/ (--no-renames sprawia, że plik przeniesiony do .github/ pojawia się pod nową ścieżką, więc kontrola go widzi), więc job z tokenem do zapisu nigdy nie wykonuje niczego, co napisał Codex. Prompt jest celowo wpisany bezpośrednio w plik workflow. Workflow workflow_run zawsze działa z gałęzi domyślnej, więc takiego promptu nie zmieni gałąź, której CI padło, a prompt-file zostałby odczytany z checkoutu tej gałęzi. Filtr event == 'push' odcina PR-y z forków: wpuściłyby niezaufany kod do joba, który trzyma twój klucz OpenAI. Warto jasno nazwać to, co zostaje: npm ci i testy uruchamiane przez Codex wykonują kod gałęzi, której CI padło, w jobie trzymającym ten klucz. Jest to do przyjęcia tylko dlatego, że filtr ogranicza job do gałęzi wypchniętych do tego repozytorium, a każdy, kto może tu wypchnąć gałąź, i tak sięga po sekrety repozytorium przez workflow uruchamiany na push. Nie rozszerzaj filtra na pull requesty ani forki.

Akcja ma dwa osobne mechanizmy ochrony i potrzebujesz obu. safety-strategy ogranicza proces Codex na runnerze. Profil uprawnień ogranicza polecenia, które Codex uruchamia. Przewodnik bezpieczeństwa OpenAI mówi wprost, że profile nie zastępują safety-strategy akcji (“do not replace the action’s safety-strategy”).

safety-strategyCo robiKiedy używać
drop-sudo (domyślna)Odbiera użytkownikowi runnera sudo przed startem Codex; na Linuksie odbiera też dostęp do należących do roota gniazd w /run, w tym Dockera. Nieodwracalna; na ponownie używanym runnerze self-hosted zmiany przeżywają jobaRunnery GitHub-hosted z Linuksem i macOS, z akcją jako ostatnim krokiem joba
unprivileged-userUruchamia Codex na koncie wskazanym w codex-userRunnery self-hosted z wcześniej utworzonym kontem
read-onlyWymusza starszy sandbox tylko do odczytu; Codex nadal działa jako domyślny użytkownik, który może mieć sudo i odczytać klucz z pamięciRzadko; nie łączy się z profilem uprawnień
unsafeBrak ograniczania uprawnieńTylko runnery Windows, gdzie to jedyna opcja, i tylko z promptami, którym w pełni ufasz

Po stronie poleceń ustaw permission-profile na :read-only w jobach review, bramki i release notes oraz na :workspace w jobach, które edytują checkout. Starszy input sandbox nadal działa, ale README zaleca profil w nowych workflowach, a oba inputy wzajemnie się wykluczają. Pominięcie obu zostawia starszy sandbox workspace-write, szerszy, niż potrzebuje review. Dodatkowe flagi codex exec przekazujesz przez codex-args; akcja odrzuca flagi, które osłabiłyby uprawnienia, zaufanie albo dostawcę modelu. Katalog codex-home jest ładowany jako zaufana konfiguracja bez tej kontroli, więc nigdy nie wskazuj w nim plików z przeglądanego checkoutu.

Równie ważne jest to, kto może wywołać uruchomienie. Domyślnie akcję mogą uruchomić tylko użytkownicy z prawem zapisu do repozytorium. allow-users dodaje wskazanych użytkowników, allow-bots wpuszcza github-actions[bot], a allow-bot-users wymienia jawnie inne zaufane boty (nie akceptuje *). Ustawienie allow-users: "*" w publicznym repozytorium zaprasza obcych do wydawania twojego limitu API. Jeśli podejrzewasz wyciek klucza, unieważnij go na platformie OpenAI, utwórz nowy i podmień sekret.

Jak weryfikować wynik Codex w CI bez czytania każdej linii?

Dział zatytułowany „Jak weryfikować wynik Codex w CI bez czytania każdej linii?”

Traktuj Codex w CI jak kolejny check, którego trafność mierzysz, a nie jak recenzenta, któremu ufasz.

  1. Zacznij od trybu doradczego. Przez kilka tygodni uruchamiaj workflow review jako check niewymagany. Poproś recenzentów, by na każdy komentarz Codex reagowali kciukiem w górę (prawdziwy problem) albo w dół (szum). Policz jedne i drugie i zapisz, jakiej precyzji potrzebujesz, zanim znaleziska zaczną blokować merge.
  2. Blokuj tylko na jobie ustrukturyzowanym. Gdy precyzja osiągnie twój próg, najpierw usuń filtr paths: z workflow (zobacz opis awarii niżej), a potem ustaw w ochronie gałęzi joby scan i gate — a nie review w wolnym tekście — jako wymagane status checki. Wymagaj obu: gdy scan padnie, gate zostaje pominięty, a ochrona gałęzi akceptuje pominięty check. Bramka pada na P0 sprawdzonym względem schematu, czyli na regule, którą da się audytować, a nie na akapicie, który ktoś musi zinterpretować.
  3. Deterministyczne bramki mają pierwszeństwo. Znaleziska Codex uzupełniają lint, sprawdzanie typów i testy, nigdy ich nie zastępują. PR z auto-fixu jest draftem, który musi przejść to samo CI i akceptację człowieka, a wydanie pozostaje szkicem, dopóki ktoś go nie opublikuje.
  4. Zachowuj dowody. Ustaw output-file i wgrywaj go przez actions/upload-artifact z wartością retention-days, żeby móc sprawdzić, co powiedział Codex, gdy przeoczony błąd trafi na produkcję.
  5. Wskaż właścicieli. Właściciel .github/codex/ (CODEOWNERS) zatwierdza zmiany promptów i schematów, a recenzent PR-a zatwierdza merge.

Jak to samo wygląda z perspektywy recenzenta, opisują review PR-a od agenta bez czytania każdej linii i czytanie dowodów zamiast kodu.

Only one of `prompt` or `prompt-file` may be specified. Ustawiłeś oba inputy. Zostaw prompt-file dla wersjonowanych promptów, a prompt dla promptów osadzonych w workflow workflow_run. Odwrotny błąd, Either `prompt` or `prompt-file` must be specified., oznacza, że nie ustawiłeś żadnego.

Failed to read server info from …. Wejście openai-api-key było puste, więc akcja pominęła kroki proxy i nie miała skąd odczytać informacji o serwerze. Sprawdź nazwę sekretu. W PR-ach z forków GitHub w ogóle nie przekazuje sekretów, więc workflow review tam nie zadziała; takie PR-y przeglądaj ręcznie albo niech zaufany maintainer wypchnie gałąź ponownie.

responses-api-proxy did not write server info. Proxy, które trzyma twój klucz API, wystartowało, ale nie zapisało pliku z portem w ciągu 10 sekund. Uruchom job ponownie i sprawdź, czy runner ma dostęp do endpointu Responses API (oraz do adresu responses-api-endpoint, jeśli go ustawiłeś).

Actor '<login>' must have write access to <owner>/<repo>. Detected permission: '<level>'. Użytkownik albo bot, który wywołał uruchomienie, nie ma prawa zapisu do repozytorium. Wariant Actor '<login>' is not a collaborator on <owner>/<repo>; write access is required. oznacza, że konto w ogóle nie jest współpracownikiem repozytorium. Dodaj konto do allow-users lub allow-bot-users tylko wtedy, gdy powierzyłbyś mu swój klucz API.

`permission-profile` and `sandbox` are mutually exclusive. Usuń input sandbox. Ten sam konflikt dotyczy safety-strategy: read-only w połączeniu z profilem.

Expected sudo to be disabled, but sudo succeeded. Wcześniejszy krok przywrócił sudo albo runner nie pozwala na tę zmianę. Na Linuksie nie uruchomisz też akcji drugi raz z promptem w tym samym jobie po drop-sudo; drugie uruchomienie Codex przenieś do nowego joba.

bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted na runnerze self-hosted. Profile uprawnień korzystają z bubblewrap, który wymaga nieuprzywilejowanych przestrzeni nazw użytkownika. Na runnerach GitHub-hosted z Linuksem akcja włącza je sama; na self-hosted musisz to zrobić ty. Testuj na jednorazowym hoście, bo zmiany drop-sudo zachodzą przed tym błędem i mogą przeżyć joba.

Codex nie może odczytać checkoutu przy unprivileged-user. Katalog /home/runner ma uprawnienia 750, więc konto Codex nie dociera do checkoutu w /home/runner/work. W kroku przed akcją dodaj to konto do grupy runner i nadaj jego grupie prawo odczytu $GITHUB_WORKSPACE, tak jak robi to przykład examples/unprivileged-user.yml z repozytorium akcji.

PR z auto-fixu nie ma żadnych checków CI. Pushe i PR-y utworzone z GITHUB_TOKEN nie uruchamiają nowych workflowów, więc CI na drafcie nigdy nie wystartuje. Wypychaj zmiany tokenem instalacji GitHub App albo niech recenzent wypchnie na tę gałąź commit, który uruchomi CI.

Wymagany check bezpieczeństwa nigdy nie raportuje na PR-ze. Workflow pominięty przez filtr paths: zostawia swoje wymagane checki w oczekiwaniu, co blokuje merge. Zanim ustawisz check jako wymagany, usuń filtr paths: na poziomie workflow i pozwól, by prompt zwracał pustą tablicę znalezisk dla PR-ów, które nie dotykają wrażliwych ścieżek.

Komentarz przy każdym pushu zalewa PR. Blok concurrency w workflow review anuluje trwające uruchomienie, gdy przychodzi nowy commit, a warunek draft == false pomija drafty aż do ready_for_review.

Review trwa za długo albo kosztuje za dużo. Ustaw timeout-minutes w każdym jobie Codex, zawęź wyzwalacze przez paths: i trzymaj review jako niewymagane, dopóki nie zasłuży na więcej. Użycie API obciąża klucz, więc śledź je tak, jak opisuje zarządzanie kosztami Codex.