Przejdź do głównej zawartości

Zaawansowana konfiguracja Codex: dostawcy, sandbox i ślad audytowy

Zaawansowana konfiguracja Codex traktuje Codex CLI jak infrastrukturę: ruch do modelu idzie przez bramę, każdy typ zadania ma własny poziom rozumowania, granice sandboxa są przetestowane, zanim agent na nie trafi, a każdy przebieg bez nadzoru zostawia zapis, który sprawdzi skrypt (zdarzenia JSONL i OpenTelemetry).

Wszystko sprawdzono na Codex CLI 0.157.1. Ta strona jest dla programisty albo tech leada, który używa Codex codziennie i musi teraz odpowiedzieć na trudniejsze pytania. Dział bezpieczeństwa chce, żeby ruch do modeli szedł przez firmową bramę. CI uruchamia Codex o drugiej w nocy i nikt nie potrafi powiedzieć, jakie polecenia wykonał ani które pliki zmienił. Kolega skopiował fragment konfiguracji ze starego wpisu na blogu i Codex przestał się uruchamiać.

Co daje konfiguracja Codex na poziomie infrastruktury?

Dział zatytułowany „Co daje konfiguracja Codex na poziomie infrastruktury?”
  • Blok dostawcy, który kieruje Codex przez proxy, Azure OpenAI albo Ollamę, oraz test, który potwierdza, że trasa działa.
  • Osobne profile dla każdego typu zadania (--profile ci, --profile deep) z własnym poziomem rozumowania i szczegółowością odpowiedzi zamiast jednego globalnego kompromisu.
  • Granice sandboxa przetestowane przez codex sandbox, zanim trafi na nie przebieg bez nadzoru.
  • Dwa sprawdzenia jq, które zamieniają strumień zdarzeń JSONL w bramkę pass/fail: nieudane polecenia i pliki zmienione poza dozwolonymi ścieżkami.
  • Eksport OpenTelemetry do własnego kolektora, dzięki czemu ślad audytowy nie zależy od tego, czy ktoś przeczyta transkrypt.

Kolejność ma znaczenie: każdy krok daje następnemu coś do sprawdzenia.

  1. Niech błędy konfiguracji zatrzymują przebieg. Uruchamiaj w CI codex exec --strict-config …, żeby klucz nieznany tej wersji Codex zatrzymał przebieg, zamiast zostać po cichu zignorowany.
  2. Ustal dostawcę. Zdecyduj, dokąd idzie ruch do modelu (bezpośrednio do OpenAI, przez bramę, do Azure, do modelu lokalnego), zanim zaczniesz stroić cokolwiek, co zależy od modelu.
  3. Przetestuj sandbox. Uruchom polecenia potrzebne twoim zadaniom przez codex sandbox i sprawdź, co jest dozwolone, a co zablokowane.
  4. Rozdziel poziom rozumowania według zadań. Ustawienia dla CI, pracy codziennej i głębokiego rozumowania trzymaj w osobnych profilach.
  5. Zapisuj każdy przebieg. Zbieraj wyjście --json, eksportuj zdarzenia OpenTelemetry i buduj na nich bramki.

Podstawy konfiguracji (położenie plików, kolejność warstw, tryby zatwierdzania) opisuje strona Konfiguracja Codex. Ta strona zaczyna się tam, gdzie tamta się kończy.

Jak skierować Codex przez bramę, Azure albo model lokalny?

Dział zatytułowany „Jak skierować Codex przez bramę, Azure albo model lokalny?”

Żeby zostać przy wbudowanym dostawcy openai i zmienić tylko jego adres, ustaw openai_base_url w konfiguracji użytkownika (~/.codex/config.toml) albo przekaż go dla pojedynczego przebiegu:

Okno terminala
# Terminal: jeden przebieg przez endpoint regionalny albo firmowy
codex -c openai_base_url='"https://llm-gateway.internal.example.com/v1"' "Summarise the open TODOs in src/"

Codex ignoruje openai_base_url w projektowym .codex/config.toml, więc sklonowane repozytorium nie przekieruje twojego ruchu. Ta sama lista kluczy zabronionych w konfiguracji projektu (0.157.1) obejmuje model_provider, model_providers, notify i otel. Każdy blok z tej strony należy więc do konfiguracji użytkownika albo konfiguracji zarządzanej przez administratora, a nie do repozytorium.

Zdefiniuj własnego dostawcę z własnym budżetem ponowień

Dział zatytułowany „Zdefiniuj własnego dostawcę z własnym budżetem ponowień”

Brama, która potrzebuje własnego klucza albo polityki ponowień, dostaje nazwanego dostawcę. Identyfikatory wbudowane są zarezerwowane. openai, ollama i lmstudio nie da się przedefiniować w [model_providers]: Codex 0.157.1 odmawia wtedy startu z komunikatem „Built-in providers cannot be overridden”. amazon-bedrock też jest wbudowany i przyjmuje tylko nadpisania base_url, auth, http_headers i aws.*, więc pełny blok bramy pod tą nazwą zatrzymuje Codex komunikatem „model_providers.amazon-bedrock only supports changing base_url, auth, http_headers …”. Wybierz nowy identyfikator:

~/.codex/config.toml
model_provider = "corp-gateway"
[model_providers.corp-gateway]
name = "OpenAI via corporate gateway"
base_url = "https://llm-gateway.internal.example.com/v1"
env_key = "CORP_GATEWAY_API_KEY" # zmienna, z której Codex czyta klucz
wire_api = "responses"
request_max_retries = 4
stream_max_retries = 10
stream_idle_timeout_ms = 300000 # zwiększ, jeśli długie tury urywają się w połowie strumienia

Azure OpenAI ma ten sam kształt plus parametr zapytania api-version:

[model_providers.azure]
name = "Azure OpenAI"
base_url = "https://YOUR_RESOURCE.openai.azure.com/openai"
env_key = "AZURE_OPENAI_API_KEY"
query_params = { api-version = "2025-04-01-preview" }
wire_api = "responses"

Zastąp YOUR_RESOURCE nazwą swojego zasobu Azure i użyj api-version, które podaje dokumentacja twojego wdrożenia.

Ollama i LM Studio to wbudowani dostawcy lokalni. Wybierz jednego kluczem najwyższego poziomu oss_provider, a potem dodaj --oss:

oss_provider = "ollama" # albo "lmstudio"
Okno terminala
codex --oss "Explain what src/billing/proration.ts does"
codex exec --oss --local-provider lmstudio "List every exported function in src/lib/"

codex exec --oss bez żadnego z tych ustawień kończy się błędem „No default OSS provider configured”, a przy niedziałającej Ollamie błędem „No running Ollama server detected” (oba zaobserwowane w 0.157.1). Oba błędy są bezpieczniejsze niż ciche przejście do chmury. Zanim przeniesiesz wrażliwą pracę na model lokalny, przeczytaj jego licencję na karcie modelu; przegląd modeli pokazuje, które licencje open-weight są zweryfikowane.

Zacznij od modelu domyślnego, najpierw dostrój poziom rozumowania (model_reasoning_effort), a model zmieniaj dopiero wtedy, gdy każą ci to twoje własne ewaluacje. W Codex 0.157.1 domyślny model to GPT-6 Astra z poziomem rozumowania low; GPT-6 Sol i GPT-6 Luna domyślnie działają na medium. Astra przyjmuje poziomy od low do max oraz dostępny tylko w Codex poziom ultra (maksymalne rozumowanie z automatycznym delegowaniem zadań); Luna nie ma ultra. Ceny i limity kontekstu są w przeglądzie modeli.

Ustawienia każdego zadania trzymaj w osobnym profilu. --profile NAZWA nakłada $CODEX_HOME/NAZWA.config.toml na konfigurację bazową:

# ~/.codex/ci.config.toml — użycie: codex exec --profile ci "…"
model = "gpt-6-luna" # "Fast and affordable model for easier tasks"
model_reasoning_effort = "low"
model_verbosity = "low"
model_reasoning_summary = "concise"
hide_agent_reasoning = true # rozumowanie nie trafia do logów CI
# ~/.codex/everyday.config.toml — praca nad funkcjami, poprawki błędów
model = "gpt-6-sol" # "Workhorse model for coding and everyday work"
model_reasoning_effort = "medium"
# ~/.codex/deep.config.toml — przeglądy architektury, trudne debugowanie
model = "gpt-6-astra"
model_reasoning_effort = "high"
ZadanieProfilDlaczego
Poprawki lintera, zmiany nazw, podbicia zależności w CIci (GPT-6 Luna, low; GPT-6 Sol na low, jeśli zmiany Luny nie przechodzą kontroli)Mechaniczne zmiany w dużej liczbie; wynik sprawdza zestaw testów, a komunikat Codex o limitach sam poleca Lunę.
Codzienna praca nad funkcjamieveryday (GPT-6 Sol, medium)Codex opisuje Sol jako „Workhorse model for coding and everyday work”, a limity użycia starczają z nim na dłużej niż z Astrą.
Projekt obejmujący wiele modułów, przyczyny niestabilnych testówdeep (Astra, high; max albo ultra tylko wtedy, gdy high nie przechodzi twoich ewaluacji)Wyższy poziom rozumowania zużywa więcej limitu; wydawaj go tam, gdzie zadanie tego wymaga.

Jeśli niczego jeszcze nie zmierzyłeś, zostań przy domyślnym ustawieniu (Astra na low) i najpierw tam podnoś poziom rozumowania. Profile z tabeli to miejsce, do którego dochodzisz, gdy twoje przebiegi pokażą, które zadania są mechaniczne, a które wymagają głębi.

Limity kontekstu zmieniaj tylko wtedy, gdy masz na to pomiar. Obecne modele działają w Codex domyślnie z oknem roboczym 272K. Możesz je zwiększyć kluczem model_context_window, maksymalnie do sufitu katalogu, czyli 872K, a model_auto_compact_token_limit ustaw niżej niż okno, żeby kompaktowanie ruszyło, zanim okno się zapełni. Dla własnego dostawcy dopasuj obie wartości do limitu, który ten dostawca publikuje.

OpenAI zaleca teraz profile uprawnień (beta, Codex CLI od 0.138.0) zamiast starszych trybów --sandbox. Profil wybierasz kluczem default_permissions (albo -c default_permissions='":workspace"' dla jednego przebiegu). codex i codex exec nie mają w 0.157.1 osobnej flagi, ale codex sandbox przyjmuje -P/--permission-profile:

default_permissions = ":workspace" # wbudowane to m.in. :read-only, :workspace, :danger-full-access

Starszy system nadal działa i używają go starsze konfiguracje oraz fragmenty z sieci:

sandbox_mode = "workspace-write"
[sandbox_workspace_write]
network_access = false # włączaj tylko dla zadań, które muszą coś pobrać
writable_roots = ["/Users/me/.cache/pnpm"]

W jednej konfiguracji wybierz jeden system. OpenAI pisze, że profile i starszy sandbox „do not compose”. Żeby dać jednemu przebiegowi prawo zapisu w sąsiednim katalogu bez poszerzania całego sandboxa, użyj --add-dir:

Okno terminala
codex --cd apps/web --add-dir ../api --add-dir ../shared "Rename the Invoice DTO in all three packages"

Potem przetestuj granice, zanim trafi na nie przebieg bez nadzoru. codex sandbox uruchamia dowolne polecenie w tym samym sandboxie, którego używa Codex. W 0.157.1 nie ma podpolecenia platformy: wszystko po -- to polecenie.

Okno terminala
# Terminal, wewnątrz repozytorium
codex sandbox -- sh -c 'touch /etc/probe' # oczekiwane: Read-only file system
codex sandbox -P :workspace -- sh -c 'touch ./probe && echo writable'
codex sandbox -P :workspace -- curl -sI https://registry.npmjs.org
codex sandbox -P :workspace -- npm test # czy prawdziwe zadanie mieści się w granicach?

Na Linuksie pierwsza próba wypisała Read-only file system, a próba sieciowa się nie powiodła (curl zakończył się kodem 6 w 0.157.1), bo dostęp do sieci jest wyłączony, dopóki konfiguracja nie ustawi network_access = true. W ten sam sposób uruchom prawdziwe polecenia zadania (npm test, pnpm build, próbną migrację). Polecenie, które nie działa tutaj, nie zadziała też w przebiegu agenta, a dowiedzenie się o tym teraz nic nie kosztuje.

Jak udowodnić, co zrobił przebieg Codex bez nadzoru?

Dział zatytułowany „Jak udowodnić, co zrobił przebieg Codex bez nadzoru?”

Nikt nie czyta 40-minutowego transkryptu z CI. Niech przebieg produkuje dowody, które sprawdzi skrypt.

codex exec --json wypisuje jedno zdarzenie JSON na linię. .type najwyższego poziomu to thread.started, turn.started, turn.completed, turn.failed, item.started, item.updated, item.completed albo error. Rodzaj pracy jest w .item.type: agent_message, reasoning, command_execution, file_change, mcp_tool_call, web_search, todo_list i inne. Element command_execution niesie command, exit_code i status, a element file_change niesie changes[].path. Codex podaje te ścieżki jako bezwzględne, więc przed porównaniem z wzorcami względnymi wobec repozytorium usuń z nich katalog roboczy.

Okno terminala
# Krok CI: uruchom, zachowaj dowody, sprawdź je
set -euo pipefail # bramka domyka się przy błędzie: nieudane polecenie codex lub git przerywa zadanie
BASE=$(git rev-parse HEAD) # commit, od którego startuje agent
# starsza flaga sandboxa; albo zamiast niej -c default_permissions='":workspace"'. Wybierz jeden system.
codex exec --profile ci --json -o summary.txt --sandbox workspace-write \
"Fix the failing unit tests in src/billing/ without changing production behaviour" \
> events.jsonl
# 1. Polecenia, które się nie powiodły albo zostały odrzucone
jq -r 'select(.type=="item.completed" and .item.type=="command_execution"
and ((.item.exit_code // 0) != 0 or .item.status=="declined"))
| "\(.item.exit_code)\t\(.item.command)"' events.jsonl
# 2. Pliki zmienione poza dozwolonymi ścieżkami: jeśli są, zadanie ma zakończyć się niepowodzeniem
# Czytaj git, nie strumień zdarzeń: edycja przez polecenie powłoki
# (sed -i, heredoc) przychodzi jako command_execution, nigdy jako file_change.
{ git diff --name-only "$BASE"; git ls-files --others --exclude-standard; } |
awk '!/^(events\.jsonl|summary\.txt|touched\.txt)$/' | sort -u > touched.txt
if grep -v -E '^(src/billing/|tests/billing/)' touched.txt; then
echo "Agent edited files outside the allowed scope"; exit 1
fi
# 3. Zużycie tokenów na turę, do panelu kosztów
jq -c 'select(.type=="turn.completed") | .usage' events.jsonl

To sprawdzenie zakresu pozwala przestać czytać każdy diff. Czyta ono gita, a nie własne zdarzenia file_change agenta, bo plik przepisany poleceniem powłoki nigdy takiego zdarzenia nie wytwarza. Wewnątrz src/billing/ agent może pisać, co chce, bo ocenią to testy i bramka review. Zmiana w package.json albo w workflow CI to naruszenie zasad i zadanie kończy się błędem, zanim spojrzy na nie człowiek. summary.txt zachowaj jako komentarz do PR, a events.jsonl jako artefakt zadania CI. Wzorzec dozwolonych ścieżek i prompt bramki review należą do tech leada. Werdykt FAIL albo naruszenie zakresu wraca do autora PR, a człowiek przegląda tylko wskazane uwagi. Jeśli potrzebujesz odpowiedzi końcowej o ustalonym typie, dodaj --output-schema (zobacz Codex w trybie headless).

Jeśli zapis ma przetrwać zadanie CI, eksportuj zdarzenia OpenTelemetry z Codex. Skieruj eksporter do kolektora na tym samym hoście albo w tej samej sieci:

[otel]
environment = "ci"
log_user_prompt = false # domyślnie; prompty nie są eksportowane
[otel.exporter.otlp-http]
endpoint = "http://localhost:4318/v1/logs"
protocol = "binary" # albo "json"; dla gRPC użyj [otel.exporter.otlp-grpc]

Domyślnie eksporter jest wyłączony, więc nic nie opuszcza maszyny, dopóki go nie ustawisz. Codex 0.157.1 emituje m.in. zdarzenia codex.conversation_starts (model, ustawienia, polityka sandboxa), codex.api_request, codex.tool_decision (zatwierdzone albo odrzucone i przez kogo), codex.tool_result, codex.sandbox_outcome i codex.turn_cost. W przebiegach bez nadzoru ustaw alerty na odmowy w codex.tool_decision i na wyniki sandboxa: jedno i drugie oznacza, że zadanie chciało czegoś, na co granice nie pozwalały.

Analityka to kanał osobny od OTel: trafia do OpenAI, nie do twojego kolektora. Żeby ją wyłączyć, ustaw:

[analytics]
enabled = false

notify uruchamia program po każdej turze z argumentem JSON (type równe agent-turn-complete oraz thread-id, turn-id, cwd, input-messages i last-assistant-message). Użyj go, żeby dopisać linię do logu przebiegów albo wysłać wiadomość na czat:

notify = ["python3", "/Users/me/.codex/notify.py"]
#!/usr/bin/env python3
import json, sys, datetime
event = json.loads(sys.argv[1])
if event.get("type") == "agent-turn-complete":
with open("/Users/me/.codex/turns.log", "a") as log:
log.write(f"{datetime.datetime.now().isoformat()}\t{event.get('cwd')}\t"
f"{(event.get('last-assistant-message') or '')[:200]}\n")

Tak, ale już nie jako serwerem MCP. codex mcp-server usunięto w 0.154.0, a codex mcp zarządza tylko zewnętrznymi serwerami, do których Codex się łączy. Do sterowania programowego użyj codex exec z powłoki albo CI, SDK dla TypeScriptu @openai/codex-sdk (wersja zsynchronizowana z CLI; 0.157.1 na dzień 2026-09-26) albo eksperymentalnego codex app-server. SDK uruchamia tego samego agenta, więc AGENTS.md, umiejętności (skills) i konfiguracja działają tak samo, a wątki zapisuje w ~/.codex/sessions, dzięki czemu resumeThread(id) może do nich wrócić. Wzorce i kompromisy opisuje przewodnik po Codex SDK. Jeśli wybierasz SDK spośród kilku narzędzi, zobacz sterowanie agentami z kodu.

Jak utrzymać współdzieloną konfigurację Codex w porządku?

Dział zatytułowany „Jak utrzymać współdzieloną konfigurację Codex w porządku?”
  • codex features list wypisuje każdą funkcję z jej etapem i faktycznym stanem. W 0.157.1 shell_snapshot, unified_exec, goals, hooks, multi_agent i worktrees są stabilne i włączone; memories jest stabilne, ale wyłączone.
  • --enable NAZWA albo --disable NAZWA zmienia funkcję dla jednego przebiegu. codex features enable NAZWA zapisuje ją w config.toml.
  • Flagi na etapie removed (na przykład tool_search, steer, js_repl) po przełączeniu nic nie robią. Usuń je ze współdzielonej konfiguracji.
  • codex doctor --json generuje raport z ukrytymi danymi wrażliwymi o instalacji, konfiguracji, uwierzytelnieniu i stanie środowiska. Dołączaj go do zgłoszeń błędów zamiast wklejać swoją konfigurację.
  • Codex nie startuje po dodaniu dostawcy. Błąd wskazuje zarezerwowany identyfikator wbudowany (openai, ollama, lmstudio) albo, dla amazon-bedrock, wymienia jedyne pola, które wolno nadpisać. Zmień nazwę bloku, na przykład na [model_providers.corp-gateway], i ustaw model_provider na nową nazwę.
  • Fragment ze starego artykułu nie działa. Przy --strict-config usuń klucz, który wskazuje błąd. Stare polecenia też zawodzą: --full-auto daje teraz „unexpected argument” (użyj profilu uprawnień, --approve-for-me albo --sandbox workspace-write), a codex mcp-server już nie istnieje. Starsze tabele [profiles.NAZWA] nadal się parsują, ale przenieś je do $CODEX_HOME/NAZWA.config.toml, żeby --profile nakładał je w obecny sposób.
  • Brama zwraca 401. Zmienna wskazana w env_key nie jest ustawiona w powłoce, która uruchomiła Codex. Runnery CI nie dziedziczą twojej powłoki logowania. Wyeksportuj zmienną w kroku zadania i sprawdź wynik przez codex doctor --json.
  • Długie tury urywają się z timeoutem strumienia. Zwiększ stream_idle_timeout_ms i stream_max_retries u własnego dostawcy. Przy wbudowanym dostawcy najpierw sprawdź, czy pośredniczące proxy nie zamyka bezczynnych połączeń.
  • Nie przychodzą zdarzenia OTel. Sprawdź, czy tabela eksportera to [otel.exporter.otlp-http] albo [otel.exporter.otlp-grpc] (domyślnie eksportera nie ma) i czy ścieżka kolektora dla HTTP kończy się na /v1/logs. Potem sprawdź ostrzeżenie o nagłówkach powyżej.
  • Przebieg agenta pada na poleceniu, które działa w twojej powłoce. Uruchom je ponownie przez codex sandbox -- POLECENIE. Jeśli tam też pada, dodaj wpis writable_roots albo --add-dir dla tej ścieżki, ewentualnie włącz sieć tylko w tym profilu, zamiast przechodzić na danger-full-access.
  • Sprawdzenie zakresu pada na plikach generowanych. Lockfile i snapshoty liczą się jako edycje. Dopisz ich dokładne ścieżki do wzorca dozwolonych albo generuj je w osobnym kroku CI bez agenta.