--- source_sha: "2f4a13dbc2a4" --- # Środowiska { #environments } Publikacja agenta wybija [wersję](concepts.md#version). **Środowisko** to nazwa, która wskazuje na jedną z nich — `production`, `staging`, `dev` — dzięki czemu możesz wypróbować nową wersję gdzieś, zanim spotkają ją wszyscy. Bez środowisk publikacja i wydanie to ten sam akt. Ze środowiskami to dwie decyzje: wybicie wersji i umieszczenie jej gdzieś. ## Czym jest środowisko { #what-an-environment-is } Nazwą, wersją, do której jest przypięte, i opcjonalnie własnym miejscem docelowym śladów. Każdy agent ma środowisko **domyślne** i to właśnie ono obsługuje zwykłą powierzchnię, gdy nikt nie powiedział inaczej. | | | |---|---| | **Nazwa** | Małe litery, z myślnikami, do 64 znaków — pojawia się w URL-ach i staje się tagiem śladów, więc `Production (EU)` i `production-eu` nie mogą być dwiema rzeczami | | **Wersja** | Która opublikowana wersja tu odpowiada. Nie ma stanu bez przypięcia | | **Tracks latest** | Czy publikacja sama przekierowuje to środowisko. Domyślnie wyłączone | | **Ślady** | Token zapisu Logfire z vaulta, żeby runy tego środowiska lądowały we własnym projekcie | | **Połączenia testowe** | Serwery MCP i klucze z vault, które to środowisko zastępuje testowymi — sandboxowym CRM, testową skrzynką. Tylko środowiska nazwane | !!! info "Nie ma środowiska bez wersji" Nieprzypięte środowisko byłoby nazwą, która odpowiada niczym, a pierwsza wiadomość do niego skierowana zawiodłaby daleko od formularza, który je utworzył. Utwórz jedno bez nazwania wersji, a zacznie od tego, co serwuje środowisko domyślne. ## Przepływ pracy, dla którego to jest { #the-workflow-it-is-for } ```mermaid flowchart LR D[Draft in the Builder] -->|publish| V[Version 7] V -->|pin| S[staging] S -->|somebody tries it| OK{Good?} OK -->|yes| P[promote to production] OK -->|no| D ``` 1. Edytuj wersję roboczą, opublikuj. To wybija wersję i nie zmienia niczego, z czego ktoś korzysta. 2. Wskaż nią `staging` i podepnij swojego testowego bota Slacka albo prywatny link do `staging`. 3. Wypróbuj go na prawdziwych pytaniach. 4. Wypromuj `production` na tę samą wersję — jedna edycja, bez ponownej publikacji. Rollback to ten sam ruch wstecz: przekieruj `production` na wersję, która działała. Stara wersja wciąż tam jest, wciąż da się ją odczytać i uruchomić. [Suita ewaluacji](evals.md#suites) ustawiona na promocję sprawdza każdą wersję wypromowaną na jej środowisko względem wersji, którą zastąpiła, i daje znać właścicielowi, gdy wynik nie przechodzi. Sama tylko informuje; środowisko, które wskazuje ją jako [strażnika](#guarding-a-promotion-with-evals), czeka, aż przejdzie. ## Ewaluacja jako strażnik promocji { #guarding-a-promotion-with-evals } Środowisko może wskazać [suity ewaluacji](evals.md#suites), które go **strzegą**. Wtedy przyjmuje wersję dopiero, gdy każdy strażnik przeszedł na dokładnie tej wersji, na wersji datasetu, przy scoringu i publikacji sędziego, do których strażnik jest przypięty, oraz przy progu, który ma teraz - zaliczenie sprzed przesunięcia przypięcia albo sprzed podniesienia progu się nie liczy. Promocja, która tego nie spełnia, jest odrzucana (`409`, `PROMOTION_BLOCKED`), a odmowa wymienia każdego strażnika i jego stan: nie przeszedł, bez rozstrzygnięcia, nie uruchomił się i dlaczego, jeszcze sprawdza, nieaktualny, niesprawdzony albo wstrzymany. Zaliczenie liczy się dla środowiska, obok którego zostało uruchomione: względem wersji, którą to środowisko serwuje teraz, i przy scoringu z jego przypięcia - zaliczenie obok wersji stagingu nic nie mówi o zastąpieniu wersji produkcji. Wstrzymany strażnik zatrzymuje wersję niezależnie od tego, co znalazł przed wstrzymaniem. Suita, która strzeże środowiska, jest **przypięta** do wersji datasetu, scoringu i opublikowanej wersji sędziego, które miała, gdy została strażnikiem. Edycja datasetu - jego przypadków, oceniania, sędziego - zostaje otwarta dla każdego, kto może go edytować, i nie zmienia tego, co sprawdza strażnik. Panel suity mówi, kiedy dataset albo jego sędzia poszedł dalej, a **Move the pin** (`POST /api/v1/agents/{id}/eval-suites/{suite}/pin`) przesuwa strażnika na najnowszą wersję, scoring i publikację sędziego; wymaga `promotions:override` i jest zapisywane jako zmiana strażników. Suita, która przestaje strzec, znów czyta najnowszą wersję, a suita, której dataset nie ma jeszcze przypadków, nie może zostać strażnikiem. Strażnik ustawiony, zanim strażnicy byli przypinani, na datasecie, który nie miał wtedy przypadków, nie jest przypięty: wstrzymuje każdą wersję, dopóki nie przypnie go ktoś, kto może pomijać bramkę promocji. Sędzia - własny sędzia datasetu albo Eval judge - zostaje przy publikacji, którą miał, gdy strażnika przypięto. Ponownie opublikowany sędzia nie ocenia strażnika, dopóki przypięcie się nie przesunie, a zaliczenie ocenione inną publikacją się nie liczy. Strażnik przypięty, gdy jego sędzia nie miał publikacji, zostawia kryteria sędziego bez oceny, dopóki przypięcie się nie przesunie. Dialog promocji pokazuje to samo i uruchamia strażników, którzy nie przeszli na tej wersji, każdego obok wersji, którą środowisko serwuje teraz (`POST /api/v1/agents/{id}/environments/{env}/gate/run`; `GET …/gate?version_id=` czyta bramkę). Strażnik, który potrzebuje sędziego, gdy [wsparcie AI](governance.md#ai-assistance) jest wyłączone, mówi to wprost, zamiast blokować bez powodu. **Pominięcie** promuje mimo strażników. Wymaga uprawnienia `promotions:override` - mają je owner i admin - oraz powodu o długości co najmniej dziesięciu znaków, podanego przez osobę zalogowaną jako ona sama, nie przez klucz API. Pominięcie, kto je zrobił i wynik każdego strażnika trafiają do audit logu i na wersję w historii, a właściciel każdego strażnika, który nie przeszedł, dostaje wiadomość. Zmiana listy strażników wymaga tego samego uprawnienia, bo zdjęcie strażnika przepuszcza to, co by zatrzymał, i tak samo osłabienie tego, co strażnik sprawdza: niższy albo usunięty próg, inny dataset, inne środowisko albo połączenia testowe tego środowiska. Ostrzejszy próg nie wymaga pominięcia; jest zapisywany tak samo, a zaliczenie przy starym progu przestaje się liczyć. Suity, która strzeże, ani datasetu, który taka suita sprawdza, nie da się usunąć, dopóki nie zostanie zdjęta. Strzeżone środowisko z włączonym **tracks latest** nie podąża za publikacją od razu: publikacja uruchamia jego strażników na nowej wersji, a środowisko przesuwa się, gdy wszyscy przejdą, zapisane jako promocja przez bramkę. Środowisko, którego strażnicy nie przeszli, zostaje na miejscu, a jego wiersz mówi, że czeka. ## `tracks_latest` i dlaczego jest wyłączone { #tracks_latest-and-why-it-is-off } Środowisko z włączonym **tracks latest** jest przekierowywane przez każdą publikację. To właściwe ustawienie dla `dev` i prawie nigdy właściwe dla `production`. Domyślne wyłączenie jest celowe: publikacja wybija wersję, a decyzja o tym, gdzie ta wersja działa, jest osobnym aktem. Sprzęgnięcie ich oznacza, że niedokończona edycja dociera do klienta, bo ktoś kliknął **Opublikuj** (Publish), żeby zapisać swoją pracę. Jedynym wyjątkiem jest `production`, które tworzy pierwsza publikacja. Dopóki jest jedynym środowiskiem agenta, nie ma skąd promować, więc podąża za publikacjami; przypnij je, gdy obok pojawi się `dev` albo `staging`. ## Podpinanie powierzchni do środowiska { #binding-a-surface-to-one } [Ekspozycja](concepts.md#exposure) — bot Slacka, widget, hostowana strona, odbiorca API — może nazwać środowisko, które obsługuje. Pominięta, dostaje domyślne. To właśnie czyni ten podział użytecznym: bot deweloperski podpięty do `dev` serwuje to, co przypina `dev`, podczas gdy widget na twojej stronie zostaje na `production`, dopóki go nie przeniesiesz. Jeden agent, dwie publiczności, dwie wersje, jeden komplet ksiąg. Strona, którą agent publikuje, dzieli się tak samo. Run w nazwanym środowisku publikuje własną [aplikację](artifacts.md#one-name-one-link), więc próba `dev` na cotygodniowym raporcie nigdy nie publikuje ponownie strony, którą otwierają czytelnicy produkcji. Środowiska z runem, który wciąż pracuje albo czeka na akceptację, nie da się usunąć, dopóki run się nie skończy: usunięcie przekazałoby ten run domyślnemu środowisku, a jego strony — produkcji. Tak samo jest, dopóki run ewaluacji w tym środowisku czeka w kolejce albo działa: inaczej szedłby dalej na połączeniach produkcji. ## Połączenia testowe { #test-connections } Wersja to ten sam spec, gdziekolwiek działa, więc `staging` sięgałby inaczej do tego samego CRM i tej samej skrzynki co `production`. Nazwane środowisko może zamiast tego odpowiedzieć na binding **połączeniem testowym**: organizacyjny [serwer MCP](mcp.md) — sandboxowym, a klucz capability z vault — kluczem testowym. Spec się nie zmienia, więc promocja wersji nie przenosi żadnego testowego poświadczenia. | Binding | Zastępowany przez | Co widzi model | |---|---|---| | Organizacyjne połączenie MCP | Inne organizacyjne połączenie MCP | Nazwy narzędzi połączenia produkcyjnego, więc staging i produkcja są porównywalne | | Klucz capability z vault | Inny klucz tego samego rodzaju i przeznaczenia | Nic: capability nigdy nie wie, jaki klucz dostała | Używa ich każdy run w tym środowisku: bot Slack podpięty do `staging`, wywołanie API, które je nazywa, harmonogram i każdy delegat, którego te runy wywołują. Narzędzia, które oferuje połączenie testowe, są zawężane przez allowlistę połączenia produkcyjnego, własną allowlistę połączenia testowego i allowlistę bindingu. !!! warning "Wyłączone, nigdy produkcja" Binding można w środowisku wyłączyć zamiast zastępować. Tak samo dzieje się z bindingiem, którego strona testowa została usunięta, wyłączona albo straciła poświadczenia: binding gaśnie tam, dopóki ktoś nie wybierze innego połączenia testowego. Strona produkcyjna nigdy nie jest awaryjnym zastępstwem. Capability, której testowy klucz usunięto, odmawia runu, zamiast działać bez klucza. Środowisko domyślne nie ma połączeń testowych — to ono obsługuje powierzchnię, która nie nazywa środowiska, czyli produkcję. Obie strony zastąpienia muszą należeć do organizacji, a klucz testowy musi być widoczny dla osoby, która go ustawia. Zapisywane są tylko identyfikatory; klucz testowy zostaje w [vault](secrets.md), a wpis audytu zapisuje, ile jest zastąpień, nie to, co zawierają. ### W ewaluacji { #in-an-eval } Ewaluacja uruchamia agenta naprawdę, więc jego narzędzia działałyby naprawdę: agent, który wysyła e-maile, wysłałby jeden na każdy przypadek. Run uruchomiony w **izolacji** — a tak działa ewaluacja — wykonuje narzędzie tylko wtedy, gdy jest to bezpieczne: | Narzędzie | Co się dzieje | |---|---| | Sięga do testowego połączenia MCP środowiska | Działa, na systemie testowym | | Tylko czyta | Działa na zwykłym połączeniu | | Zapisuje, na testowym kluczu z vault | Działa tylko wtedy, gdy jego capability deklaruje, że sam klucz wyznacza cel; inaczej **nie jest wykonywane** i jest zapisywane | | Zapisuje i nie ma połączenia testowego | **Nie jest wykonywane.** Zapisywane jako zamierzone wywołanie, z argumentami | Klucz testowy zastępuje poświadczenie, ale URL albo host w konfiguracji capability nadal może kierować zapisy na produkcję. Dlatego podmieniony klucz pozwala capability zapisywać w ewaluacji tylko wtedy, gdy deklaruje ona `test_key_isolates`, a [katalog](reference/capabilities.md#what-an-eval-runs) wymienia, które to robią. Narzędzie MCP liczy się jako czytające tylko wtedy, gdy serwer oznacza je `readOnlyHint`, a połączenie ma włączone zaufanie do tego oznaczenia. Domyślnie nie ma, bo oznaczenie to deklaracja samego serwera. Narzędzie capability deklaruje to w rejestrze, a [katalog](reference/capabilities.md#what-an-eval-runs) wymienia, które to robią. **Narzędzie, które niczego nie deklaruje, zapisuje.** Model dowiaduje się, że wywołanie nie zostało wysłane, a zamierzone wywołanie zostaje zachowane z runem do oceny. Run w izolacji może też dostawać odpowiedzi z nagrania runu, z którego wzięto przypadek — z wywołań, które zachował jego transkrypt. Wywołanie jest dopasowywane po narzędziu, argumentach i kolejności wśród identycznych wywołań i dostaje oryginalny wynik; wywołanie, którego nagranie nie zawiera, nie jest wykonywane i zostaje zapisane jako rozbieżne. Run, którego transkrypt zgubił wywołanie, nie jest odtwarzany wcale. Run w izolacji nie ma kogo zapytać o zatwierdzenie, więc wywołanie objęte bramką też nie jest wykonywane i zostaje zapisane jako wymagające zatwierdzenia. ## Testowanie z poziomu Buildera { #trying-it-from-the-builder } **Testuj** w nagłówku Buildera otwiera czat obok Buildera, a nie nad nim - ten sam czat co `/chat`, ze strumieniowaniem, krokami narzędzi, kartami zatwierdzeń i pytaniami. Odpowiada jako **wersja robocza**, z nieopublikowanymi zmianami, albo jako wersja dowolnego środowiska, i mówi która. Do testu wersji roboczej nic nie trzeba publikować: wersja robocza musi przejść te same sprawdzenia co publikacja i uruchomić ją może tylko osoba, która może edytować agenta. Run zatrzymany na zatwierdzeniu kontynuuje na wersji roboczej takiej, jaka była na jego początku. Każda tura jest tam **runem testowym**: liczonym w budżecie i zapisywanym jak każdy inny, oznaczonym `test` w Aktywności i możliwym do odfiltrowania (**With test runs**, **Without test runs**, **Only test runs**; `?test=true` albo `false` w `GET /api/v1/runs`). Panel zaczyna nową rozmowę, wysyła ostatnią wiadomość ponownie po zmianie i trzyma kilka przypiętych promptów do uruchomienia jednym kliknięciem. Jego szerokość, to, co odpowiada, i przypięte prompty są zapamiętywane per agent w przeglądarce. Ramka czatu wysyła w każdej turze `draft: true` albo `test: true` z `environment_id`. **Porównaj** stawia dwa czaty obok siebie - wersję roboczą i produkcję albo dwa środowiska - a pole nad nimi pyta oba o to samo jednocześnie, więc odpowiedzi różnią się tylko tym, co odpowiada. **Co zmienia wersja robocza** pokazuje wersję roboczą na tle opublikowanej wersji, jako ten sam diff, który rysuje historia wersji. Naciśnięcie T w dowolnym miejscu Buildera, poza polem tekstowym, otwiera albo zamyka panel. ## Ślady per środowisko { #tracing-per-environment } Środowisko może nieść własny token zapisu Logfire, zapieczętowany w [vaulcie](secrets.md), oraz nazwę usługi. Jego runy trafiają do śladów w tamtym projekcie, otagowane nazwą środowiska. To właśnie trzyma eksperyment ze stagingu z dala od dashboardu, który ktoś obserwuje pod kątem incydentów produkcyjnych — i jest per środowisko, a nie per deployment, bo te dwa to naprawdę różne projekty. Gdzie trafiają trace'y, należy do środowiska; *ile niosą* — do agenta. Blok [observability](reference/spec.md#observability) agenta ma tryb `content`: `full` zapisuje wiadomość, wyjście modelu i każdy argument narzędzia, a `none` — tylko czas, tokeny, koszt i nazwy narzędzi. Przy projekcie nad danymi medycznymi, prawnymi albo kadrowymi to właśnie `none` powstrzymuje kopię chronionej treści przed opuszczeniem maszyny. Token środowiska przekierowuje run, ale tego wyboru nie nadpisuje. ## Czym domyślne środowisko nie jest { #what-the-default-environment-is-not } Środowisko domyślne jest **zarządzane przez publikację**, a nie przez to API. Nie możesz go usunąć, przemianować innego środowiska na nie ani ręcznie przełączyć, które jest domyślne. Oddanie odpowiedzi na pytanie "co dostaje zwykła powierzchnia" w dwie ręce oznacza, że one w końcu się poróżnią, a ta różnica wychodzi na jaw jako klient spotykający wersję, której nikt nie wydał. ## Podsumowanie { #recap } - Środowisko to **nazwa przypięta do wersji**; każdy agent ma domyślne. - Publikacja wybija wersję. **Umieszczenie jej gdzieś to osobna decyzja** — dlatego `tracks_latest` jest wyłączone w środowisku, które dodajesz; `production` utworzone przez pierwszą publikację podąża za nimi, dopóki go nie przypniesz. - **Powierzchnia może nazwać swoje środowisko**, więc bot deweloperski i publiczny widget mogą serwować różne wersje jednego agenta. - **Rollback to przekierowanie**, bo stare wersje pozostają czytelne i uruchamialne. - Środowisko może być **strzeżone przez suity ewaluacji**: wersja trafia na nie dopiero, gdy przejdą na tej wersji, albo z ich pominięciem - z powodem i uprawnieniem `promotions:override`. - Nazwane środowisko może zastąpić bindingi **połączeniami testowymi**; binding bez takiego połączenia jest tam wyłączony, nigdy nie trafia na produkcję. W ewaluacji narzędzie, które zapisuje i nie ma połączenia testowego, jest **zapisywane, a nie uruchamiane**. - Środowisko domyślne jest zarządzane przez publikację i celowo nie da się go tu edytować.