Jakieś pięć–sześć miesięcy temu zauważyłem hooki w Copilocie. Z ciekawości sprawdziłem wtedy, co w tym temacie oferuje Codex.
Albo nie było tam nic ciekawego, albo zwyczajnie niczego nie znalazłem. Dzisiaj już nie pamiętam.
Ostatnio, przy okazji pisania wpisu o pośpiechu w pracy z AI (możesz go przeczytać TUTAJ), wróciłem do tematu. I tu nagle bęc – hooki w Codexie zaczęły wyglądać naprawdę interesująco.
Miesiąc w świecie AI potrafi zrobić większą różnicę niż rok w projekcie, w którym „zaraz zrobimy aktualizację frameworka”.
Czym są hooki?
Hook to skrypt uruchamiany automatycznie w określonym momencie pracy Codexa coś jak hooki w gicie (o tym możesz poczytać TUTAJ).
Możesz dzięki temu dodać kontekst na początku sesji, sprawdzić komendę przed jej wykonaniem, przeanalizować wynik działania narzędzia albo zmusić Codexa do jeszcze jednej rundy pracy, zanim uzna zadanie za zakończone. Sam skrypt działa w przewidywalnym momencie cyklu życia agenta, więc nie musisz liczyć wyłącznie na to, że model przypomni sobie o zasadzie zapisanej gdzieś w odmętach instrukcji.
Obecnie Codex obsługuje następujące hooki:
SessionStart– uruchamia się podczas rozpoczęcia, wznowienia, wyczyszczenia lub kompaktowania sesji. Może dodać dodatkowy kontekst dla modelu.SubagentStart– uruchamia się, gdy Codex startuje subagenta. Pozwala przekazać mu dodatkowe instrukcje.PreToolUse– działa przed użyciem obsługiwanego narzędzia, np. basha,apply_patchlub MCP. Może zablokować albo zmodyfikować wywołanie.PermissionRequest– uruchamia się, gdy Codex chce poprosić użytkownika o zgodę. Hook może automatycznie zaakceptować lub odrzucić żądanie.PostToolUse– działa po wykonaniu narzędzia. Może przeanalizować wynik i przekazać modelowi dodatkową informację.PreCompact– uruchamia się przed kompaktowaniem kontekstu rozmowy.PostCompact— uruchamia się po kompaktowaniu kontekstu.UserPromptSubmit— działa przed przekazaniem promptu do modelu. Może dodać kontekst albo całkowicie zablokować prompt.SubagentStop— uruchamia się, kiedy subagent chce zakończyć działanie. Możesz nakazać mu wykonanie kolejnego kroku.Stop— działa, gdy Codex chce zakończyć turę. Hook może powiedzieć: „Nie tak szybko, sprawdź jeszcze testy”.
Brzmi trochę jak event listenery, middleware i zabezpieczenia aplikacji wrzucone do jednego worka. I w sumie właśnie tak możesz o nich myśleć.
Ten sam prompt, dwa różne zachowania
Przygotowałem bardzo prosty przykład. Nawiązuje on do pierwszego wpisu z serii, czyli zasady: daj AI kontekst.
Prompt składa się z dwóch słów:
Zrób endpoint
Bez hooka Codex nie pyta, po co ten endpoint jest potrzebny. Od razu rozpoczyna standardową procedurę: sprawdza strukturę repozytorium, szuka instrukcji i próbuje ustalić istniejące wzorce.
Czyli technicznie zabiera się do pracy, ale nadal nie wie, jaki problem ma właściwie rozwiązać.
Następnie dodałem hook SessionStart, który przekazuje Codexowi prostą regułę:
Przed wykonaniem zadania sprawdź, czy prompt wyjaśnia cel biznesowy. Jeśli nie, zapytaj użytkownika, jaki cel biznesowy ma realizować zmiana. Nie pytaj o niego, jeżeli zadanie dotyczy naprawy błędu lub istniejącego zachowania.
Po uruchomieniu nowej sesji podaję dokładnie ten sam prompt:
Zrób endpoint
Tym razem Codex nie zaczyna skanować projektu. Najpierw pyta:
Jaki cel biznesowy ma realizować ta zmiana?
Niby mała różnica, ale dokładnie takich drobnych zabezpieczeń potrzebujemy podczas pracy z AI.
Model jest bardzo chętny do działania. Czasem nawet zbyt chętny. Gdy napiszesz „zrób endpoint”, to zrobi endpoint. Czy rozwiąże on właściwy problem? To już zupełnie inne pytanie.
Jak działa ten przykład?
Całość umieściłem w małym repozytorium przygotowanym specjalnie do tego wpisu (znajdziesz je TUTAJ). Znajdziesz tam plik: .codex/hooks.json
Konfiguracja zawiera hook SessionStart, uruchamiany przy rozpoczęciu, wznowieniu, wyczyszczeniu oraz kompaktowaniu sesji.
{ "hooks": { "SessionStart": [ { "matcher": "startup|resume|clear|compact", "hooks": [ { "type": "command", "command": "printf '%s\n' 'Przed wykonaniem zadania sprawdź, czy prompt wyjaśnia cel biznesowy. Jeśli nie, zapytaj użytkownika: Jaki cel biznesowy ma realizować ta zmiana? Wyjątek: jeśli prompt dotyczy poprawki błędu lub naprawy istniejącego zachowania, nie pytaj o cel biznesowy i wykonaj zadanie.'", "timeout": 5, "statusMessage": "Ładowanie reguły celu biznesowego" } ] } ] } }
Hook wykonuje zwykłe printf. Tekst wypisany na standardowe wyjście zostaje dodany jako dodatkowy kontekst dla Codexa. Nie jest potrzebny osobny skrypt, paczka npm ani siedemnaście warstw abstrakcji.
Ważne jest jedno: SessionStart nie analizuje promptu samodzielnie.
Hook nie sprawdza za pomocą skryptu, czy prompt zawiera cel biznesowy. Dodaje jedynie regułę do kontekstu modelu. To Codex ma później ocenić prompt i zdecydować, czy powinien zadać dodatkowe pytanie.
Czyli moment przekazania instrukcji jest deterministyczny, ale jej interpretacja nadal zależy od LLM-a. Nie jest to więc twarda walidacja jak w kodzie.
Jeżeli chcesz naprawdę zablokować określone działanie, lepszym miejscem będzie na przykład PreToolUse albo PermissionRequest.
Uruchom to sam
Mógłbym teraz dokładnie rozpisać Ci, co skopiować, gdzie wkleić albo jeszcze prościej dać prompt.
Tylko że wtedy byłby to kolejny tutorial typu kopiuj-wklej, po którym wszystko działa, dopóki nie zmienisz jednego przecinka.
Potraktuj repozytorium jako przykład do nauki. Jest ono małe, proste i to wszystko celowo.
Pamiętaj o tym aby uruchomić /hooks i oznaczyć hook jako zaufany.
Możesz na przykład wymagać podania kryteriów akceptacji, nazwy ticketa albo informacji, w jaki sposób zmiana ma zostać przetestowana.
Hooki nie zastąpią myślenia
Hooki wyglądają bardzo ciekawie, ale nie są magiczną warstwą, która nagle sprawi, że Codex będzie zawsze działał idealnie. I z tą myslą Cię dzisiaj zostawiam.

