Projektowanie narzędzia dla agenta: polityka, sandboxing, pamięć i weryfikacja
Dowiedz się, które warstwy czasu wykonywania przekształcają model językowy używany do wywoływania narzędzi w niezawodnego agenta: polityka wykonywania, sandboxing systemu operacyjnego, trwały stan, weryfikacja, kontrola kontekstu oraz koszt.
Źródła: Agent Harness Engineering: The Missing Layer Between an LLM and a Real AI Agent
Zespoły, które zamierzają stworzyć agenta AI, zazwyczaj zaczynają od porównywania modeli: rozmiarów okna kontekstowego, wyników testów benchmarkowych, jakości rozumowania oraz ceny za token. Gdy wybierany zostanie model, podłącza się kilka narzędzi, a rezultatem jest tzw. agent. W tym momencie istnieje w rzeczywistości model, który potrafi wywoływać funkcje, a luka pomiędzy nim a agentem produkcyjnym jest wypełniana warstwą wykonawczą, powszechnie nazywaną obecnie agent harness. Ten przewodnik omawia poszczególne warstwy tego rozwiązania, przed czym chroni każda z nich oraz jak stopniowo rozwijać takie rozwiązanie, unikając przy tym zagłębiania się w abstrakcje frameworku.
Model umiejący wywoływać narzędzia to jeszcze nie agent
Typowy zestaw wyjściowy składa się z krótkiego listy funkcji dostępnych dla modelu.
search()
read_file()
write_file()
run_command()
Dzięki tym czterem funkcjom model może wyszukiwać, czytać, pisać i wykonywać polecenia. Wydaje się to oznaką autonomii, ale w tym układzie nic nie decyduje o tym, do czego model ma dostęp, które operacje wymagają zatwierdzenia przez człowieka, jakie informacje przetrwają awarię lub restart, w jaki sposób sprawdzane są wyniki, ani ile z rezultatów każdego narzędzia jest wracane do promptu. Wszystkie te obowiązki należą do narzędzia sterującego.
Narzędzie to okazuje się również zmienną mierzalną. W chwili pisania tego tekstu badanie z 2026 roku porównujące narzędzia sterujące agentami programistycznymi wykazało różnice sięgające 40 razy w liczbie tokenów zużytych na rozwiązanie jednego zadania, podczas gdy różnice w stopie powodzenia między tymi samymi narzędziami były znacznie mniejsze. Wniosek jest taki, że sprytny silnik wykonawczy nie sprawia, iż słaby model stanie się genialny. Raczej silnik ten w dużej mierze wpływa na to, jak efektywnie, bezpiecznie i przewidywalnie zdolny model wykonywa swoje zadania.
Pętla w centrum i pytania wokół niej
W swojej istocie agent to pętla: zadaje się modelowi pytanie, co ma zrobić, wykonywany jest żądany narzędzie, wynik dodawany jest do kontekstu i proces powtarza się, aż model poinformuje o zakończeniu.
while True:
response = model(context)
if response.is_final:
break
result = execute_tool(response.tool_call)
context.append(result)
Wiele rzeczywistych agentów ma w swojej strukturze coś bardzo podobnego. Model podejmuje decyzję, silnik wykonuje ją, następnie wraca informacja o obserwacji, a model wybiera kolejny krok. Sama pętla jest prosta; trudności inżynieryjne leżą we wszystkim, co ją otacza. Praktyczny interfejs musi na każdym kroku odpowiadać na długą listę pytań operacyjnych.
Can the agent execute this command?
Can it access this directory?
Does it need human approval?
What happens if the command fails?
What information should return to the model?
What should survive the session?
Should another agent review the result?
How much context should we send?
How much will this turn cost?
What happens if the model loops forever?
Wszystkie te elementy razem tworzą tzw. „harness”. Jeden z najnowszych artykułów konceptualnych opisuje go jako środowisko uruchomieniowe, które łączy model językowy ze światem zewnętrznym za pomocą narzędzi, zarządzania kontekstem, mechanizmów bezpieczeństwa, funkcji orkiestracji oraz punktów rozszerzalności. Przydatny obraz mentalny dzieli ten system na dwie części.
AI Agent
│
┌────────┴────────┐
│ │
Model Harness
│ │
reasoning ┌──────┼───────┐
planning │ │ │
generation Tools Memory Safety
│ │ │
Sandbox Context Verification
Z jednej strony model dostarcza umiejętności rozumowania, planowania i generowania treści. Z drugiej strony „harness” zapewnia narzędzia, pamięć oraz mechanizmy bezpieczeństwa, wspierane przez środowisko izolowane, obsługę kontekstu oraz proces weryfikacji. Model dostarcza inteligencji; „harness” określa, w jaki sposób ta inteligencja oddziałuje na rzeczywiste systemy.
Dlaczego prompt nie może być mechanizmem bezpieczeństwa
Załóżmy, że prompt systemu zawiera jasną zasadę:
Nigdy nie usuwaj pliku produkcyjnego bez uprzedniego zapytania mnie.
W tym zdaniu nie ma nic dwuznacznego, a mimo to pozostaje to prośbą. Model może je błędnie zinterpretować, stracić z nim kontakt w trakcie długiej sesji, rozważyć je w kontekście sprzecznych instrukcji znajdujących się gdzie indziej, przekonać siebie, że aktualny przypadek jest wyjątkiem, lub osiągnąć ten sam destruktywny rezultat za pomocą innego narzędzia, którego reguła wyraźnie nie obejmowała. Prośba o uniknięcie czegoś jest zasadniczo inna od uczynienia tej rzeczy niemożliwą bez upoważnienia. Prompt wyraża życzenie:
Please don't do X.
„Harness” może wyrażać regułę, która jest ewaluowana w kodzie:
if dangerous_action and not approved:
deny()
Druga wersja działa niezależnie od tego, czy model pamięta instrukcję. To stanowi pierwszą zasadę inżynierii narzędzi: gdy reguła jest deterministyczna, należy ją zaimplementować w kodzie deterministycznym. Claude Code postępuje tak samo w swojej architekturze. Hooki uruchamiają się przy zdarzeniach cyklu życia i wywołaniach narzędzi i mogą na przykład odrzucić wywołanie narzędzia przed jego wykonaniem, podczas gdy pliki takie jak CLAUDE.md dostarczają wskazówek, które model odczytuje jako kontekst. Jeśli piszesz takiego pliku, przechowuj go jako źródło wskazówek, a realizację zasad przenieś do hooków; nasze przewodnik dotyczący skutecznego pliku CLAUDE.md opisuje, co powinno się w nim znajdować.
Szczegół 1: granica wykonywania pomiędzy żądaniem a akcją
Pierwszym pytaniem, które musi rozstrzygnąć system zarządzania zasobami, jest to, jakie działania agent może w ogóle wykonać. Rozważmy narzędzie, które usuwa plik.
def delete_file(path):
os.remove(path)
Model może je wywołać z dowolnym argumentem, jaki mu się podoba.
delete_file("important.md")
Jeśli to wywołanie następuje natychmiast, model ma nieograniczoną władzę nad wszystkim, do czego może dotrzeć dana funkcja. Rozwiązaniem jest kierowanie każdego wywołania przez mechanizm kontrolny, który sprawdza zasady przed jego wysłaniem.
def execute(call):
if call.name == "delete_file":
if not call.args.get("human_approved"):
return "DENIED: human approval required"
return dispatch(call)
Teraz model nadal może prosić o usunięcie, ale proszenie już nie oznacza realizacji. Proces staje się decyzją zgodną z zasadami, która ma dwa możliwe wyniki.
Model decision
↓
Policy check
↓
Permission?
↙ ↘
No Yes
↓ ↓
Deny Execute
To odzwierciedla konwencjonalny projekt bezpieczeństwa: model proponuje, a czas wykonywania decyduje o realizacji. Jednym szczegółem, który warto udoskonalić w rzeczywistym kodzie, jest źródło zatwierdzenia. W powyższym szkicu flaga zatwierdzenia jest odczytywana z argumentów samej funkcji, które generuje model. W środowisku produkcyjnym zatwierdzenie powinno pochodzić z innego źródła – np. z kroku potwierdzenia przez człowieka lub podpisanego tokena, którego model nie może sfałszować; w przeciwnym razie model może po prostu sam ustawić tę flagę.
Dlaczego kontrole na poziomie narzędzia są nieskuteczne
Zasady narzędzi są konieczne, ale niewystarczające. Wyobraźmy sobie sytuację, gdy narzędzie odrzuca tę funkcję:
delete_file("secrets/api_key")
To wygląda jak ochrona, dopóki agent nie uruchomi zamiast tego odpowiedniego polecenia w shellu:
rm secrets/api_key
Zasada delete_file nigdy nie dostrzega tej operacji. Albo narzędzie blokuje odczyt tajnego ścieżki:
read("secrets/api_key")
Jednak ścieżka względna może przejść niezauważona, ponieważ nikt jej nie znormalizował:
read("../secrets/api_key")
Symlinki, programy pomocnicze otwierające pliki w imieniu agenta oraz interpreterzy przyjmujące dowolny kod tworzą podobne „boczne drzwi”. Polityka sformułowana w kategoriach nazw narzędzi i argumentów tekstowych nie może wymienić wszystkich dróg do zasobu, więc nie stanowi kompletnego ograniczenia bezpieczeństwa. Wytyczne OpenAI dotyczące obsługi agentów programistycznych zalecają łączenie sandboxingu, polityk zatwierdzania, ograniczonego wykonywania, kontroli sieciowych oraz telemetrii zamiast polegania wyłącznie na instrukcjach. Zasada, którą należy zachować: narzędzie implementuje politykę, a system operacyjny stanowi ostateczną barierę bezpieczeństwa.
Szczegół 2: sandboxing tego, do czego agent może fizycznie dotrzeć
Polityka określa, co agent ma prawo robić; sandbox pyta natomiast, do czego może w ogóle dotrzeć. Słabszym podejściem jest lista zakazów, która próbuje wymienić każde wrażliwe miejsce.
Don't access:
- /etc
- ~/.ssh
- secrets/
- production/
- credentials/
- ...
Takie listy nigdy nie są kompletnymi. Silniejszym podejściem jest odwrócenie standardowej zasady: nie przyznawać prawie nic, a następnie dodać dokładnie to, czego potrzebuje zadanie, na przykład pojedynczą przestrzeń roboczą projektu.
Agent workspace:
/workspace
├── src/
├── tests/
├── pyproject.toml
└── README.md
Agent otrzymuje na hostingu tylko /workspace, nic więcej. Wyrażone jako polityka, stanowi to listę dopuszczeń.
Allowed:
/workspace
Everything else:
unavailable
Ponieważ reszta systemu plików po prostu nie istnieje z punktu widzenia agenta, sztuczki z ścieżkami, symbole linkowe oraz procesy pomocnicze tracą większość swojej skuteczności. Kontenery, dedykowane maszyny wirtualne oraz ograniczone konta użytkowników to powszechne sposoby realizacji tego rozwiązania. SDK Agents firmy OpenAI dodało wbudowaną możliwość wykonywania w środowisku sandbox właśnie w tym celu, dzięki czemu agenci mogą instalować zależności, edytować pliki i wykonywać polecenia w kontrolowanym środowisku.
Ograniczenia sieciowe i zasobowe powinny znajdować się w sandbox
Izolacja systemu plików to nie wszystko. Agent, który może wykonywać tak proste operacje, ma zupełnie inny profil zagrożeń:
curl https://example.com
Dzięki możliwości połączenia z siecią agent może:
- przeglądać i uruchamiać dowolne oprogramowanie
- wywozić dane na zewnętrzny serwer
- korzystać z API stron trzecich
Zatem prawdziwa przestrzeń bezpieczeństwa obejmuje kilka aspektów, a nie tylko pliki.
Filesystem
Network
Processes
Environment variables
Secrets
CPU
Memory
Time
Procesy w tle dziedziczą zmienne środowiskowe i poufne dane, a limity CPU, pamięci i czasu zapobiegają niekontrolowanemu wykonywaniu zadań. To właśnie ze względu na tak szeroki zakres nowoczesne środowiska wykonawcze projektują przestrzeń bezpieczeństwa jako kompletną środowisko wykonawcze, a nie tylko cienką otoczkę.
Szczegół 3: trwały stan przetrwający sesję
Przy długotrwałych zadaniach pojawia się inny rodzaj awarii. Agent spędza godzinę na przeglądaniu repozytorium i poznaje ważną zasadę architektury.
The authentication service must never directly access the database.
All database operations go through Repository classes.
Następnie okno kontekstowe wypełnia się, sesja jest restartowana i ta wiedza znika. Następna sesja nie ma pojęcia, dlaczego projekt wygląda w taki sposób, i może swobodnie go naruszać. Historia rozmów to niewłaściwe miejsce na tego typu informacje. Przydatne narzędzie dzieli co najmniej trzy kategorie informacji o różnych okresach ważności.
Conversation state
↓
temporary
Project state
↓
persistent
Harness configuration
↓
persistent + globally enforced
Konkretne przykłady każdej z nich:
Conversation:
"Let's investigate the login bug."
Project:
"Authentication uses OAuth."
Harness:
"Never modify generated migrations."
Element rozmowy może bezpiecznie zniknąć po zakończeniu zadania. Informacje o projekcie powinny przetrwać pomiędzy sesjami, na przykład w pliku z notatkami w wersjonowaniu lub w pamięci przechowującej dane. Zasada harness powinna być stosowana przy każdym uruchomieniu, niezależnie od tego, co aktualnie pamięta model, co zazwyczaj oznacza, że znajduje się ona w kodzie konfiguracyjnym i służącym do egzekwowania zasad, a nie w tekście. Im dłuższe są sesje, tym ważniejszy staje się ten podział. API Agents firmy OpenAI zawiera na przykład funkcje zarządzania kontekstem przeznaczone dla agentów działających przez długi czas, w tym automatyczną kompresję kontekstu gdy sesja zbliża się do swojego limitu. To właśnie w momencie kompresji tracą się niezapisane informacje o projekcie, dlatego warto je celowo przechowywać przed tym momentem. Aby dowiedzieć się więcej na temat poziomów pamięci, zobacz pamięć agenta o czterech poziomach z użyciem LangGraph i Amazon Bedrock.
LangGraph i Bedrock.Szaryf 4: weryfikacja, czy agent nie posiada
Agenci mogą się mylić z pełnym przekonaniem, dlatego agent, który wprowadził zmianę, nie powinien decydować o jej poprawności. Weźmy ten wynik:
def calculate_total(items):
return sum(item.price for item in items) + 1
Samotny + 1 może wydawać się celowy dla modelu, który go napisał. Niezależny krok weryfikacji może ocenić tę zmianę na podstawie kilku wskaźników.
Code
Tests
Type checking
Linting
Security rules
Expected behavior
To, co czyni to cennym, to rozdzielenie procesu tworzenia od oceny.
Agent
│
↓
Changes
│
↓
Verification
↙ ↘
PASS FAIL
↓ ↓
Continue Investigate
Pomyślne przejście pozwala pętli kontynuować; niepowodzenie zmusza agenta do ponownej analizy. Jedna istotna korekta jest łatwa do przeoczenia: osoba sprawdzająca powinna zgłaszać problemy, zamiast je po cichu naprawiać. Jeśli osoba weryfikująca potajemnie poprawi błąd, tracimy informację o tym, że pierwotny agent poniósł porażkę, a nasze metryki sukcesu stają się nieprawdziwe.
Testy bez faktycznych zmian jako standard dla ryzykownych modyfikacji
W przypadku operacji o większym znaczeniu standardem powinno być przeglądanie zachowania domyślnego. Zamiast funkcji stosującej zmiany natychmiastowo:
apply_change()
należy użyć takiej, której bezpiecznym domyślnym modelem jest test bez faktycznych zmian:
apply_change(dry_run=True)
Agent najpierw otrzymuje opis efektu tych zmian.
Would modify:
src/auth.py
tests/test_auth.py
Tylko wyraźny, oddzielny krok, najlepiej wymagający zatwierdzenia, przechodzi od przeglądu do wykonania. Dzięki temu zarówno osoba sprawdzająca, jak i każdy inny recenzent mają coś konkretnego do przeanalizowania przed wprowadzeniem jakichkolwiek zmian.
Szczegół 5: inżynieria kontekstu
Każdy token umieszczony w kontekście kosztuje pieniędzy, konkuruje o uwagę modelu i przy długich zadaniach ma tendencję do gromadzenia się szybciej, niż zostaje usunięty. Załóżmy, że agent potrzebuje jednej funkcji z pliku składającego się z 5000 linii. Proste rozwiązanie polega na wysyłaniu całego pliku, następnie pełnego wyniku kolejnych poszukiwań, potem wyniku kolejnego narzędzia i tak dalej. Wkrótce kontekst zawiera już to wszystko:
Task
+ entire repository
+ previous searches
+ tool output
+ logs
+ previous reasoning
+ repeated instructions
Model technicznie może widzieć każdy token, ale widoczność nie oznacza zrozumienia. Lepszy projekt traktuje kontekst jako łańcuch przetwarzania, który skondensowuje informacje przed ich dotarciem do głównego agenta.
Main Agent
│
├── Search Agent
│ │
│ └── 50,000 tokens
│
│ ↓
│
└── 1,000-token summary
Tutaj agent poszukiwawczy może zużyć 50 000 tokenów podczas eksploracji, ale główna sesja otrzymuje jedynie streszczenie zawierające 1 000 tokenów z najważniejszych informacji. To mocny argument na rzecz subagentów. Na przykład Claude Code opisuje subagenty jako elementy działające w swoich oddzielnych oknach kontekstowych i zwracające do głównej rozmowy tylko swój ostateczny wynik, co zapobiega przepełnieniu głównego kontekstu obszernymi dochodzeniami pobocznymi. Wadą jest to, że streszczenie może pominąć szczegóły, których agent główny będzie potrzebował później, dlatego streszczenia powinny zawierać wskazówki (ścieżki plików, zakresy linii), które umożliwią agentowi pobrać konkretne informacje na żądanie.
Ekonomia: cena za token to nie koszt za zadanie
Zarządzanie kontekstem to również kwestia budżetu. Przypomnijmy badanie, które wykazało różnicę sięgającą 40 razy w liczbie tokenów na rozwiązane zadanie pomiędzy różnymi narzędziami, przy znacznie mniejszych różnicach w stopie sukcesów. To zmienia to, jakie pytanie warto zadać. Zamiast „który model jest najtańszy?”, zapytajmy, ile tokenów potrzebuje cały system agenta, aby ukończyć zadanie. Porównajmy dwa takie rozwiązania.
Agent A: tańszy model, marnotrawne narzędzie
Model:
$X / million tokens
Task:
500k tokens
Agent B: droższy model, efektywne narzędzie
Model:
2X / million tokens
Task:
100k tokens
Agent B płaci dwa razy więcej za token, ale używa jednej piątej tokenów, więc każde ukończone zadanie kosztuje mniej więcej 40 procent tego, co wydaje Agent A, jeszcze zanim weźmiemy pod uwagę różnice w stopie sukcesu. Cena modelu jest tylko jednym z czynników; ekonomika agenta zależy od ilości pracy, jaką narzędzie nakłada na model. Nasz model kosztów oparty na architekturze dla agentic AI omawia to bardziej szczegółowo.
Rundy bez działań i polityki zakończenia
Część strat jest niewidoczna w metrykach na zapytanie. Wyobraźmy sobie agenta, który utknął w ogłaszaniu swoich zamiarów bez podejmowania żadnych działań:
I should inspect the repository.
i ponownie w następnej rundzie:
I should inspect the repository.
i jeszcze raz:
I should inspect the repository.
Nic się nie zmienia, a mimo to każda tura zużywa tokeny, czas oczekiwania, zasoby obliczeniowe, przestrzeń kontekstową, a czasem także pieniądze. Ten sam model badawczy opisuje ten nakład pracy jako podatek od oczekiwania na wykonanie zadania, a nie tylko podatek od tokenów – użytkownicy muszą czekać na tury, które nic nie osiągają. System wymaga reguł zakończenia, a najprostszą z nich jest ustalenie sztywnej granicy liczby tur.
MAX_TURNS = 30
if agent.turns >= MAX_TURNS:
stop()
Granica to zabezpieczenie, a nie strategia. Bardziej przydatne systemy potrafią wykrywać sygnały wskazujące na zatrzymanie się procesu.
No progress
Repeated tool calls
Repeated identical observations
No state change
Test suite unchanged
Agent oscillation
Budget exhausted
Powtarzające się identyczne wywołania narzędzi, niezmienne obserwacje, brak zmian w systemie plików, zestaw testów, który nadal zawodzi w ten sam sposób, oscylacje pomiędzy dwoma stanami lub wyczerpany budżet – wszystko to oznacza, że kontynuowanie pracy raczej nie pomoże. W takiej sytuacji narzędzie powinno się zatrzymać, podsumować sytuację i przekazać ją wyższym szczeblom. Nasz przewodnik po ograniczonych pętlach agentowych w TypeScript pokazuje te wzorce w kodzie.
Projektowanie narzędzi programistycznych staje się odrębną dziedziną. Niedawne badanie kodu źródłowego jedenaście systemów agentów programistycznych wykazało u nich powtarzające się wzorce architektury: wykonywanie narzędzi, zarządzanie kontekstem, mechanizmy bezpieczeństwa, orkiestracja oraz możliwości rozszerzania. Autorzy doszli do wniosku, że takie narzędzia ewoluowały z prostych środków w pełnoprawne platformy. Wczesne agenty wyglądały następująco:
LLM + tools
Obecne systemy przypominają stos.
LLM
↓
Agent loop
↓
Tool router
↓
Policy engine
↓
Sandbox
↓
Context manager
↓
Memory
↓
Verification
↓
Observability
↓
Orchestration
Model nadal stanowi rdzeń, ale środowisko działania wokół niego – od routera narzędzi i silnika polityk przez sandbox, menedżer kontekstu, pamięć, mechanizmy weryfikacji, możliwości obserwowania oraz orkiestrację – stało się samodzielnym produktem.
Przykładowa struktura agenta programistycznego
Rozsądna architektura początkowa dla agenta programistycznego umieszcza pętlę agenta bezpośrednio pod modelem i dzieli się na trzy komponenty: router narzędzi, menedżer kontekstu oraz pamięć. Wywołania narzędzi przechodzą przez silnik polityk do środowiska sandbox, wyniki są weryfikowane, a wszystko jest rejestrowane za pomocą mechanizmów obserwowalności.
┌──────────────┐
│ Model │
└──────┬───────┘
│
↓
┌─────────────────┐
│ Agent Loop │
└────────┬────────┘
│
┌─────────────┼─────────────┐
↓ ↓ ↓
Tool Router Context Memory
│ Manager │
↓ │ ↓
Policy Engine │ Persistent State
│ │
↓ ↓
Sandbox ←────── Tools
│
↓
Verification
│
↓
Observability
Uczyń każdy komponent niezależnie testowalnym: przeprowadź testy jednostkowe silnika polityk przy użyciu syntetycznych wywołań, sprawdź obsługę różnorodnych ścieżek i ocenij działanie mechanizmu weryfikacji na znanych błędnych plikach, wszystko to bez wywoływania modelu.
Rozwijaj rozwiązanie na podstawie błędów, a nie frameworka
Aby czerpać te korzyści, nie potrzebujesz rozbudowanego frameworka dla agentów. Pętla centralna może pozostać mała nawet po dodaniu silnika polityk, mechanizmów sandboxingu i weryfikacji.
while turns < MAX_TURNS:
action = model.next_action(context)
if action.is_final:
return action.answer
if not policy.allows(action):
context.append("Action denied")
continue
result = sandbox.execute(action)
verification = verifier.check(result)
context.append(
summarize(result, verification)
)
Zwróć uwagę na kolejność działań: sprawdzenie zasad następuje przed wykonaniem, odmówiona akcja jest zgłaszana z powrotem do modelu zamiast powodować przerwanie pętli, wykonanie zawsze odbywa się w środowisku sandbox, a to, co wraca do kontekstu, to streszczenie wyniku oraz jego weryfikacja, a nie surowy wyjście. Dopiero wtedy należy dodawać złożoność tylko w odpowiedzi na zaobserwowany błąd.
Agent deleted something?
→ add execution policy
Agent accessed the wrong file?
→ strengthen sandbox
Agent forgets architecture?
→ add persistent project memory
Agent produces bad code?
→ add verification
Agent becomes expensive?
→ optimize context
Agent loops?
→ add termination detection
Każdy objaw odpowiada dokładnie jednemu warstwie. Jest to o wiele lepsze niż wprowadzanie pięćdziesięciu abstrakcji, zanim dowiemy się, jaki mamy problem. Aby uzyskać szerszą dyskusję na temat tego, czy budować tę pętlę samodzielnie, czy zastosować gotowe rozwiązanie, zapoznaj się z runtime harnesses vs composed frameworks.
Repozytorium jako baza wiedzy agenta
W rozwoju opartym na agentach repozytorium to coś więcej niż kod źródłowy. Może zawierać wszystko, czego agent potrzebuje do pracy nad projektem: decyzje architektoniczne, polecenia do rozwoju i testowania, słownictwo specyficzne dla danej dziedziny, schematy, plany, podręczniki operacyjne oraz instrukcje specyficzne dla agenta – wszystko to jest wersjonowane obok kodu, który opisują. Własne opracowania OpenAI na temat inżynierii agentów podkreślają tę kwestię, traktując wersjonowane pliki przechowywane w repozytorium jako system rejestrujący to, co agent musi znać, aby zrozumieć i zmienić projekt, oraz zalecają użycie mapy wskazującej na konkretne dokumenty zamiast jednego ogromnego pliku z instrukcjami. Konsekwencja jest oczywista: decyzja projektowa, która istnieje tylko w umyśle kogoś lub w wątku rozmowy, nie istnieje dla agenta. Umożliwienie odkrywania wiedzy stało się częścią architektury oprogramowania.
Hooks: zachowanie, którego model nie musi pamiętać
Haki należą do najprzydatniejszych elementów bazowych harnessu. Hak umożliwia środowisku uruchomieniowemu reagowanie na zdarzenia cyklu życia za pomocą kodu deterministycznego. Najbardziej oczywisty z nich kontroluje wywołania narzędzi.
Before tool call
↓
Check policy
↓
Allow / deny
Kolejny zapewnia spójność jakości kodu po każdej modyfikacji.
After file edit
↓
Run formatter
↓
Run type checker
Trzeci chroni wiedzę przed kompresją kontekstu.
Before context compaction
↓
Persist important state
Czwarty tworzy ślad audytowy.
After task completion
↓
Generate audit record
Claude Code dokumentuje haki jako polecenia uruchamiane na podstawie zdarzeń cyklu życia, które działają w sposób deterministyczny i mogą między innymi zablokować wywołanie narzędzia przed jego wykonaniem. Ich siła wynika z przeniesienia zachowań całkowicie poza mechanizmy rozumowania modelu. Zamiast pisać w instrukcji „proszę pamiętać o uruchomieniu formatera” i mieć nadzieję, środowisko uruchomieniowe po prostu uruchamia formatera za każdym razem.
Nigdy nie pozwól modelowi kontrolować granic
Modele są probabilistyczne; granice bezpieczeństwa nie powinny nim być. Ten antypatron przekazuje decyzję modelowi:
if model_says_safe:
execute()
Ten patron przekazuje ją infrastrukturze, z której nie można wydobyć innej odpowiedzi:
if operating_system_allows:
execute()
Wykorzystuj model do decyzji, które wymagają osądu, a deterministyczną infrastrukturę do decyzji, które potrzebują gwarancji. W praktyce każda warstwa odpowiada na swoje własne pytanie.
Model:
Should I modify this file?
Harness:
Is this file inside the workspace?
OS:
Can this process write to the file?
Human:
Should this high-risk action proceed?
Model decyduje, czy zmiana jest dobrym pomysłem, narzędzie sprawdza, czy cel znajduje się w obszarze pracy, system operacyjny decyduje, czy proces może zapisać plik, a człowiek decyduje, czy działanie o wysokim ryzyku powinno zostać przeprowadzone. Takie warstwowe rozwiązania są znacznie bardziej odporne niż oczekiwanie, że jakaś pojedyncza komponenta wszystko załatwi poprawnie.
Narzędzia wzmacniają modele; nie zastępują ich
Może się wydawać, że uprzęże są ważniejsze od modeli. Dowody tego nie potwierdzają. W badanym układzie wybór uprzęży miał duży wpływ na efektywność wykorzystania zasobów, ale znacznie mniejszy wpływ na sukces zadania, a żadna ilość modyfikacji w czasie działania nie zamieni słabego modelu w silnego inżyniera oprogramowania. Prosty sposób na rozróżnienie tych dwóch elementów:
Model capability
=
What the agent can reason about
Harness quality
=
How effectively that capability is deployed
Genialny model w słabym środowisku wykonawczym marnuje ogromne ilości zasobów i pieniędzy. Starannie zaprojektowane środowisko wykonawcze wokół słabego modelu nadal daje słabe wyniki, choć w sposób bezpieczny i efektywny. Potrzebne są oba elementy.
Pięć pytań, które należy zadać przed wdrożeniem jakiegokolwiek agenta
1. Co może robić?
Spisz wszystkie narzędzia i zaznacz każdą niebezpieczną operację.
read
write
delete
execute
network
deploy
send_message
2. Do czego może dotrzeć?
Definicje narzędzi opisują tylko część obrazu sytuacji. Sprawdź, do czego proces faktycznie może uzyskać dostęp:
filesystem
network
environment
secrets
processes
credentials
3. Co przetrwa restart?
Zrestartuj agenta i dowiedz się:
What does it remember?
What does it forget?
Where is important state stored?
4. Kto weryfikuje wynik?
Dla operacji o znaczeniowym wpływie jednoetapowy proces nie wystarcza:
generate → approve
Wstaw niezależne sprawdzenia pomiędzy generowaniem a zatwierdzeniem:
generate
↓
test
↓
review
↓
approve
5. Ile naprawdę kosztuje każde zadanie?
Liczby tokenów na zapytanie same w sobie są mylące:
tokens per request
Mierząc zamiast tego wyniki:
tokens per successful task
latency per successful task
tool calls per task
retries per task
human interventions
Tokeny, opóźnienia, wywołania narzędzi, próby ponowne oraz interwencje ludzkie na zadanie zakończone pomyślnie to wskaźniki pokazujące, czy system jest wart uruchamiania.
Funkcjonalna definicja agenta produkcyjnego
Łączenie poszczególnych warstw daje bardziej dokładną definicję.
Agent =
Model
+ Tools
+ Execution Environment
+ Policy
+ Memory
+ Context Management
+ Verification
+ Observability
Każdy element ma swoje miejsce. Bez modelu nie ma inteligencji; bez narzędzi nie ma działania; bez środowiska wykonywania i polityki agent może być niebezpieczny; bez pamięci długie zadania stają się kruche; bez zarządzania kontekstem koszty rosną wykładniczo; bez weryfikacji błędy rozprzestrzeniają się niezauważone; a bez możliwości obserwacji nie można odtworzyć tego, co się stało, gdy coś pójdzie nie tak.
Podsumowanie
Rozmowy w branży przesuwają się od pytania, który model najlepiej radzi sobie z testami porównawczymi, na to, jaki środowisko działania umożliwia modelowi niezawodne wykonywanie użytecznych zadań. Dostawcy koncentrują się na tych samych elementach budulcowych: OpenAI sprzedaje teraz zarządzaną infrastrukturę agentów, która obejmuje sandboxy, obsługę kontekstu, wyszukiwanie narzędzi, wywoływanie narzędzi z kodu oraz długotrwałe wykonywanie zadań, natomiast Anthropic udostępnia trwałe instrukcje, umiejętności, podagenty oraz deterministyczne mechanizmy. Badania zaczynają traktować tę infrastrukturę jako zmienną eksperymentalną, zamiast postrzegać model jako cały system. Te funkcje rozwijają się szybko, więc sprawdź aktualną dokumentację.
Naiwny schemat tworzenia agenta jest krótki:
Pick LLM
+
Add tools
=
Agent
Rzeczywisty wygląda tak:
Model
↓
Agent Runtime
↓
┌─────────┼─────────┐
↓ ↓ ↓
Policy Context Memory
↓ ↓ ↓
Sandbox Tools Persistence
└─────────┼─────────┘
↓
Verification
↓
Observability
Model podejmuje decyzje; narzędzie określa warunki, w których te decyzje przekształcają się w działania. Zanim wybierzesz framework, zastanów się, co się dzieje, gdy model się myli, i oprzyj narzędzie wokół tej odpowiedzi.
- Wdroż reguły deterministyczne w kodzie i hookach, a nie w promptach.
- Traktuj zasady narzędzi jako pierwszą linię obrony, a sandbox systemu operacyjnego, włączając ograniczenia sieciowe i zasobów, jako rzeczywistą granicę.
- Rozdziel stan rozmowy, projektu i narzędzia według okresu ich trwania oraz przechowuj dane projektu przed jego kompresją.
- Zachowaj niezależność weryfikacji i spraw, aby recenzenci raportowali problemy, a nie je naprawiali.
- Optymalizuj liczbę tokenów na zakończony pomyślnie zadanie oraz przerywaj wykonywanie zadań, które nie przynoszą postępów.
Celem nie jest agent, który nigdy się nie myli, lecz system, w którym błąd modelu nie przekształca się automatycznie w incydent produkcyjny.
Literatura pokrewna
- Budowanie osobistego agenta AI, któremu można zaufać: pamięć, narzędzia i dostęp uzyskany — Jak osobisty agent taki jak Hermes Agent łączy pamięć, narzędzia oraz routowanie modeli, oraz jak bezpiecznie wdrożyć go przy użyciu wąskich ról, źródeł o niskim ryzyku i dostępu uzyskanego.
- Projektowanie systemów wielu agentów w oparciu o A2A: węzły, pamięć i zarządzanie — Architektura referencyjna dla systemów wielu agentów zbudowanych na protokole A2A, obejmująca moduły agentów, typy pamięci, orkiestrację, zagrożenia bezpieczeństwa oraz listę kontrolną projektu.