Od inżynierii pętli do inżynierii grafów: budowa systemów niezawodnych
Od inżynierii pętli do inżynierii grafów: pętla agenta jako jednostka inżynieryjna, w której pojedyncza pętla ulega załamaniu z powodu splątanych stanów, oraz dlaczego grafy pomagają.
Źródła: From Loop Engineering to Graph Engineering: Building Reliable Agentic Systems in Tech Startups
To przewodnictwo pokazuje, jak odbudować ścieżkę od surowców do działającego systemu w ramach tematu: Od inżynierii pętli do inżynierii grafów: tworzenie niezawodnych systemów agentowych w startupach technologicznych. Skupia się na krokach operacyjnych, wyraźnych sprawdzeniach oraz kodzie, który można bez problemu dodać do repozytorium, nie musząc zgadywać intencji twórcy. Na etapie przeglądu należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu systemu. Obok wyników funkcjonalnych należy zapisywać czas wykonywania operacji oraz koszt tokenów lub zapytań. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z wersji demonstracyjnej do środowisk współdzielonych.
while not finished:
context = build_context(state)
action = model.decide(context)
observation = tools.execute(action)
state = update(state, action, observation)
1. Pętla agenta jako obiekt inżynieryjny
Gdy przechodzisz przez etap 1 The Agent Loop, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Ustaw punkty kontrolne po kosztownych krokach. Funkcja wznowienia nie powinna ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.
action = model(current_state)
observation = execute(action)
next_state = transition(current_state, action, observation)
continue_execution =
task_is_not_complete
and execution_budget_is_available
MAX_ITERATIONS = 12
MAX_TOOL_CALLS = 30
MAX_RUNTIME_SECONDS = 600
MAX_TOKEN_COST = 250_000
while budgets_available(state):
action = agent.next_action(state)
if not policy.allows(action):
return TerminalFailure("policy_violation")
result = execute_idempotently(action)
state = persist_transition(state, action, result)
verification = verifier.evaluate(state)
if verification.passed:
return VerifiedSuccess(
state=state,
evidence=verification.evidence
)
return TerminalFailure("budget_exhausted")
2. Gdzie zaczyna się psucie pojedynczego pętla
Gdy pracujesz nad etapem „Gdzie pojedynczy etap”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponowne, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. Ustal punkty kontrolne po kosztownych krokach. Narzędzie do kontynuacji pracy nie powinno ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.
Związanie stanów
Gdy przechodzisz przez etap powiązania stanów, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Ustalaj punkty kontrolne po kosztownych krokach. Narzędzie do kontynuacji pracy nie powinno ponownie naliczać opłaty za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł. Gdy przechodzisz przez etap powiązania stanów, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do wspólnych środowisk.
Niejednoznaczne uzupełnienie
Faza uzupełniania o niejednoznaczne wartości działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę o cofnięciu działań, zanim rozszerzysz zakres. Trzymaj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Utrzymuj stan struktury w formie prostych, typizowanych elementów. Wplecione bloki danych ukrywają informację o tym, który węzeł zapisał dane do którego pola, co powoduje przerwanie kontynuacji działania po zakłóceniach.
Globowe próby ponowne
Faza ponawianych prób na poziomie globalnym działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię do analizy. Zanim rozszerzysz zakres, zapisz jeden idealny przypadek działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań. Zdokumentuj zarówno prawidłowy przebieg operacji, jak i ścieżkę przywracania do normalnego stanu. Ponawianie prób, kontrola przez ludzi oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później w celu udoskonalenia. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wplecione struktury ukrywają informację o tym, który węzeł zapisał dane w danym polu, co utrudnia kontynuację pracy po przerwach.
Słaba izolacja błędów
Faza izolacji błędów The Weak funkcjonuje najlepiej, gdy jest traktowana jako mierzalna powierzchnia. Zapisz jeden „złoty zapis”, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wkładki nawiasowe ukrywają informację o tym, który węzeł zapisał dane do którego pola, co powoduje przerwę w kontynuacji działania po przerwach. Faza izolacji błędów The Weak funkcjonuje najlepiej, gdy jest traktowana jako mierzalna powierzchnia. Zapisz jeden „złoty zapis”, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z wersji demonstracyjnej do środowisk współdzielonych.
Agregacja uprawnień
W fazie agregacji uprawnień należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać oddzielnie od kodu aplikacji. Pliki środowiskowe, magazyny tajemnic oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności przeglądania całej struktury. Zastosuj ludzką aprobatę dla operacji, które wiążą się z wydawaniem pieniędzy lub modyfikacją danych produkcyjnych. Połączenia skompilowane w czasie kompilacji nie gwarantują pełnej kompletności biznesowej.
Ograniczona równoczesność
W fazie ograniczonej jednoczesności należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanej punktacji kontrolnej, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponownego wykonania, kontrola przez ludzi oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później. Konieczna jest ludzka akceptacja w przypadku operacji, które powodują wydatki lub zmieniają dane produkcyjne. Połączenia realizowane w czasie kompilacji nie równają się kompletności rozwiązania biznesowego.
Słaba możliwość odtworzenia
W fazie ograniczonej możliwości ponownego uruchomienia należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, łatwe do przetestowania jednostki nad rozbudowanymi skryptami. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną strukturę procesów. Konieczne jest ludzkie zatwierdzenie w przypadkach, gdy dochodzi do wydatków lub zmian w danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie gwarantują kompletności rozwiązania biznesowego. W fazie ograniczonej możliwości ponownego uruchomienia należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Obok wyników funkcjonalnych należy rejestrować czas wykonywania oraz koszt tokenów lub zapytań. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do wspólnych środowisk.
3. Jakie zmiany wprowadza inżynieria grafów
Podczas przechodzenia przez 3 etapy inżynierii grafów najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całego grafu. Ustaw punkty kontrolne po kosztownych krokach. System powinien unikać ponownego naliczania opłat za tę samą funkcję LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.
Graph:
nodes
edges
shared state
terminal states
interface Node<Input, Output> {
id: string;
inputSchema: Schema<Input>;
outputSchema: Schema<Output>;
timeoutMs: number;
retryPolicy: RetryPolicy;
requiredCapabilities: Capability[];
execute(
input: Input,
context: RunContext
): Promise<Output>;
verify(
output: Output,
context: RunContext
): Promise<Evidence>;
}
interface Edge {
from: NodeId;
to: NodeId;
condition: (
state: WorkflowState
) => boolean;
}
const edges = [
edge(
"build",
"tests",
state => state.build.exitCode === 0
),
edge(
"build",
"repair",
state =>
state.build.exitCode !== 0 &&
state.repairAttempts < 3
),
edge(
"build",
"failed",
state =>
state.build.exitCode !== 0 &&
state.repairAttempts >= 3
)
];
4. Graf dla pipeline dostaw wspomaganych przez AI
Gdy opracowujesz diagram 4 A dla danej fazy, najpierw zapisz warunki umowy: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponowne, kontrolne punkty ludzkie oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później w celu udoskonalenia. Ustaw punkty kontrolne po kosztownych krokach. System powrotu nie powinien ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.
+----------------+
| Threat Model |
+--------+-------+
|
Intake -> Normalize -> Plan ------+-----> Implementation
| | |
| +-------v--------+ |
+--->| Test Planning |-----+
+----------------+ |
v
Build
|
+----------------------+------------------+
| pass | fail
v v
Integration Tests Diagnose -> Repair
| |
+----+----+ +-> Build
| |
pass fail
| |
v +-> Diagnose
Security Check
|
+----+----+
| |
pass high risk
| |
v v
PR Creation Human Approval
| |
+----+----+
|
v
Canary Deploy
|
Runtime Verify
| |
pass fail
| |
v v
Done Rollback -> Failed
5. Stan musi być typowany, trwały i podzielony
Gdy przechodzisz przez etap „5 State Must Be”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Ustalaj punkty kontrolne po kosztownych krokach. System powinien unikać ponownego naliczania opłat za tę samą funkcję LLM, gdy operator próbuje ponownie uruchomić późniejszy element. Gdy przechodzisz przez etap „5 State Must Be”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do wspólnych środowisk.
{
"runId": "run_93af",
"goal": {
"ticketId": "ENG-482",
"repository": "payments-api",
"baseRevision": "5df87a1"
},
"plan": {
"artifactId": "sha256:71d...",
"version": 2
},
"implementation": {
"commit": "81f3ce2",
"changedFiles": [
"src/refunds/service.ts",
"tests/refunds/service.test.ts"
]
},
"build": {
"exitCode": 0,
"artifactId": "sha256:932..."
},
"verification": {
"unitTests": "passed",
"integrationTests": "passed",
"security": "pending"
},
"budgets": {
"repairAttempts": 1,
"toolCalls": 18,
"tokens": 84320
}
}
{
"eventId": "evt_1092",
"runId": "run_93af",
"nodeId": "integration-tests",
"attempt": 2,
"inputHash": "sha256:8a2...",
"outputHash": "sha256:19c...",
"status": "succeeded",
"startedAt": "2026-09-14T08:41:02Z",
"completedAt": "2026-09-14T08:43:18Z"
}
6. Przejścia kontrolowane dowodami
Etap 6 Przejść kontrolowanych dowodami działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę o cofnięciu działań przed rozszerzaniem zakresu. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, składysek z danymi poufnymi oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całego grafu. Utrzymuj stan grafu w formie prostych, typizowanych struktur. Wplecione bloki danych ukrywają informację o tym, który węzeł zapisał dane w danym polu, co powoduje przerwanie kontynuacji działania po przerwach.
type TestEvidence = {
command: string;
revision: string;
exitCode: number;
totalTests: number;
failedTests: number;
reportArtifact: ArtifactRef;
};
function testsPassed(
evidence: TestEvidence,
workflow: WorkflowState
): boolean {
return (
evidence.exitCode === 0 &&
evidence.totalTests > 0 &&
evidence.failedTests === 0 &&
evidence.revision === workflow.currentRevision
);
}
repository_valid
and build_passed
and tests_passed
and security_accepted
and deployment_verified
7. Rodowód artefaktów i selektywne odtwarzanie
7 linii pochodzenia artefaktów oraz etapów pracy funkcjonuje najlepiej, gdy traktuje się je jako mierzalną powierzchnię. Zapisz jeden przykład udanego działania, jeden przypadek awarii oraz notatkę o cofnięciu zmian przed rozszerzeniem zakresu. Zdokumentuj zarówno ścieżkę udanego działania, jak i ścieżkę przywracania stanu. Próby ponownych działań, mechanizmy kontroli ludzkiej oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później. Utrzymuj stan grafu w formie prostych, spójnych struktur typowych. Wplecione elementy ukrywają informację o tym, który węzeł zapisał dane w danym polu, co utrudnia kontynuację pracy po przerwach.
{
"artifactId": "sha256:f39...",
"type": "test_report",
"producedBy": "integration-tests",
"graphVersion": "delivery-v4",
"inputs": [
"sha256:source-revision-81f3ce2",
"sha256:test-config-a17"
]
}
Source code changed:
invalidate build artifact
invalidate unit-test report
invalidate integration-test report
invalidate deployment artifact
Threat model unchanged:
preserve existing threat-model artifact
Requirements unchanged:
preserve normalized requirements
preserve approved implementation plan
8. Idempotencja i kontrola efektów ubocznych
Faza 8 dotycząca identyczności i efektów ubocznych funkcjonuje najlepiej, gdy jest traktowana jako mierzalna powierzchnia. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wtórne struktury danych ukrywają informację o tym, który węzeł zapisał dane do którego pola, co utrudnia kontynuację pracy po przerwach. Faza 8 dotycząca identyczności i efektów ubocznych funkcjonuje najlepiej, gdy jest traktowana jako mierzalna powierzchnia. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do wspólnych środowisk.
const idempotencyKey = [
runId,
nodeId,
inputArtifactHash
].join(":");
await deploymentApi.deploy({
idempotencyKey,
revision,
environment
});
deploy_canary -> verify_runtime
|
+-> failure -> rollback_canary
9. Deterministyczne i oparte na modelu routowanie
W fazie 9 „Deterministyczne i oparte na modelu” należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny poufnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepiej używać ustrukturyzowanych wyników z walidacją schematu niż tekstu w formie swobodnej.
if (testReport.failedTests > 0) {
return "repair";
}
if (securityReport.criticalFindings > 0) {
return "human-review";
}
return "deploy";
const decision = await riskClassifier.run({
changeSummary,
affectedServices,
dataClassification,
migrationPlan
});
type RiskDecision = {
level: "low" | "medium" | "high";
reasons: string[];
requiredChecks: CheckId[];
};
10. Planowanie, paralelizm i połączenia
Dla 10 przypadków równoległości planowania i etapów należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg procesu, jak i ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później. Konieczne jest uzyskanie zatwierdzenia człowieka w przypadku operacji, które powodują wydatki lub zmieniają dane produkcyjne. Połączenia realizowane w czasie kompilacji nie równają się pełności funkcjonalności biznesowej.
all required predecessor nodes are complete
and the incoming transition conditions are satisfied
+-> Generate Tests --+
Plan Complete ---+-> Threat Model ----+-> Join -> Implementation Review
+-> API Analysis ----+
Wszystko
Dla etapu All należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany proces. Konieczne jest ludzkie zatwierdzenie w przypadkach, gdy dochodzi do wydatków lub zmian w danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie równają się kompletności rozwiązania biznesowego. Dla etapu All należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do wspólnych środowisk.
Każdy
Gdy przechodzisz przez dowolny etap, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Ustaw punkty kontrolne po kosztownych krokach. System powrotu nie powinien ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator ponawia próbę z późniejszym węzłem.
Kworum
Gdy przechodzisz przez etap Quorum, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponowne, kontrola przez ludzi oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później. Ustal punkty kontrolne po kosztownych krokach. Narzędzie do kontynuacji pracy nie powinno ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.
Najlepsze starania
Gdy przechodzisz przez etap „Najlepszych starań”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Ustalaj punkty kontrolne po kosztownych krokach. System powinien unikać ponownego naliczania opłat za tę samą funkcję LLM, gdy operator próbuje ponownie uruchomić późniejszy element. Gdy przechodzisz przez etap „Najlepszych starań”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do wspólnych środowisk.
Szybkie wykrywanie błędów
Faza szybkiego zawodzenia działa najlepiej, gdy jest traktowana jako mierzalna powierzchnia. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę o cofnięciu zmian, zanim rozszerzysz zakres. Trzymaj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Utrzymuj stan struktury w prostym formacie i z określonym typem danych. Wplecione bloki danych ukrywają informację o tym, który węzeł zapisał dane w danym polu, co powoduje przerwanie kontynuacji działania po przerwach.
11. Semantyka awarii
Faza 11 „Semantyki niepowodzeń” działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden idealny zapis transakcji, jeden przypadek niepowodzenia oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres badania. Zdokumentuj zarówno ścieżkę pomyślnego przebiegu, jak i ścieżkę przywracania stanu. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości nieodebranych stanowią część produktu, a nie elementy dodawane później. Utrzymuj stan grafu w formie prostych, spójnych struktur typowych. Wkładki nawiasowe ukrywają informację o tym, który węzeł zapisał dane w danym polu, co utrudnia kontynuację pracy po przerwach.
type FailureClass =
| "transient_dependency"
| "invalid_input"
| "verification_failed"
| "policy_denied"
| "budget_exhausted"
| "human_rejected"
| "unknown";
transient_dependency -> retry with backoff
invalid_input -> return to the upstream producer
verification_failed -> diagnose and repair
policy_denied -> terminal failure
budget_exhausted -> human escalation
human_rejected -> terminal cancellation
unknown -> quarantine and inspect
repair_attempts_remaining
and runtime_budget_available
and token_budget_available
and permitted_blast_radius_not_exceeded
12. Granice bezpieczeństwa należą do węzłów
Faza „12 Security Boundaries Belong” funkcjonuje najlepiej, gdy traktowana jest jako mierzalna powierzchnia. Zanim rozszerzysz zakres, zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań. Wolij małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wkładki nawiasowe ukrywają informację o tym, który węzeł zapisał dane do którego pola, co powoduje przerwę w kontynuacji działania po zakłóceniach. Faza „12 Security Boundaries Belong” funkcjonuje najlepiej, gdy traktowana jest jako mierzalna powierzchnia. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.
nodes:
repository_analysis:
capabilities:
- repository:read
implementation:
capabilities:
- repository:read
- workspace:write
create_pull_request:
capabilities:
- repository:pull_request:create
deploy_canary:
capabilities:
- deployment:preview:create
production_release:
capabilities:
- deployment:production:create
approval:
required: true
13. Wersjonowanie i powtarzalność
W fazie 13 dotyczącej wersjonowania i powtarzalności należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Zatwierdzenie przez człowieka powinno być wymagane dla operacji, które wiążą się z wydawaniem pieniędzy lub modyfikacją danych produkcyjnych. Połączenia skompilowane w czasie kompilacji nie równają się pełności funkcjonalności biznesowej.
{
"runId": "run_93af",
"graph": {
"name": "software-delivery",
"version": "4.2.1"
},
"nodes": {
"planner": "planner@2.3.0",
"implementation": "coding-agent@5.1.2",
"security-review": "security-review@1.8.0"
},
"models": {
"planner": "model-a-2026-08",
"implementation": "model-b-2026-09"
},
"policyVersion": "delivery-policy@3.4.0",
"baseRevision": "5df87a1"
}
14. Obserwowalność na poziomie grafu
W fazie 14 „Obserwowalności w Graph” należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg procesu, jak i ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później. Konieczne jest uzyskanie zatwierdzenia człowieka dla operacji, które powodują wydatki lub zmieniają dane produkcyjne. Połączenia realizowane w czasie kompilacji nie równają się pełnej kompletności funkcjonalności biznesowej.
workflow_run_id
graph_version
node_id
node_attempt
parent_node_id
artifact_ids
model_version
prompt_version
15. Minimalna implementacja startupu
W fazie 15 A Minimal Startup należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Konieczne jest ludzkie zatwierdzenie w tych przypadkach, gdy dochodzi do wydawania pieniędzy lub modyfikacji danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie równają się pełnej kompletności biznesowej. W fazie 15 A Minimal Startup należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Obok wyników funkcjonalnych należy rejestrować czas wykonywania oraz koszt tokenów lub zapytań. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do wspólnych środowisk.
>workflow_definitions
workflow_versions
workflow_runs
node_definitions
node_attempts
transition_events
artifacts
approvals
capability_grants
def schedule(run):
state = load_state(run.id)
candidates = find_pending_nodes(run.graph_version)
for node in candidates:
if dependencies_satisfied(node, state):
if incoming_guards_allow(node, state):
enqueue(
run_id=run.id,
node_id=node.id,
graph_version=run.graph_version
)
def execute_node(job):
attempt = create_attempt(job)
try:
inputs = resolve_inputs(job)
validate(inputs, job.node.input_schema)
capabilities = issue_capabilities(job.node)
output = job.node.execute(inputs, capabilities)
validate(output, job.node.output_schema)
evidence = job.node.verify(output)
persist_success(attempt, output, evidence)
evaluate_outgoing_edges(job.run_id, job.node.id)
except Exception as error:
failure = classify_failure(error)
persist_failure(attempt, failure)
apply_failure_transition(job, failure)
finally:
revoke_capabilities(job.node)
16. Migracja z pętli na graf
Podczas przechodzenia przez etap 16 Migracja z pętli, najpierw zapisz specyfikację: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Trzymaj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całego grafu. Ustaw punkty kontrolne po kosztownych krokach. Narzędzie do kontynuacji pracy nie powinno ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.
Krok 1: Wyposażenie istniejącej pętli w narzędzia diagnostyczne
Gdy pracujesz nad etapem 1 instrumentacji, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponowne, kontrolne punkty ludzkie oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. Ustalaj punkty kontrolne po kosztownych krokach. Narzędzie do kontynuacji pracy nie powinno ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.
Krok 2: Identyfikacja stabilnych etapów
Gdy przechodzisz przez etap nr 2 „Identyfikacja stabilności”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Ustalaj punkty kontrolne po kosztownych krokach. System powinien unikać ponownego naliczania opłat za tę samą funkcję LLM, gdy operator próbuje ponownie uruchomić późniejszy element. Gdy przechodzisz przez etap nr 2 „Identyfikacja stabilności”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do wspólnych środowisk.
Etap 3: Definicja typowanych artefaktów
Krok 3, pole „Definiuj typy”, działa najlepiej, gdy traktuje się je jako mierzalną powierzchnię. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całego grafu. Utrzymuj stan grafu w formie prostej i z typami. Wplecione struktury ukrywają informację o tym, który węzeł zapisał dane w danym polu, co utrudnia kontynuację pracy po przerwach.
Krok 4: Eksternalizacja przejść
Etap 4, polegający na zewnętrznym przetwarzaniu przejść, działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny przypadek działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres projektu. Zdokumentuj zarówno ścieżkę pomyślnego działania, jak i ścieżkę przywracania do normalnego stanu. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wplecione struktury ukrywają informację o tym, który węzeł zapisał dane do którego pola, i powodują przerwanie kontynuacji działania po zakłóceniach.
Krok 5: Dodanie niezależnej weryfikacji
Etap 5 „Dodaj niezależny etap” funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań przed rozszerzaniem zakresu. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś etap zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wtórne struktury ukrywają informację o tym, który węzeł zapisał dane do którego pola, co utrudnia kontynuację pracy po przerwach. Etap 5 „Dodaj niezależny etap” funkcjonuje najlepiej, gdy traktowany jest jako mierzalna powierzchnia. Zapisz jeden idealny zapis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań przed rozszerzaniem zakresu. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.
Krok 6: Wprowadzenie punktów kontrolnych
W etapie 6, „Wprowadzenie punktów kontrolnych”, przed zmianą kodu należy zdefiniować dane wejściowe, osobę odpowiedzialną za ten etap oraz kryteria zakończenia. Operatorzy powinni móc ponownie uruchomić ten etap od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Zatwierdzenie przez człowieka powinno być wymagane dla operacji, które wiążą się z wydawaniem pieniędzy lub modyfikacją danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie równają się pełnej kompletności biznesowej.
Krok 7: Izolacja funkcjonalności
W fazie 7, polegającej na izolacji funkcjonalności, należy zdefiniować dane wejściowe, osobę odpowiedzialną za tę fazę oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić tę fazę na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg procesu, jak i ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później. Konieczne jest uzyskanie zatwierdzenia człowieka w przypadku operacji, które powodują wydatki lub zmieniają dane produkcyjne. Połączenia realizowane w czasie kompilacji nie równają się pełności funkcjonalności biznesowej.
Krok 8: Dodanie ograniczonych ścieżek naprawczych
W etapie „Dodaj ograniczenie” z kroku 8 należy najpierw zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Lepiej używać małych, łatwych do przetestowania jednostek niż rozbudowanych skryptów. Gdy jakiś krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Konieczna jest ludzka akceptacja w przypadkach, gdy dochodzi do wydawania pieniędzy lub modyfikacji danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie gwarantują kompletności rozwiązania biznesowego. W etapie „Dodaj ograniczenie” z kroku 8 należy najpierw zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Obok wyników funkcjonalnych należy rejestrować czas wykonywania oraz koszt tokenów lub zapytań. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.
Krok 9: Parallelizacja niezależnych od dowodów zadań
Podczas pracy nad etapem Krok 9: Parallelizacja niezależnych od dowodów zadań, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Ustaw punkty kontrolne po kosztownych krokach. System powrotu nie powinien ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.
Krok 10: Wersjonowanie struktury
Gdy pracujesz nad wersją kroku 10, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponowne, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. Ustalaj punkty kontrolne po kosztownych krokach. Narzędzie do kontynuacji pracy nie powinno ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.
17. Powszechne antypaternale w inżynierii grafów
Gdy przechodzisz przez 17 etapów projektowania grafów, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Ustalaj punkty kontrolne po kosztownych krokach. System powinien unikać ponownego pobierania opłat za tę samą funkcję LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.
Jeden agent na węzeł
Deterministyczne decyzje kontrolowane przez model
Wspólny, zmienialny stan
Nieograniczone cykle
Globowe uprawnienia
Brak ścieżek kompensacyjnych
Grafy bez historii zmian
Przedwczesne dynamiczne routowanie
18. Gdy graf jest niepotrzebny
Wniosek
Implicit control flow
becomes
explicit workflow topology
Conversation state
becomes
typed durable state
Agent-declared success
becomes
evidence-gated completion
Global retries
become
bounded local recovery
Shared privileges
become
node-scoped capabilities
Complete reruns
become
dependency-aware replay
Sequential execution
becomes
controlled concurrency
Opaque behavior
becomes
graph-level observability