IntentFlow: Zarządzanie agentami LLM za pomocą skompilowanej polityki i sprawdzalnych śladów działania
Przegląd IntentFlow – eksperymentalnego języka, który egzekwuje zasady agenta poza modelem i tworzy łańcuchy haszów z zapisami, które audytor może niezależnie zweryfikować.
Źródła: IntentFlow: Governed LLM Agents With Auditable, Hash-Chained Traces
Załóżmy, że agent LLM jest podłączony do odczytywania zgłoszenia na GitHubie, wyszukiwania plików w repozytorium, sporządzania odpowiedzi, a ponieważ ktoś się spieszył, agent publikuje tę odpowiedź i zamyka zgłoszenie. Zasady bezpieczeństwa zostały zawarte w instrukcjach: nigdy nie zamykać zgłoszenia, zawsze podawać dowody, w razie wątpliwości zwracać się do człowieka. Mimo to model i tak zamknął zgłoszenie.
To nie była zła wola. Zasady zapisane w prozie są jedynie sugestiami, a model, napędzany sprytnie sformułowanym tekstem zgłoszenia, czasami traktuje te sugestie jako opcjonalne. Gdy osoba sprawdzająca bezpieczeństwo żąda dowodów na to, że agent nigdy nie wykonał zabronionej czynności, istnieją jedynie logi aplikacji utworzone przez ten sam kod, w formacie wymyślonym przez kogoś innego. To nie są dowody – to zwykły dziennik.
IntentFlow to eksperymentalny język stworzony po to, by wypełnić tę lukę.
Gdzie zazwyczaj znajduje się zarządzanie
Większość zasad zarządzania agentami znajduje się w jednym z trzech miejsc, a każde z nich ma swoje wady:
- W instrukcji. Jest to proza, którą model może zignorować, a jedyną formą audytu jest przeczytanie końcowego wyniku i mieć nadzieję.
- W kodzie aplikacji. To jest rzeczywiste egzekwowanie zasad, ale polityka ta jest teraz splątana z kodem Python, który wywołuje model, a na pytanie „co agent miał prawo robić?” odpowiada się poprzez przeczytanie bazy kodu.
- W zbiorze funkcji zwrotnych frameworka. Funkcje są ze sobą łączone, podczas gdy polityka znajduje się w umyśle kogoś i w ad-hoc zapisach.
Brakuje pojedynczego, podlegającego weryfikacji artefaktu opisującego zakres dopuszczalnego zachowania: dowodów, które agent musi posiadać, działań, które może podjąć, tych, których nigdy nie może podjąć, czynników, które zmuszają człowieka do interwencji, oraz sposobu sprawdzania jego wyników. Taki artefakt powinien być egzekwowany poza modelem i powinien pozostawić świadectwo, które każdy może niezależnie zweryfikować później.
Idea w jednym akapicie
IntentFlow to mały język deklaratywny. Plik .iflow określa cel, wymagania dotyczące dowodów, zasady działania, reguły weryfikacji, sposoby radzenia sobie z niepewnościami oraz sformatowany kontrakt wyjściowy. Kompilator przekształca ten plik w plan wykonania w formacie JSON, który następnie realizowany jest przez system w czasie rzeczywistym składający się z 13 faz; każde wezwanie narzędzia jest przekazywane przez ActionGate, w tym również odczytanie dowodów z dysku. Ten mechanizm konsultuje skompilowaną politykę i nigdy nie odczytuje wyników modelu, dzięki czemu model nie może go obejść. Każde uruchomienie tworzy ślad w formie łańcucha hashów, opcjonalnie podpisany. Następnie intentflow audit odbudowuje reguły na podstawie pliku źródłowego i pokazuje, że uruchomienie przestrzegało ich zasad. Wystarczy mu ten plik oraz ślad – nie ma potrzeby ufać systemowi w czasie rzeczywistym, backendowi ani modelowi.
Słowa kluczowe projektu dobrze to podsumowują: programy w Pythonie realizują obliczenia deterministyczne, natomiast programy w IntentFlow kierują się kognicją.
Jak wygląda program
Głównym przykładem jest cel triażu problemów, pokazany tutaj w jego istocie zarządzania. Zaczyna się od nazwy i celu:
goal TriageGitHubIssue {
objective:
triage a GitHub issue safely and propose a maintainer-ready response
Pozostałe sekcje dotyczą dowodów, dozwolonych działań, weryfikacji, radzenia sobie z niepewnościami oraz kształtu wyniku:
evidence:
require issue_body
require comments
require repo_context
optional related_issues
distrust unsupported_claims actions:
allow read_issue
allow search_repo
allow draft_comment
require_approval post_comment
deny close_issue verify:
require cites_evidence
require maintainer_safe_tone
require no_unverified_claims
check confidence >= 0.65 uncertainty:
if confidence < 0.65 ask_human
if missing_evidence ask_human
if security_risk block_action output:
summary: string
likely_cause: string?
confidence: number
suggested_response: markdown
proposed_labels: list[string]
}
Przeczytaj to od góry do dołu, a dowiesz się, co może zrobić agent. deny close_issue nie jest radą – jest wbudowane w mechanizm kontrolny. Dzięki require_approval post_comment krok dalszy jest domyślnie odrzucany, dopóki osoba lub inny proces nie udzieli zatwierdzenia. Natomiast check confidence >= 0.65 to ścisła, liczbowa kontrola. Blok output: stanowi sformalizowany kontrakt, według którego weryfikowane są wyniki.
Jak to działa
Proces jest prosty, a każdy etap ogranicza możliwości następnego:
.iflow source -> parser -> analyzer (IFLOW diagnostics) -> compiler ->
execution plan (JSON) -> runtime (13-phase machine) -> traced result ->
replay / audit
Wielokrotne wybory projektowe sprawiają, że audyt ma sens, a nie jest jedynie dekoracyjny:
- Brama znajduje się poza modelem. Działania odrzucone lub niezlistowane powodują błędy, a działania wymagające zatwierdzenia kończą się niepowodzeniem bez udzielenia zgody. Ponieważ brama nigdy nie odczytuje wyników modelu, iniekcja poleceń nie ma żadnych możliwości manipulacji.
- Najpierw następuje kalibracja. Serwer backendowy zgłasza surową wartość pewności, a czas wykonywania dostosowuje ją zgodnie z polityką kalibracji planu, po czym reguły dotyczące niepewności analizują tę skorygowaną wartość. Łącznie obie wartości są przechowywane.
- Weryfikacja jest przeprowadzana w sposób ścisły, a nie domyślny. Reguły podlegające sprawdzeniu przez maszynę, takie jak
cites_evidence,requires_phraseoraz sprawdzenia progów, są wdrażane w odniesieniu do rzeczywistego stanu. Reguły wymagające oceny przez model językowy znajdują się w odrębnej kategorii zaufania i, gdy nie ma dostępnego sędziego, są rejestrowane jako pominięte i nigdy nie są przechodzone w tajemnicy. - Ślad jest tylko do dodawania i jest kompletny. Każda faza, decyzja bramy, eskalacja oraz sprawdzenie trafiają do zapisu łączonego łańcuchem haszów, gdzie każde zdarzenie przechowuje hasz poprzedniego hasza połączony z kanonicznym zdarzeniem. Podpisanie śladu zamyka jego korzeń za pomocą HMAC, dzięki czemu posiadacz klucza może wykryć modyfikacje.
Każdy przebieg kończy się jednym z sześciu możliwych stanów, a kod wyjścia procesu odzwierciedla go. Ważną gwarancją jest to, że nieudana weryfikacja kończy przebieg jako failed_verification. System nie może zgłosić tego jako completed, a jedna z kontrol audytora została stworzona specjalnie po to, by wykryć wszelkie próby ukrycia tego faktu.
Spróbuj w pięć minut
Jądro nie ma zależności od środowiska działania, a każda z poniższych komend działa offline i w sposób deterministyczny bez klucza API. Jest przeznaczone dla Pythona 3.10 lub nowszych wersji.
git clone https://github.com/dgenio/intentflow
cd intentflow
pip install -e .
Weryfikuj przykład flagowy, poproś o wyjaśnienie i uruchom go:
intentflow validate examples/opensource_triage.iflow
intentflow explain examples/opensource_triage.iflow
intentflow run examples/opensource_triage.iflow \
--backend simulate --trace-dir traces
Wykonanie drukuje podobny do tego podsumowanie, reprezentujące rzeczywiste wykonanie w wersji 0.6.0:
--- run summary ---
goal: TriageGitHubIssue
status: completed
backend: simulate
confidence: 0.676
verification: passed
uncertainty: clear
trace id: b9f44900...
trace written to traces/TriageGitHubIssue-...json
Teraz sprawdź, jak się zachowało. Polecenie audit ponownie kompiluje kod źródłowy i potwierdza, że ślad działania pozostał w granicach programu:
intentflow audit examples/opensource_triage.iflow traces/TriageGitHubIssue-*.json
Czysty wynik wygląda tak:
{
"goal": "TriageGitHubIssue",
"conformant": true,
"violations": []
}
AUDIT: CONFORMANT — the trace stayed inside the program's envelope
Aby zobaczyć, jak faktycznie aktywują się ograniczenia, spróbuj przykładu celowo ryzykownego. Pozwala on na wykonanie operacji wdrożenia bez żadnego kroku zatwierdzenia. Analizator wykrywa błąd IFLOW010, skompilowany profil ryzyka okazuje się wysoki, a po uruchomieniu reguły if security_risk block_action zostaje ona wdrożona:
intentflow run examples/high_risk_deploy.iflow --backend simulate
# -> status: blocked
Odrzucona akcja write_database nigdy nie może zostać wykonywana, bez względu na to, co mówi model.
To same funkcje są dostępne w Pythonie. Zacznij od importu:
import intentflow
Następnie załaduj program, uruchom go i zarejestruj funkcję Pythona jako kontrolowaną akcję:
program = intentflow.load("examples/opensource_triage.iflow")
result = program.run(backend="simulate")
assert result["status"] == "completed"# register a Python function as a governed action (runs through the gate):
program.register_tool("lookup_user", serves=("user_record",),
handler=lambda src: "enterprise plan")report = intentflow.audit_document(program.compile(), result)
assert report["conformant"]
Rejestracja narzędzia nie omija zasad zarządzania. Twoja funkcja nadal przechodzi przez bramkę działań.
Dlaczego poziom pewności spada z 0,72 na 0,676
To nie jest wada, lecz odzwierciedla całą ideę projektu. Przykład diagnostyki produkcyjnej wykorzystuje próg 0,7. W symulatorze surowy poziom pewności wynosi 0,72 i przekracza ten próg, ale kalibracja obniża go do 0,676, poniżej progu, więc proces celowo kończy się jako needs_human. Diagnoza, co do której agent nie jest pewny, nie powinna być realizowana bez nadzoru. Symulator służy do tego, aby cała ta struktura kontroli – bramki, kalibracji, weryfikacji, eskalacji i śledzenia – mogła być testowana od początku do końca bez konieczności korzystania z sieci lub problematycznego zachowania.
Szczerze mówiąc, ograniczenia
IntentFlow znajduje się w wersji 0.6.0 i jest klasyfikowany jako wersja przedalfa, bez obecnie żadnego pipeline’u CI. Funkcjonuje poprawnie, a repozytorium zawiera około 233 testów, które nie wymagają ani połączenia sieciowego, ani kluczy API, jednak istnieją poważne braki:
- Gramatyka jest zorientowana na linie i nie zawiera złożonych warunków, więc nie istnieje
if a and b. - Kalibracja polega na stałej macie skurczu, a nie na modelu nauczanym, chociaż planuje się użycie takiego modelu.
- Wyniki o kształcie obiektu mają typ tylko na najwyższym poziomie, przy czym nie ma żadnych wymogów dotyczących ich zawartości.
- Prymitywy niepewności inne niż
ask_humaniblock_actionsą rejestrowane, ale nie są wykonywane. - Narzędzia z efektami ubocznymi są objęte zasadami, ale nigdy tak naprawdę nie są uruchamiane. Istnieją reguły kontrolne dla nich, a rzeczywiste zapisy na zewnątrz są jeszcze przed nami.
- Pipeline’y są liniowe, natomiast DAG-y znajdują się na planach rozwoju.
Simulator symuluje krok rozumowania i o tym informuje. Istnieją backendy dla OpenAI i Anthropic, które przechodzą przez ten sam proces zarządzania, a tryb odtwarzania pozwala na wykonywanie zadań w sposób deterministyczny bez użycia kluczy. Mimo to punktem odniesienia dla zgodności pozostaje ten deterministyczny simulator.
Dla obecnego systemu zarządzania agentami produkcyjnymi to jeszcze nie jest rozwiązanie idealne. Aby jasno zrozumieć, jak powinno wyglądać audytowalne wykonywanie zadań przez agenta, oraz aby móc z tym eksperymentować, projekt jest niezwykle konkretny jak na swój wiek.
Co wynieść z tego
- Zachowaj politykę poza modelem. Tekst to jedynie prośba, natomiast skompilowany kod
denywspierany przez mechanizm ignorujący wyniki modelu stanowi twardą zasadę. - Samodzielnie tworzone logi niewiele dowodzą, natomiast ślad działania, który może sprawdzić niezależna strona, tak. Audytor ponownie wyprowadza zasady z źródła i potrzebuje tylko tego źródła oraz śladu.
Poprawne testowanie takiej idei oznacza nadanie jej rzeczywistego celu. Napisz plik .iflow dla agenta, który faktycznie używasz, sprawdź, czy polecenie explain opisuje to, co zamierzałeś, a następnie uruchom go w trybie symulacji i przeanalizuj wyniki.