Strona główna / Artykuły

Siedemnaście małych narzędzi MCP zamiast jednego ogromnego agenta: system pisania oparty na sztucznej inteligencji

Jak system badawczy i pisarski dzieli proces przetwarzania wideo, wyszukiwania, tworzenia projektów, krytyki oraz weryfikacji kodu na określone narzędzia MCP, wraz z artefaktami i śledzeniem działań.

Wydawca: REACTAPP.TOP13 min czytania2957 słów

Źródła: Why I Built MaxyAI as 17 Small MCP Tools Instead of One Giant Agent

Trudnym elementem agenta do pisania opartego na sztucznej inteligencji nie jest sprawienie, by model językowy pisał. Chodzi o decydowanie o tym, za co model nie powinien być odpowiedzialny. Wczesne próby stworzenia takich agentów zazwyczaj sprowadzały się do jednej architektury: przekazanie pojedynczemu modelowi tematu, dołączenie narzędzia do wyszukiwania i poproszenie go o przeprowadzenie badań, rozumowanie, napisanie tekstu, weryfikację oraz naprawę błędów w jednym długim procesie. Pytania stawały się coraz bardziej złożone, ślady działania trudne do debugowania, a błędy deterministyczne plątały się z decyzjami semantycznymi. MaxyAI, system badawczy i pisarski oparty na sztucznej inteligencji, wyruszył z innej idei: każda funkcja, która ma odrębne dane wejściowe, sposoby awarii, zasady ponownych prób lub wyjście wielokrotnie używalne, ma stać się odrębnym narzędziem zlokalizowanym za pojedynczym serwerem MCP.

Dane wejściowe rzadko są uporządkowane. Mogą to być wykład z YouTube, repozytorium na GitHubie, strona dokumentacyjna oraz kilka linków referencyjnych. MaxyAI przetwarza to wszystko, rozszerza badania poprzez wyszukiwanie w sieci, przechowuje rosnący zbiór danych na dysku i kształtuje go w postać streszczenia. Następnie tworzy projekt rozdział po rozdziale, przekazuje go algorytmowi oceniającemu, wyodrębnia każdy blok kodu w Pythonie, weryfikuje i uruchamia kod, naprawia błędy składniowe i eksportuje jeden samodzielny artykuł w formacie HTML.

W tle nie ma żadnego skomplikowanego promptu. System to serwer FastMCP z 17 zarejestrowanymi narzędziami, z których 12 służy do badań. Narzędzia są celowo proste. Jedno transkrybuje wideo, drugie rozumie repozytoria, trzecie wyszukuje informacje w sieci, czwarte tworzy streszczenie, piąte ocenia artykuł, a szóste weryfikuje kod. Model decyduje, które narzędzie użyć, a Python znajdujący się w każdym z nich wykonywać określone zadania.

To rozdzielenie jest najważniejszą zaletą tego projektu. Model może ulegać zmianom bez wpływu na proces pobierania treści z YouTube. Przeglądarkę może się wymienić bez zakłócania pracy narzędzia do tworzenia treści. Etap weryfikacji kodu można debugować bez konieczności ponownego przeprowadzania badań. A ponieważ każdy ważny krok pozostawia jakiś artefakt lub ślad, długotrwałe autonomiczne działanie można później przeanalizować, zamiast traktować je jako jeden ogromny zapis rozmowy.

Liczba 17 nigdy nie była celem. Wynikała z prostej zasady: funkcja otrzymuje własne narzędzie lub mechanizm obsługi, gdy komunikuje się z innym zewnętrznym systemem, tworzy artefakt nadający się do ponownego użycia, wymaga odrębnego zachowania przy próbach ponownych działań lub korzysta z weryfikacji deterministycznej. MCP zapewnia następnie wszystkim tym specjalistycznym komponentom wspólną interfejs.

Dlaczego nie jeden duży narzędzie? Ponieważ system rozwiązuje kilka odrębnych problemów inżynieryjnych, a nie jeden problem rozumowania. Każda z tych czynności (przyjmowanie wideo, analiza repozytoriów, odkrywanie treści w sieci, zarządzanie stanem, tworzenie projektów, krytyka, uruchamianie kodu, naprawa, publikacja) ma swoje własne dane wejściowe, koszty, możliwe błędy oraz potrzeby ponownych prób. Jeden meganarzędzie skróciłoby instrukcje, ale utrudniłoby obserwację i rozbudowę systemu.

To wszystko nie oznacza, że każdy agent potrzebuje 17 narzędzi. To studium przypadku dotyczące dekompozycji: gdzie decyzje semantyczne powinny być podejmowane przez model, gdzie zwykły kod powinien pełnić główną rolę, jak artefakty mogą zastępować zbyt rozbudowany stan konwersacji oraz dlaczego kod wygenerowany powinien przejść określone testy deterministyczne, zanim zostanie zobaczony przez użytkownika.

Proces od początku do końca

Weźmy temat wywoływania funkcji LLM oraz strukturyzowanych wyjść, wraz z początkowym zestawem wytycznych, takimi jak jeden film na YouTube, jeden repozytorium na GitHubie oraz kilka adresów URL dokumentacji.

Faza 1 nie generuje tekstu prozatorskiego. Jej zadaniem jest zbieranie dowodów. Serwer MCP wybiera adresy URL, przekazuje wideo do multimodalnej API Gemini, przekształca repozytoria w przyjazne modelowi streszczenia za pomocą gitingest, przeszukuje strony za pomocą Firecrawl, uzupełnia braki poprzez wyszukiwanie w Tavily oraz śledzi listę źródeł w plikach stanu znajdujących się w katalogu .nova/. Rezultatem jest plik research.md – duży dokument badawczy, który każdy może otworzyć i przeczytać, zamiast ukrytej pamięci konwersacyjnej.

Faza 2 bierze ten artefakt i planuje publikację. Funkcja generate_article_outline przydziela sekcje, cele liczby słów oraz cele dotyczące kodu, a draft_article_section pisze po jednej określonej sekcji za każdym razem, gdy jest wywoływana. Następnie critic_evaluate_article ocenia kompletny szkic pod kątem głębi merytorycznej, jakości kodu, struktury oraz dokładności cytowań, a refine_and_save_article wprowadza wymagane poprawki przed napisaniem pliku article.md.

Faza 3 traktuje Markdown jako coś, co musi przetrwać wykonywanie, a nie tylko wyglądać przekonująco. Bloki w Pythonie są wyodrębniane i analizowane za pomocą ast.parse(). Poprawne fragmenty są zapisywane w katalogu .nova/sandbox/ i uruchamiane z limitem czasowym pięciu sekund. Błąd składniowy wysyła błąd oraz fragment do funkcji fix_code_snippets, a wynik jest ponownie poddawany weryfikacji. Gdy kod przejdzie testy, export_publication_bundle tworzy samodzielny dokument HTML.

Śledzenie operacji obejmuje całe wykonywanie. Każde śledzenie modelu i narzędzia ujawnia opóźnienia, metadane dostawcy, hierarchię narzędzi oraz wyniki pośrednie. Przedstawiona jako diagram, architektura składa się z trzech faz (badania, autor i krytyk, testy kodu i wydawca), które dzielą się mechanizmami przechodzenia na zapasowe rozwiązania oraz możliwościami obserwacji.

Server MCP jako filar

Pierwsza decyzja projektowa dotyczyła poziomu protokołu: umożliwienie dostępu do funkcjonalności za pośrednictwem Model Context Protocol oraz unikanie bezpośredniego włączania każdej funkcji do pojedynczego pętla aplikacji.

MCP dostarcza klientowi standardowego słownictwa do znajdowania i wywoływania narzędzi. FastMCP ułatwia to w Pythonie, ponieważ zwykła funkcja typowana staje się narzędziem MCP dzięki dekoratorowi, a jej sygnatura staje się częścią umowy narzędzia. Implementacja może pozostać zwykłym kodem w Pythonie, nawet gdy klientem jest agent.

W projekcie mcp_server/src/routers/tools.py jest punktem wejścia do warstwy narzędzi. Uproszczona procedura rejestracji wygląda następująco:

import opik
from fastmcp import FastMCP

from ..tools import run_web_research_tool

def register_mcp_tools(mcp: FastMCP) -> None:
    @mcp.tool(name="run_web_research")
    @opik.track(type="tool", tags=["research", "tavily"])
    async def run_web_research(
        queries: list[str],
        research_directory: str,
    ) -> dict:
        return await run_web_research_tool(
            queries=queries,
            research_directory=research_directory,
        )

Dekorator służy nie tylko do upiększenia składni. Klient widzi nazwane narzędzie z typowanymi argumentami, podczas gdy implementacja pozostaje w warstwie narzędzi i obsługujących je mechanizmów. Ta separacja ma znaczenie, gdy serwer rozrasta się poza kilka podstawowych funkcji.

Celowo unikano pojedynczego narzędzia do_everything(topic), ponieważ mogłoby ono ponownie wprowadzić powiązania, których uniknięcie było celem projektu. Mniejsze narzędzia umożliwiają modelowi kompozycję zachowań: wyodrębnianie źródeł, sprawdzanie brakujących elementów, ponowne wyszukiwanie, tworzenie szkiców, opracowywanie projektów, krytyka oraz naprawa. Ułatwiają one również czytanie śladów działania, ponieważ każdy etap odpowiada jednej istotnej akcji.

Zatem serwer składający się z 17 narzędzi to nie 17 osobnych poleceń – to zbiór ograniczonych funkcji. Największy udział, 12 narzędzi, przypada na badania, ponieważ to właśnie przy pozyskiwaniu źródeł proces wymaga największej różnorodności.

Badania: różne źródła, różne narzędzia

Badania pochłonęły najwięcej wysiłków projektowych, ponieważ funkcja „szukanie w sieci” ukrywa kilka operacji. Wideo, repozytorium na GitHubie oraz strona dokumentacyjna oparta na JavaScriptie stwarzają trzy różne problemy z danymi, a przetwarzanie ich za pomocą jednego skrapera od samego początku dostarcza autorowi słabego kontekstu.

Gemini dla YouTube

Rozwiązywanie problemów z długimi filmami lokalnie jest kosztowne: trzeba pobrać audio, przetworzyć je na tekst mowy, zarządzać pamięcią GPU, a następnie stworzyć streszczenie transkrypcji. Moduł youtube_handler.py obiera prostsze podejście – przekazuje publiczny adres YouTube bezpośrednio do Gemini jako wejście multimodalne i prosi o strukturyzowany Markdown z oznaczeniami czasowymi.

Powodem wyboru Gemini nie jest to, że jest to najlepszy model dla całego projektu. Chodzi o to, że ta funkcjonalność pasuje do zadań: możliwość natywnego przetwarzania danych multimodalnych oznacza, że serwer może obsługiwać wideo bez konieczności używania lokalnego stacku Whisper ani karty graficznej na komputerze klienta.

Błędy serwera dostawcy są radzone przez ten sam moduł przy użyciu eksponencjalnych prób ponownych, co pozwala utrzymać tymczasowe awarie po stronie modelu wewnątrz narzędzia, dzięki czemu zewnętrzny agent nie musi znać szczegółów sieciowych.

@retry(
    retry=retry_if_exception_type(errors.ServerError),
    wait=wait_exponential(multiplier=1, min=5, max=60),
    stop=stop_after_attempt(3),
)
async def transcribe_youtube(url: str, output_path: Path, timestamp: int = 30):
    client = track_genai_client(
        genai.Client(api_key=settings.google_api_key.get_secret_value())
    )

    parts = [
        types.Part(file_data=types.FileData(file_uri=url)),
        types.Part(text=PROMPT_YOUTUBE_TRANSCRIPTION.format(timestamp=timestamp)),
    ]

    response = await client.aio.models.generate_content(
        model=settings.youtube_transcription_model,
        contents=parts,
    )

    output_path.write_text(response.text, encoding="utf-8")

W jednym przeprowadzonym teście 39-minutowa prelekcja została przekształcona w uporządkowane notatki w ciągu 17,8 sekundy bez wykorzystania pamięci GPU po stronie klienta. Był to tylko jeden przypadek badany, a nie uniwersalny standard oceny, ponieważ obciążenie serwera i warunki sieciowe mogą go zmieniać. Zapisany zapis pokazał identyfikator modelu gemini-3.7-flash oraz utrwalony plik .nova/guidelines_filenames.json zawierający informacje o stanie.

gitingest dla repozytoriów

Repozytorium to nie strona internetowa. Model potrzebuje struktury plików oraz rzeczywistego kodu źródłowego, a nie elementów nawigacyjnych GitHuba, dlatego mechanizm obsługi GitHuba wykorzystuje gitingest do stworzenia zwięzłego podsumowania repozytorium przyjaznego dla modeli językowych.

Walidacja AST to odrębna kwestia. Narzędzia typu gitingest jedynie pobierają dane, dostarczając modelowi badawczemu mapę katalogów oraz zawartość plików, podczas gdy parser AST w Pythonie zostaje użyty znacznie później, podczas sprawdzania generowanego kodu w procesie publikacji. Połączenie tych dwóch rozwiązań skomplikowałoby architekturę.

Trzymanie ich oddzielnie ułatwia również rozbudowę. Narzędzie typu GitLab lub lokalny importer folderów będzie musiało po prostu wygenerować ten sam artefakt badawczy, ponieważ narzędzie tworzące kod nie zależy od tego, skąd pochodzi kod źródłowy.

Tavily i Firecrawl razem

Oba narzędzia rozwiązują różne aspekty badań w sieci. Tavily pomaga w odkrywaniu, przekształcając pytanie „Co mi jeszcze brakuje?” w zestaw precyzyjnych zapytań. Firecrawl przydaje się, gdy serwer wybrał konkretną stronę i chce jej zawartość w sposób uporządkowany wydobyć.

Projekt wykorzystuje tę różnicę, aby sprawić, że badania przebiegają w sposób iteracyjny. Przyjęcie początkowych odniesień nie jest końcem procesu. Agent przegląda korpus, tworzy nowe zapytania dotyczące tego, co wciąż brakuje, je uruchamia, dodaje uzyskane wyniki i może powtarzać ten proces nawet trzy razy.

Konstrukcja jest celowo asymetryczna: LLM decyduje, co jest nieobecne, natomiast Tavily i Firecrawl zajmują się wyszukiwaniem informacji. Ten sam schemat powtarza się przez cały proces – model jest używany tam, gdzie przydatne jest semantyczne osądzenie, natomiast zwykły kod i usługi tam, gdzie lepsza jest deterministyczna praca. Aktywność Firecrawl podczas badania pokazuje, że przed rozpoczęciem pracy nad projektem przegląda on heterogeniczne źródła techniczne.

Pliki w katalogu .nova/ zamiast jednej ogromnej rozmowy

Badania mogą łatwo generować dziesiątki tysięcy tokenów, a przechowywanie każdej zebranej strony oraz pośrednich decyzji przy każdym kolejnym wywołaniu narzędzia byłoby marnotrawstwem zasobów.

Zamiast tego system tworzy małe pliki kontrolne w katalogu .nova/, takie jak guidelines_filenames.json i next_queries.json, a duże treści przechowuje w plikach typu research.md. Model otrzymuje tylko tę część, która jest potrzebna do bieżącej operacji.

To mniej „magiczne” niż „pamięć agenta”, ale znacznie łatwiejsze do sprawdzenia. Gdy proces zostaje przerwany w połowie, katalog stanu pokazuje, jakie odniesienia zostały zebrane lub która kolejna runda wyszukiwania była planowana. W praktyce system plików pełni rolę prostego, ale skutecznego mechanizmu koordynacji pomiędzy poszczególnymi fazami.

Autor to pipeline

Gdy już istnieje plik research.md, naturalną pokusą jest przesłanie całego pliku do dużego modelu i poproszenie o artykuł liczący 2000 słów. Projekt unikał tego od samego początku, ponieważ ograniczenia wyjściowe oraz konieczność obsługi długiego kontekstu utrudniają jednoczesną kontrolę nad strukturą, zakresem kodu i cytacjami.

Faza pisania dzieli natomiast zadanie na cztery narzędzia:

  • generate_article_outline przekształca zbiór danych badawczych w listę sekcji z określonymi limitami słów i celami dotyczącymi kodu.
  • draft_article_section tworzy sekcje o ograniczonym rozmiarze zamiast jednego ogromnego tekstu końcowego.
  • critic_evaluate_article ocenia przygotowany szkic według ustrukturyzowanej skali od 0 do 100.
  • refine_and_save_article przeprowadza niezbędne poprawki, tworzy spis treści, sprawdza strukturę cytatów i zapisuje plik article.md.
  • Ważne jest, aby krytyk nie powiedział po prostu „wygląda dobrze”. Jego wynik to ustrukturyzowana informacja zwrotna, na której może oprzeć się inne narzędzie:

    {
     "overall_score": 85,
     "status": "APPROVED",
     "category_scores": {
     "technical_depth": 27,
     "code_quality": 26,
     "structure_clarity": 17,
     "citation_fidelity": 15
     },
     "specific_critiques": [
     "Section 3.2 mentions timeout handling but omits the asyncio.wait_for example.",
     "Citation [14] is cited twice with conflicting author names."
     ],
     "required_revisions": [
     "Add the timeout example.",
     "Deduplicate bibliography reference [14]."
     ]
    }
    

    To wzorzec z każdym razem ogranicza rolę modelu. Model ogólny decyduje o strukturze, osoba tworząca tekst syntetyzuje jedną sekcję, krytyk szuka wad, a etap udoskonalania wykorzystuje listę kontrolną. Żaden pojedynczy model nie jest proszony o wykonywanie wszystkich czterech zadań w ramach jednego procesu.

    Wynik 85 na 100 nie jest naukową miarą jakości. Jest to sygnał kontroli przepływu pracy, a najcenniejszą częścią jest krytyka oraz lista poprawek czytelna dla maszyny.

    Ślad prawdziwego łańcucha pisarzy pokazuje ustrukturyzowany prompt, wywołanie modelu czatowego oraz parsera Pydantic – to właśnie takie zapisy umożliwiają zrozumienie autonomicznego procesu pisania w późniejszym czasie.

    Kod jako wykonywalny artefakt

    Artykuł techniczny może być dobrze napisany, ale nadal nie spełnić oczekiwań czytelników, jeśli jego kod się nie uruchomi. Dlatego właśnie istnieje trzecia faza.

    Budowniczy otwiera plik article.md, wyodrębnia z niego kod Pythona umieszczony w ramkach, weryfikuje każdy blok za pomocą ast.parse(), zapisuje sprawdzone fragmenty do katalogu .nova/sandbox/, uruchamia je jako proces potomny, jednocześnie przechwytując dane z stdout i stderr, i pozwala na ponowną obróbkę błędów za pomocą narzędzia do naprawy opartego na LLM.

    Statyczna analiza i wykonywanie kodu wykrywają różne problemy. ast.parse() jest szybki i natychmiast odrzuca nieważny kod Pythona. Proces potomny natomiast łapie błędy w trakcie wykonywania, których sama składnia nie może wykryć.

    def validate_python_syntax(code: str):
     try:
     ast.parse(code)
     return True, None
     except SyntaxError as exc:
     return False, f"SyntaxError at line {exc.lineno}: {exc.msg}"
    result = subprocess.run(
     [sys.executable, str(file_path)],
     capture_output=True,
     text=True,
     timeout=5,
     env={"PYTHONUNBUFFERED": "1"},
    )
    

    Nieudany fragment jest naprawiany i wysyłany ponownie na weryfikację przed skompilowaniem artykułu. W jednym przypadku wygenerowany artykuł zawierał pip install google-genai wewnątrz bloku Pythona. Wyglądało to prawdopodobnie w formacie Markdown, ale Python natychmiast to odrzucił. fix_code_snippets otrzymał informację o błędzie oraz uszkodzony blok, przepisał fragment i odesłał go na ponowną weryfikację.

    # Broken
    pip install google-genai
    from google import genai
    
    # Repaired
    # Requires: pip install google-genai
    import os
    from google import genai
    
    client = genai.Client(
        api_key=os.environ.get("GEMINI_API_KEY", "mock-key")
    )
    

    Pętla naprawcza jest celowo utrzymywana lokalnie. Model nie może przepisać całego artykułu tylko dlatego, że jeden fragment zawiodł. Otrzymuje najmniejszą użyteczną jednostkę – kod wraz z błędem – a deterministyczne sprawdzenia pozostają bramą kontrolną.

    Mówiąc prościej: plik article.md jest skanowany pod kątem kodu Pythona umieszczonego w ramkach, każdy fragment jest analizowany, przechowywany w katalogu .nova/sandbox/ i wykonywany w ograniczonym procesie potomnym. W przypadku niepowodzenia kod wraz z informacjami o błędzie jest pakowany i przekazywany do funkcji fix_code_snippets, a zaproponowana naprawa ponownie przechodzi tę samą ścieżkę walidacji. Model nigdy nie zatwierdza własnej naprawy – to LLM proponuje rozwiązanie, a ast.parse() w połączeniu z wykonywaniem decyduje o jego przyjęciu. Dopiero gdy pętla się zamyka, funkcja export_publication_bundle przekształca przejrzany artefakt w samodzielny plik HTML.

    Jeden aspekt zasługuje na szczególną uwagę. Warstwa wykonywania to narzędzie do uruchamiania podprocesów z ochroną, a nie wzmocniona przestrzeń bezpieczeństwa. Czas wygaśnięcia oraz podprocesy skutecznie pomagają w weryfikacji jakości treści, wykrywając błędy składniowe, awarie w trakcie działania oraz zatrzymania aplikacji. Kod całkowicie niezaufany wymagałby silniejszej izolacji, takiej jak kontenery, nazwy przestrzeni, mechanizmy seccomp, mikroVM-y lub dedykowana usługa przestrzeni bezpieczeństwa z ograniczeniami dotyczącymi systemu plików, sieci, wywołań systemowych, procesora i pamięci.

    Dwie wspólne warstwy: routowanie modeli i śledzenie

    Widzialną architekturę tworzą trzy fazy, jednak dwa wspólne elementy odgrywają równie ważną rolę w codziennym użyciu.

    Routowanie modeli z uwzględnieniem limitów

    Jedno badanie może generować wiele wywołań modeli, co łatwo prowadzi do wyczerpania limitów dostępnych w wersji bezpłatnej. Aby uniknąć konieczności inicjalizacji specyficznej dla dostawcy w każdym obsługiwaczu, tworzenie modeli jest centralizowane w pliku llm_utils.py, przy czym konfiguracja dostawcy i klucza API znajduje się w ustawieniach.

    Projekt rozwijał się wokół serii modeli Gemini Flash, Gemini Flash Lite oraz Llama hostowanego przez Groq. Te konkretne modele nie są trwałe, ale to nie ma znaczenia. Każde narzędzie komunikuje się z abstrakcją modelu, bez żadnych szczegółów dotyczących dostawcy wbudowanych w kod badawczy i programistyczny.

    Eksperymenty stają się również tańsze, ponieważ przeniesienie zadania na tańszy lub obecnie dostępny model nie wpływa na umowę narzędzia MCP.

    def get_chat_model(model_id: str, schema=None):
        selected = settings.llm_configs[model_id]
        identifier = selected["identifier"]
        params = selected.get("params", {}).copy()
    
        # resolve provider-specific API key
        ...
    
        model = init_chat_model(identifier, **params)
        return track_langchain_model(model)
    

    Opik umożliwia sprawdzanie długich sekwencji operacji

    Łogi tracą swoją użyteczność, gdy serwer MCP wywołuje model, który z kolei uruchamia narzędzie, które tworzy artefakt, który aktywuje inny model. Wykorzystanie narzędzi Opik do śledzenia działania klientów modeli i narzędzi MCP pokazuje tę hierarchię bezpośrednio, bez konieczności składania informacji z zapisów wydruku.

    Korzyści są praktyczne: wolny krok Firecrawl można porównać z wywołaniem modelu, można zidentyfikować model, który faktycznie udzielił odpowiedzi, zobaczyć dane otrzymane przez parser, a także odtworzyć ścieżkę, która doprowadziła do powstania błędnego artefaktu. Zdjęcia ekranu z zapisami śledzenia stanowią interfejs rozwojowy do zrozumienia procesu pracy, a nie tylko element dekoracyjny.

    Czego projekt uczy nas na temat projektowania agentów

    Zdolność do tworzenia artykułów nie jest tym, co czyni MaxyAI interesującym, ponieważ już jeden model typu frontier potrafi przekształcić prompt w przyzwoity tekst. Wyjątkowym elementem jest sposób, w jaki podzielono pracę nad artykułem – przetwarzanie wideo, analiza repozytorium, wyszukiwanie, tworzenie szkicu, pisanie pierwszej wersji, krytyka, wydobywanie kodu, weryfikacja, naprawa i eksport to osobne narzędzia. MCP zapewnia im wspólną strukturę, pliki na dysku umożliwiają przekazywanie dużych ilości danych pomiędzy fazami bez konieczności przechowywania ich w pamięci czatu, a Opik sprawia, że cała ścieżka pracy jest widoczna.

    Punkty rozszerzeń są łatwe do zauważenia – narzędzie do importowania plików PDF dostarcza Fazie 1 innego rodzaju źródła danych. Zastąpienie Tavily nie wpływa na narzędzie do pisania. Do Fazy 3 można dodać weryfikację za pomocą JavaScriptu, podczas gdy silnik wyszukiwawczy pozostaje nietknięty. Zmiana dostawców modeli nie zmienia struktury MCP.

    Wzmocnienie systemu przeznaczonego do produkcji zaczęłoby się od silniejszej izolacji w środowisku sandbox, następnie od ustalonej serii testów obejmujących badania, cytaty i jakość kodu, bardziej przejrzystych metadanych dotyczących możliwości dostawcy oraz trwałych punktów kontrolnych podczas działania. Już dziś projekt podkreśla, że model może wybrać kolejną akcję, natomiast jakość systemu zależy od narzędzi, ograniczeń, artefaktów oraz pętli zwrotnej, które go otaczają.

    Trzy lekcje inżynieryjne mają zastosowanie również w innych systemach agentowych:

    1. Ograniczenia narzędzi są ważniejsze niż ich liczba. Nadaj każdej funkcji własne ograniczenia, jeśli dotyka ona innego systemu, zawodzi lub próbuje ponownie w inny sposób, albo wytwarza artefakt, który ktoś będzie ponownie wykorzystywał.
    2. Modele proponują rozwiązania, a deterministyczne sprawdzenia podejmują decyzje, o ile to możliwe. Model językowy może poprawić fragment tekstu, ale ostateczna decyzja zapada po analizie i wykonaniu.
  • Wskazanie, że można przeglądać dane, jest lepsze od niejasnego określenia „pamięć”. Zapisane wyniki badań, pliki kontrolne oraz ślady działania umożliwiają debugowanie długich procesów oraz ponowne uruchomienie poszczególnych etapów bez konieczności odbudowywania ogromnej historii rozmów.