176 lines
9.9 KiB
Markdown
176 lines
9.9 KiB
Markdown
# Architektura sieci agentowej modyfikującej kod
|
|
|
|
## 1. Problem
|
|
|
|
Zmiany typu "podnieś wersję SDK w 60 repozytoriach" są mechanicznie proste, ale kosztowne:
|
|
każde repozytorium ma inny układ, inne miejsca użycia biblioteki i inny poziom pokrycia testami.
|
|
Klasyczna automatyzacja (skrypt + sed) załatwia 70% przypadków i zostawia najgorsze 30%.
|
|
Agent z LLM załatwia pozostałe 30%, ale wprowadza trzy nowe problemy: niepowtarzalność,
|
|
brak audytowalności i nieograniczony zakres zmian.
|
|
|
|
Ten projekt jest odpowiedzią na pytanie: **jak wpuścić agenta do repozytorium tak,
|
|
żeby dało się to pokazać audytorowi.**
|
|
|
|
## 2. Trzy warstwy i jedna zasada
|
|
|
|
```
|
|
┌───────────────────────────────────────────────────────────────────┐
|
|
│ KONTEKST — APM (Microsoft Agent Package Manager) │
|
|
│ apm.yml + .apm/{instructions,skills,prompts,agents,context} │
|
|
│ Wersjonowany, pinowany lockfile'em, audytowany polityką. │
|
|
└──────────────────────────────┬────────────────────────────────────┘
|
|
│ apm install → apm_modules/
|
|
┌──────────────────────────────▼────────────────────────────────────┐
|
|
│ RUNTIME — agno Workflow │
|
|
│ Kompilacja prymitywów APM → Agent/Skills/Steps. │
|
|
│ Deterministyczne kroki + sandboxowane narzędzia. │
|
|
└──────────────────────────────┬────────────────────────────────────┘
|
|
│ agentic-codemod run
|
|
┌──────────────────────────────▼────────────────────────────────────┐
|
|
│ EGZEKUCJA — GitLab CI │
|
|
│ Efemeryczny job, bramka manualna, artefakty audytowe, MR. │
|
|
└───────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
Zasada nadrzędna: **kontekst jest artefaktem, nie kodem**. Zmiana zachowania sieci agentowej
|
|
(nowa reguła migracji, ostrzejszy guardrail, inny model dla roli) to podbicie wersji pakietu APM,
|
|
a nie merge request do Pythona. Dzięki temu zespół właściciela SDK może dostarczyć wiedzę
|
|
migracyjną, nie mając dostępu do silnika pipeline'u.
|
|
|
|
## 3. Przepływ
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
T[Trigger: issue z labelką / MR / harmonogram / formularz] --> C[apm install + apm audit]
|
|
C --> I[intake: deterministyczny wsad zadania]
|
|
I --> R[recon: fakty o repozytorium]
|
|
R --> P[plan: ChangePlan z kryteriami akceptacji]
|
|
P --> G{jest co wdrażać?}
|
|
G -- nie --> M[manifest + komentarz w issue]
|
|
G -- tak --> B[bump wersji: deterministyczny]
|
|
B --> L[pętla: implement → verify]
|
|
L -- czerwono, iteracja < limit --> L
|
|
L -- zielono --> V[review: recenzja diffa]
|
|
V --> S[scribe: opis merge requesta]
|
|
S --> H{bramka manualna w CI}
|
|
H -- zatwierdzone --> MR[branch + commit + push + MR]
|
|
H -- nie --> A[artefakty do wglądu, zero zmian zdalnych]
|
|
```
|
|
|
|
### Role w sieci
|
|
|
|
| Agent | Model | Narzędzia | Wyjście |
|
|
|---|---|---|---|
|
|
| `scout` | planner | odczyt, wyszukiwanie | `RepoProfile` |
|
|
| `planner` | planner | odczyt, wyszukiwanie | `ChangePlan` |
|
|
| `coder` | coder | odczyt, edycja, weryfikacja | zmieniony kod |
|
|
| `reviewer` | reviewer | odczyt, diff | `ReviewVerdict` |
|
|
| `scribe` | scribe | diff | `MergeRequestDraft` |
|
|
|
|
Definicje ról leżą w `.apm/agents/*.agent.md`. Kod nie zna nazw agentów - czyta je z kontekstu.
|
|
|
|
## 4. Co jest deterministyczne, a co należy do modelu
|
|
|
|
To jest najważniejsza decyzja projektowa. Model dostaje wyłącznie tę część pracy,
|
|
której nie da się zrobić inaczej.
|
|
|
|
| Krok | Wykonawca | Dlaczego |
|
|
|---|---|---|
|
|
| Wykrycie ekosystemu, plików zależności, komendy testowej | kod (`adapters/`) | jednoznaczne, sprawdzalne |
|
|
| Podbicie deklaracji wersji | kod (`adapters/`) | zero powodów, by ryzykować halucynację w pliku zależności |
|
|
| Migracja objęta regułami codemod | kod (`workflow/codemod.py`) | reguły z pakietu APM, w pełni powtarzalne |
|
|
| Nietypowe użycia API, kontekst biznesowy | model (`coder`) | tu klasyczna automatyzacja się kończy |
|
|
| Ocena zakresu i ryzyka zmiany | model (`reviewer`) + kontrola mechaniczna | dwa niezależne spojrzenia |
|
|
| Uruchomienie testów | kod (`tools/verification.py`) | agent nie dostaje powłoki |
|
|
| Branch, commit, push, MR | kod (`workflow/runner.py`) | jednoznaczny autor i format historii |
|
|
|
|
Konsekwencja: pipeline ma **dwa tryby o identycznej topologii**. Tryb `--offline` używa
|
|
wyłącznie reguł (`RuleBrain`), tryb domyślny dokłada agentów (`LlmBrain`). Tryb offline jest
|
|
bramką jakości na każdym MR - sprawdza cały przepływ bez kosztu GPU i bez dostępu do modelu.
|
|
|
|
## 5. Model bezpieczeństwa
|
|
|
|
Guardraile istnieją w dwóch warstwach, bo prompt nie jest zabezpieczeniem.
|
|
|
|
**Warstwa promptowa** (`.apm/instructions/security.instructions.md`) - dla modelu:
|
|
zakaz zmian w plikach pipeline'u, zakaz sekretów, zakaz rozszerzania zakresu,
|
|
zakaz usuwania testów, zakaz nowych zależności.
|
|
|
|
**Warstwa egzekucji** (`tools/workspace.py`, `config.py`) - dla audytora:
|
|
|
|
- każda ścieżka rozwiązywana względem korzenia repozytorium; wyjście przez `..` i dowiązania niemożliwe,
|
|
- lista `DEFAULT_DENY_GLOBS` blokuje zapis do `.gitlab-ci.yml`, `.git/`, `Dockerfile*`, `*.pem`, `.env*`, manifestów APM,
|
|
- budżety: liczba zmienionych plików, rozmiar pliku, liczba wywołań narzędzi, limit czasu weryfikacji,
|
|
- agent nie ma powłoki - jedyna operacja wykonawcza to `run_verification` z komendą ustaloną przez adapter,
|
|
- środowisko weryfikacji jest czyszczone ze zmiennych zawierających `TOKEN`, `SECRET`, `PASSWORD`, `API_KEY`,
|
|
- każde wywołanie narzędzia trafia do `trace.jsonl` z redakcją sekretów.
|
|
|
|
**Warstwa dostawy kontekstu** (`apm-policy.yml`): dozwolone źródła pakietów, zakaz prymitywu
|
|
`hooks` (wykonuje kod na runnerze), wymagane piny po tagu, wymagany lockfile, `apm audit`
|
|
wykrywający ręczną edycję zainstalowanego kontekstu.
|
|
|
|
## 6. Artefakty przebiegu
|
|
|
|
Każde uruchomienie zostawia w `--run-dir` komplet dowodów:
|
|
|
|
| Plik | Zawartość |
|
|
|---|---|
|
|
| `run.json` | manifest: zadanie, profil, plan, weryfikacje, werdykt, modele, hash lockfile'a APM |
|
|
| `plan.json` | plan zmian z kryteriami akceptacji i pozycjami `requires_human` |
|
|
| `profile.json` | ustalone fakty o repozytorium |
|
|
| `review.json` | werdykt recenzenta z findingami |
|
|
| `merge_request.md` | tytuł i opis MR |
|
|
| `changes.patch` | pełny diff |
|
|
| `trace.jsonl` | każde wywołanie narzędzia z czasem i wynikiem |
|
|
|
|
To jest odpowiedź na pytanie audytora "na jakiej podstawie ta zmiana weszła do repozytorium".
|
|
|
|
## 7. Backend LLM
|
|
|
|
Silnik zna wyłącznie jeden kontrakt: **endpoint zgodny z API OpenAI pod `CODEMOD_LLM_BASE_URL`**.
|
|
Cała wiedza o dostawcy jest w `llm.py` (fabryka modeli) i `llm/models.yml` (adresy, modele per rola).
|
|
|
|
Docelowo jest to vLLM na OpenShifcie. Lokalnie nie ma jednej ścieżki dla obu systemów -
|
|
Docker na macOS nie ma dostępu do Metala - więc `task llm:up` wykrywa platformę:
|
|
|
|
| Backend | Kiedy | Mechanizm |
|
|
|---|---|---|
|
|
| `vllm-gpu` | Linux + NVIDIA + Docker | `vllm/vllm-openai` przez docker compose |
|
|
| `vllm-metal` | macOS Apple Silicon | plugin `vllm-project/vllm-metal` (MLX), natywny `vllm serve` |
|
|
| `ollama` | awaryjnie, obie platformy | `/v1` zgodne z OpenAI, natywnie lub w kontenerze |
|
|
| `mock` | testy i CI | `llm/mock_server.py` - stdlib, zero pobierania |
|
|
|
|
Każdy backend serwujący realny model wymusza `--enable-auto-tool-choice` z parserem `hermes`.
|
|
Bez tego vLLM zwraca opis wywołania w treści odpowiedzi zamiast `tool_calls`, agent `coder`
|
|
nie tknąłby żadnego pliku, a przebieg kończyłby się "sukcesem" bez jednej zmiany - awaria cicha,
|
|
czyli najgorszy rodzaj.
|
|
|
|
### Atrapa jako test double
|
|
|
|
`mock` nie jest symulatorem modelu. Odpowiada z góry ustalonymi wywołaniami narzędzi
|
|
i strukturami zestrojonymi z fixture'em `acme-app`, a rozpoznaje pytającego po nazwie agenta,
|
|
którą agno wstrzykuje do komunikatu systemowego. Dzięki temu `tests/test_llm_path.py`
|
|
przepuszcza pełny przebieg przez `LlmBrain` - budowę agentów z definicji APM, tool-calling,
|
|
parsowanie strukturalnych wyjść i pętlę weryfikacji - na każdym MR, bez GPU i bez sieci.
|
|
|
|
Podział odpowiedzialności testów jest więc taki:
|
|
|
|
| Co jest sprawdzane | Czym |
|
|
|---|---|
|
|
| reguły, adaptery, sandbox, workflow | tryb `--offline` (`RuleBrain`) |
|
|
| agenci, narzędzia, schematy, pętla | tryb `llm` na atrapie (`LlmBrain` + `mock`) |
|
|
| jakość migracji na nietypowym kodzie | realny model, ręcznie |
|
|
|
|
## 8. Granice rozwiązania
|
|
|
|
- **Bez agenta-nadzorcy.** Topologia jest jawnym przepływem (agno `Workflow`), a nie
|
|
swobodną delegacją między agentami. W zamian za mniejszą elastyczność dostajemy
|
|
przewidywalny koszt, powtarzalny ślad i możliwość wstawienia bramki między krokami.
|
|
- **Bez AgentOS.** Runtime to efemeryczny job CI. Nie utrzymujemy usługi z pamięcią sesji -
|
|
stan przebiegu żyje w artefaktach.
|
|
- **Bez dostępu do sieci z poziomu agenta.** Cała wiedza migracyjna przychodzi w pakiecie APM.
|
|
Jeśli notatki migracyjnej nie ma, pipeline zatrzymuje się i zgłasza `requires_human`,
|
|
zamiast migrować "z pamięci modelu".
|
|
- **Nie każde repozytorium się nadaje.** Bez działającej komendy testowej weryfikacja nic nie znaczy,
|
|
a bez weryfikacji ten pipeline nie ma prawa niczego publikować.
|