Blog
AI20 min czytania

CopilotKit — generative UI i agenci wewnątrz aplikacji webowej

CopilotKit daje agentowi LLM dostęp do stanu Twojego interfejsu i pozwala mu renderować własne komponenty Reacta w czacie. Runtime jest jednak w Node, a protokół AG-UI nie ma SDK dla PHP — pokazujemy trzy warianty wpięcia tego w aplikację laravelową, z których jeden jest na produkcji płatny, oraz co dokładnie zostaje po stronie open source.

CopilotKit zaczyna się tam, gdzie kończy się okienko czatu przyklejone do prawego dolnego rogu strony. Zamiast modelu, który odpowiada tekstem na tekst, dostajesz agenta, który widzi stan Twojej aplikacji, wywołuje funkcje w przeglądarce użytkownika, renderuje w rozmowie Twoje komponenty Reacta i potrafi zatrzymać się w połowie zadania, żeby zapytać człowieka o zgodę.

Liczby na dzień pisania tego tekstu: CopilotKit/CopilotKit ma 36 871 gwiazdek i 199 współtwórców, licencję MIT, jest napisany w TypeScripcie i powstał w czerwcu 2023. Wydanie v1.68.2 wyszło 20 sierpnia 2026 o 2:38 UTC — a ostatni commit trafił do repozytorium tego samego dnia, kilka godzin później. W 2026 roku, do 20 sierpnia, projekt wydał 94 wersje. Paczka @copilotkit/react-core miała 328 989 pobrań w tygodniu 12–18 sierpnia 2026.

To tempo jest jednocześnie największą zaletą i największym kosztem tego projektu, i wrócimy do tego przy pułapkach. Najpierw jednak rzecz, którą trzeba powiedzieć wprost, bo decyduje o tym, czy ten wpis jest dla Ciebie: runtime CopilotKitu działa w Node, a protokół, na którym całość stoi, nie ma dziś SDK dla PHP. Jeśli backend piszesz w Laravelu, integracja jest jak najbardziej możliwa — ale w jednym z trzech wariantów, które różnią się kosztem i modelem bezpieczeństwa. Opisujemy je niżej, razem z tym, który z nich jest na produkcji płatny.

Trzy warstwy i jeden protokół

Architektura ma trzy części i warto je rozdzielić od początku, bo nazwy w dokumentacji potrafią się zlewać:

  • Frontend SDK@copilotkit/react-core. Hooki i gotowe komponenty czatu (CopilotChat, CopilotSidebar, CopilotPopup, CopilotThreadsDrawer). Poza Reactem są też SDK dla Angulara, Vue i React Native.
  • Copilot Runtime@copilotkit/runtime. Handler HTTP montowany w Twoim serwerze aplikacyjnym. Tu siedzi klucz do modelu, autoryzacja, middleware i routing między agentami. Adaptery: Next.js, Express, Hono, Bun, Deno, Cloudflare Workers.
  • Backend agenta — warstwa, która realnie prowadzi rozmowę z modelem. Może to być wbudowany BuiltInAgent (pętla agentowa w procesie runtime'u, na modelach OpenAI, Anthropica, Google albo dowolnym z AI SDK), albo zewnętrzny framework: LangGraph, Mastra, CrewAI, Pydantic AI, Microsoft Agent Framework, AWS Strands, Google ADK.

Spaja je AG-UI — protokół zdarzeniowy, który CopilotKit sam stworzył i wydzielił do osobnego repozytorium (ag-ui-protocol/ag-ui, 15 412 gwiazdek, MIT). Definiuje 16 typów zdarzeń przesyłanych domyślnie przez Server-Sent Events: cyklu życia przebiegu, kroków, strumieniowania tekstu, wywołań narzędzi, migawek i różnic stanu, zdarzeń własnych.

Konsekwencja tego podziału jest praktyczna: frontend nie wie, jaki framework agentowy siedzi z drugiej strony. Runtime rozpoznaje agentów przez własną końcówkę GET /info i reprezentuje każdego z nich jako proxy implementujące ten sam interfejs AbstractAgent. Wymiana LangGrapha na Mastrę nie dotyka kodu komponentów.

Co ten stack faktycznie daje

Pięć mechanizmów, które odróżniają to od integracji z API modelu napisanej samodzielnie w jeden dzień.

1. Agent widzi stan aplikacji

Hook useAgentContext rejestruje dowolne dane jako kontekst przekazywany do modelu. Wywołań może być wiele, w różnych komponentach — wszystkie są scalane, a zmiana danych aktualizuje kontekst automatycznie.

import { useAgentContext } from '@copilotkit/react-core/v2';

useAgentContext({
    description: 'Aktualnie zalogowany użytkownik',
    value: user,
});

useAgentContext({
    description: 'Otwarte zlecenia serwisowe w tym widoku',
    value: zlecenia,
});

To zdejmuje z Ciebie najbardziej żmudną część takich integracji: sklejanie promptu systemowego z bieżącego stanu ekranu przy każdym żądaniu.

2. Narzędzia wykonywane w przeglądarce

useFrontendTool rejestruje funkcję, którą model może wywołać — a która wykonuje się w przeglądarce użytkownika, ze wszystkim, do czego przeglądarka ma dostęp: stanem komponentów, localStorage, ciasteczkami, bibliotekami frontendowymi.

import { z } from 'zod';
import { useFrontendTool } from '@copilotkit/react-core/v2';

useFrontendTool({
    name: 'przefiltrujListe',
    description: 'Ustawia filtry na liście zleceń.',
    parameters: z.object({
        status: z.enum(['nowe', 'w_toku', 'zamkniete']),
        odpowiedzialny: z.string().optional().describe('Login opiekuna'),
    }),
    handler: async ({ status, odpowiedzialny }) => {
        setFiltry({ status, odpowiedzialny });
        return `Ustawiono filtr: ${status}.`;
    },
});

Schemat parametrów opisujesz Zodem i to on jest jednocześnie kontraktem dla modelu i walidacją wejścia. Zwrócony string wraca do agenta jako wynik narzędzia, więc może kontynuować rozumowanie.

3. Generative UI, czyli własne komponenty w czacie

Tu leży sedno nazwy „generative UI”. Wywołanie narzędzia nie musi wyświetlić się jako blok JSON-a — możesz je wyrenderować własnym komponentem, ze stanem pośrednim w trakcie działania.

import { useRenderTool } from '@copilotkit/react-core/v2';

useRenderTool({
    name: 'pobierz_raport_sprzedazy',
    parameters: z.object({ miesiac: z.string() }),
    render: ({ status, parameters, result }) => {
        if (status !== 'complete') {
            return <SzkieletWykresu miesiac={parameters.miesiac} />;
        }

        return <WykresSprzedazy dane={result} />;
    },
});

Nazwa w useRenderTool musi zgadzać się z nazwą narzędzia po stronie agenta — to jedyne spoiwo między backendem a widokiem. Jest też useDefaultRenderTool: renderer zbiorczy dla wszystkiego, co nie ma własnego. W praktyce włączamy go od pierwszego dnia, bo bez niego wywołania narzędzi serwerowych i narzędzi z serwerów MCP są w czacie niewidoczne, co przy diagnostyce jest kosztowne.

4. Human-in-the-loop

Agent zatrzymuje przebieg, pokazuje komponent, czeka na odpowiedź człowieka i wraca do rozumowania z tą odpowiedzią jako wynikiem narzędzia. CopilotKit ma na to dwa wzorce i różnicę między nimi opłaca się zrozumieć przed wyborem:

  • useHumanInTheLoop — pauzę inicjuje model, wywołując zarejestrowane narzędzie klienckie. Backend nie musi o niczym wiedzieć: wystarczy schemat Zoda i funkcja render, która dostaje respond do oddania odpowiedzi.
  • useInterrupt — pauzę wymusza graf, wywołaniem interrupt(...) w węźle LangGrapha. Kontraktem jest kod serwerowy, nie decyzja modelu.

Różnica sprowadza się do pytania, komu ufasz w kwestii tego, kiedy zapytać człowieka. Przy zatwierdzaniu przelewu albo wysyłce maila do klienta nie chcemy, żeby o istnieniu bramki decydował model — tam właściwy jest useInterrupt albo autoryzacja po stronie serwera, a nie samo useHumanInTheLoop. Ten drugi jest dobry do pytań o preferencje: wybór terminu, wariantu, adresata z listy.

5. Stan dzielony w dwie strony

useAgent daje dostęp do reaktywnego stanu agenta. Model może go zmienić w trakcie pracy, a komponenty renderują się od nowa; frontend może w niego pisać przez agent.setState.

import { useAgent } from '@copilotkit/react-core/v2';

const { agent } = useAgent();
const zadania = agent.state.zadania ?? [];

agent.setState({ ...agent.state, preferencje: { motyw: 'dark' } });

Pod spodem BuiltInAgent dostaje dwa narzędzia protokolarne, AGUISendStateSnapshot i AGUISendStateDelta, a runtime dowozi ich efekty do przeglądarki przez SSE. Do zwykłego czatu to nadmiar. Do interfejsu, w którym agent wypełnia formularz albo buduje listę na oczach użytkownika — sensowniejsze niż przepychanie wszystkiego przez wywołania narzędzi.

Jest jeszcze agent.subscribe z pełnym strumieniem zdarzeń AG-UI (onToolCallEndEvent, onStateChanged, onRunErrorEvent i pozostałe). To najlepsze miejsce na własną telemetrię i audyt tego, co agent zrobił.

Start w pięć minut, jeśli masz Node

Wymagania: Node 20+ i klucz do modelu. Trasa runtime'u w Next.js:

// app/api/copilotkit/route.ts
import { CopilotRuntime, copilotRuntimeNextJSAppRouterEndpoint } from '@copilotkit/runtime';
import { BuiltInAgent } from '@copilotkit/runtime/v2';
import { NextRequest } from 'next/server';

const runtime = new CopilotRuntime({
    agents: { default: new BuiltInAgent({ model: 'openai:gpt-5.4-mini' }) },
});

export const POST = async (req: NextRequest) => {
    const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
        runtime,
        endpoint: '/api/copilotkit',
    });

    return handleRequest(req);
};

I strona klienta — provider plus komponent czatu:

import { CopilotKit, CopilotSidebar } from '@copilotkit/react-core/v2';
import '@copilotkit/react-core/v2/styles.css';

<CopilotKit runtimeUrl="/api/copilotkit">
    <YourApp />
    <CopilotSidebar />
</CopilotKit>

Agent zarejestrowany pod kluczem default jest używany przez gotowe komponenty bez podawania agentId — przy jednym agencie to oszczędza dużo powtarzalnej konfiguracji.

Klucz do modelu żyje w runtimie, po stronie serwera. To jedyny powód, dla którego ten runtime w ogóle istnieje, i wystarczający, żeby nie próbować go ominąć „na chwilę” w prototypie, który potem trafi na staging.

Warto zauważyć, co CLI npx copilotkit@latest create robi, a czego nie: zakłada nowy projekt w osobnym katalogu. Nie doda CopilotKitu do aplikacji, którą już masz. Do istniejącego projektu instalujesz paczki ręcznie.

A co z Laravelem

Tu zaczyna się część, której nie znajdziesz w dokumentacji, bo dokumentacja zakłada Next.js. SDK protokołu AG-UI istnieją dla ośmiu języków: JavaScript, Python, Go, Java, Kotlin, Rust, Ruby i Dart. PHP na tej liście nie ma. Runtime też jest paczką npm. Zostają trzy warianty.

Wariant A: narzędzia frontendowe uderzające w istniejące trasy Laravela

Najtańszy i naszym zdaniem najlepszy na start. Agent działa w runtimie w Node, ale nie dotyka Twojej bazy. Wszystko, co ma zrobić w domenie aplikacji, robi przez narzędzia frontendowe, które wykonują się w przeglądarce zalogowanego użytkownika i wołają trasy, które już masz.

useFrontendTool({
    name: 'zmienStatusZlecenia',
    description: 'Zmienia status zlecenia serwisowego.',
    parameters: z.object({
        zlecenie: z.number().describe('ID zlecenia'),
        status: z.enum(['nowe', 'w_toku', 'zamkniete']),
    }),
    handler: async ({ zlecenie, status }) => {
        const odpowiedz = await fetch(`/zlecenia/${zlecenie}/status`, {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
            },
            body: JSON.stringify({ status }),
        });

        if (!odpowiedz.ok) {
            return `Nie udało się zmienić statusu (HTTP ${odpowiedz.status}).`;
        }

        return 'Status zmieniony.';
    },
});

Dlaczego to jest dobry wzorzec: żądanie leci z ciasteczkiem sesji, więc decyzję podejmuje ZlecenieController i ZleceniePolicy — czyli kod, który już napisałeś i przetestowałeś. Agent nie może zrobić niczego, czego nie może zrobić zalogowany człowiek. Nie dublujesz autoryzacji w drugim języku, a odpowiedź 403 z Laravela jest dla modelu zwykłym wynikiem narzędzia, który potrafi zakomunikować użytkownikowi.

Ograniczenie jest jedno i realne: narzędzie działa tylko wtedy, gdy karta przeglądarki jest otwarta. Do zadań w tle to nie jest droga.

Wariant B: runtime jako sidecar w Compose

Runtime jest małym serwerem HTTP, więc traktujemy go jak każdą inną usługę pomocniczą obok aplikacji laravelowej:

# docker-compose.yml — fragment
services:
    copilot:
        build: ./docker/copilot
        environment:
            OPENAI_API_KEY: '${OPENAI_API_KEY}'
            # Telemetria open source — patrz sekcja o RODO niżej
            COPILOTKIT_TELEMETRY_DISABLED: 'true'
        expose:
            - '4000'
        networks:
            - sail
// docker/copilot/server.ts
import express from 'express';
import { BuiltInAgent, CopilotRuntime } from '@copilotkit/runtime/v2';
import { createCopilotExpressHandler } from '@copilotkit/runtime/v2/express';

const runtime = new CopilotRuntime({
    agents: { default: new BuiltInAgent({ model: 'openai:gpt-5.4-mini' }) },
});

const app = express();

app.use(createCopilotExpressHandler({ runtime, basePath: '/copilot' }));
app.listen(4000);

Dalej location /copilot w nginksie proxy'owane na copilot:4000, a we froncie runtimeUrl="/copilot". Z punktu widzenia przeglądarki wszystko jest na jednej domenie, więc nie ma CORS-a ani problemu z ciasteczkami SameSite.

Tożsamość użytkownika przenosisz nagłówkiem. Provider przyjmuje headers, a runtime v2 ma hook onRequest, który wykonuje się przed kodem agenta i operuje na surowym obiekcie Request:

createCopilotRuntimeHandler({
    runtime,
    basePath: '/copilot',
    hooks: {
        onRequest: ({ request }) => {
            const naglowek = request.headers.get('authorization');

            if (!naglowek?.startsWith('Bearer ')) {
                throw new Response(JSON.stringify({ error: 'unauthorized' }), { status: 401 });
            }

            // Weryfikacja tokenu podpisanego przez Laravela
        },
    },
});

Po stronie Laravela najprościej wystawić krótkożyciowy podpisany token w propsach współdzielonych Inertii i podać go providerowi. Uwaga na szczegół z dokumentacji: stary adapter Next.js nie przekazuje opcji hooks — do bramki onRequest potrzebny jest createCopilotRuntimeHandler z @copilotkit/runtime/v2. Sygnatury tych handlerów zmieniały się między wersjami mniejszymi, więc wersje paczek przypnij dokładnie i sprawdź je przy każdej aktualizacji.

Wariant C: własna końcówka AG-UI w PHP

Technicznie da się pominąć runtime w Node i podać providerowi instancję HttpAgent wskazującą na endpoint, który sam strumieniuje zdarzenia AG-UI — także napisany w PHP:

import { HttpAgent } from '@ag-ui/client';
import { CopilotKit } from '@copilotkit/react-core/v2';

const agent = new HttpAgent({ url: 'https://api.example.com/agui/support' });

<CopilotKit selfManagedAgents={{ 'support-agent': agent }}>
    <YourApp />
</CopilotKit>

I tu trzeba postawić czerwoną flagę, bo to nie wynika z kodu, tylko z licencji: selfManagedAgents jest częścią komercyjnej oferty Enterprise Intelligence. Dokumentacja mówi o tym wprost i odsyła do rozmowy o licencji na użycie produkcyjne. Darmowy odpowiednik nazywa się agents__unsafe_dev_only i nazwa jest celowo krzykliwa — służy do prototypowania lokalnie.

Do tego dochodzi koszt implementacji: obsługa 16 typów zdarzeń, poprawne strumieniowanie SSE z PHP-a, zarządzanie cyklem życia przebiegu i przerwaniami, bez żadnego SDK do oparcia się. Przy Octane i długo żyjących workerach jest to wykonalne, ale to projekt na tygodnie, nie na popołudnie. Wybieraj ten wariant, jeśli masz twarde wymaganie „żadnego Node'a w infrastrukturze” i budżet na licencję — inaczej wariant A albo B wypada lepiej pod każdym względem.

Inertia i React: to działa

Dobra wiadomość dla stacku, na którym stoi między innymi ta strona: CopilotKit to zwykłe komponenty Reacta, więc w aplikacji na Inertii wpina się w setup() bez żadnych obejść.

// resources/js/app.jsx
createInertiaApp({
    setup({ el, App, props }) {
        createRoot(el).render(
            <CopilotKit runtimeUrl="/copilot">
                <App {...props} />
            </CopilotKit>,
        );
    },
});

Provider musi być nad <App />, bo hooki wywoływane w komponentach stron potrzebują jego kontekstu. Nawigacja Inertii nie odmontowuje providera, więc rozmowa przeżywa przejście między stronami — a hooki useAgentContext zarejestrowane w konkretnej stronie znikają razem z nią, co jest właściwym zachowaniem: agent przestaje widzieć kontekst ekranu, którego użytkownik już nie ma przed sobą.

v1 kontra v2: pułapka na każdym tutorialu

CopilotKit przeszedł zmianę nazw API i to jest dziś główne źródło zamieszania. Materiały z internetu, wpisy blogowe i część odpowiedzi modeli językowych operują nazwami z v1; dokumentacja i przykłady wyżej — v2. Odpowiedniki:

  • useCopilotActionuseFrontendTool
  • useCopilotReadableuseAgentContext
  • useCoAgentuseAgent
  • useCopilotAction z renderuseRenderTool / useDefaultRenderTool
  • useCopilotAction z renderAndWaitForResponseuseHumanInTheLoop

Rozpoznasz to po imporcie. v2 to @copilotkit/react-core/v2 i @copilotkit/runtime/v2; komponenty czatu, które w v1 mieszkały w @copilotkit/react-ui, w v2 wychodzą z react-core/v2. Oba style działają równolegle, ale mieszanie ich w jednym drzewie komponentów kończy się błędami kontekstu, które trudno odczytać. W nowym projekcie wybierz v2 i trzymaj się jednego wariantu; w istniejącym jest oficjalny przewodnik migracji.

Co jest darmowe, a co nie

Podział jest czysty i lepiej poznać go przed, a nie po wycenie. W open source zostaje:

  • frontend SDK z hookami i gotowymi komponentami czatu,
  • runtime z adapterami do wszystkich wymienionych środowisk,
  • BuiltInAgent i wszystkie integracje z frameworkami agentowymi,
  • protokół AG-UI i prymitywy generative UI: renderowanie narzędzi, renderowanie stanu, API headless.

Za Enterprise Intelligence Platform — osobną usługę backendową — płacisz za:

  • trwałe wątki i historię rozmów przeżywającą odświeżenie strony i zmianę urządzenia, na Postgresie i Redisie,
  • synchronizację w czasie rzeczywistym przez WebSocket między kartami i urządzeniami,
  • hostowany inspector, konsolę administracyjną i zarządzanie kluczami,
  • wielodostępność: organizacje, projekty, użytkownicy — trzy poziomy izolacji,
  • selfManagedAgents, czyli wariant C powyżej.

Platformę można uruchomić w chmurze dostawcy albo u siebie, czartem Helma copilot-intelligence na własnym Kubernetesie — kod aplikacji się nie zmienia, przełącznikiem jest konfiguracja runtime'u.

Praktyczny wniosek dla większości projektów, jakie widzimy: brak trwałości rozmów w wersji darmowej jest tym punktem, który zwykle wymusza decyzję. Ma to jednak drugie dno, o którym dokumentacja pisze uczciwie — jeśli stan i tak trzymasz we własnym Postgresie i potrafisz odtworzyć kontekst wątku z własnych tabel, open source wystarcza. W aplikacji laravelowej to nie jest egzotyczne założenie: tabela rozmowy, tabela wiadomosci, kilka relacji i historia jest Twoja, w Twojej bazie, objęta Twoimi kopiami zapasowymi i Twoim RODO. Płacisz wtedy tylko za to, czego naprawdę nie chcesz pisać.

Telemetria, zgody i klient z compliance

Open source zbiera telemetrię i jest ona włączona domyślnie. Warto wiedzieć dokładnie, co i jak, bo to pytanie wraca na każdym audycie:

  • Zbierane są metadane. Dokumentacja deklaruje, że nie zbiera promptów, wiadomości, stanu agenta, danych narzędzi ani treści aplikacji, i że dane nie są sprzedawane ani udostępniane dalej.
  • Zdarzenia z runtime'u bez identyfikatora licencji są próbkowane — domyślnie 5% (COPILOTKIT_TELEMETRY_SAMPLE_RATE, wartości od 0 do 1). Wywołania z identyfikatorem telemetrycznym omijają próbkowanie.
  • Inspector w przeglądarce wysyła zdarzenia z trwałym anonimowym identyfikatorem trzymanym w pamięci przeglądarki.
  • Wyłącznik jest jeden: COPILOTKIT_TELEMETRY_DISABLED=true w środowisku runtime'u — obejmuje zarówno runtime, jak i Inspectora. Respektowany jest też nagłówek Do Not Track.

Do tego dochodzi rzecz, której w dokumentacji telemetrii nie ma, a widać ją w drzewie zależności: @copilotkit/react-core i @copilotkit/runtime ciągną @scarf/scarf (analityka instalacji paczek), a runtime dodatkowo @segment/analytics-node. Jeśli budujesz obrazy w środowisku z regulowanym ruchem wychodzącym, to jest miejsce, w którym pojawi się nieoczekiwane połączenie podczas npm install.

Ustaw COPILOTKIT_TELEMETRY_DISABLED=true w tym samym commicie, w którym dodajesz paczki. Później nikt tego nie zrobi, a przy wdrożeniu u klienta z działem bezpieczeństwa to pytanie pojawia się zawsze — lepiej mieć odpowiedź w repozytorium niż w kalendarzu.

Na co uważać

  • 94 wydania w 2026 roku. Projekt zmienia się szybko, a nazwy handlerów i hooków realnie migrowały. Przypnij dokładne wersje wszystkich paczek @copilotkit/* — mają wspólny numer, tu 1.68.2 — i aktualizuj je świadomie.
  • Node 20+ jest wymagany, a runtime to paczka npm. W stacku bez Node'a dochodzi kontener, obraz do budowania i jeszcze jedna rzecz do łatania.
  • Brak SDK AG-UI dla PHP. Osiem języków, PHP nie jest jednym z nich.
  • selfManagedAgents to funkcja komercyjna. Darmowe agents__unsafe_dev_only nie jest przeznaczone na produkcję i nazwa to komunikuje.
  • Historia rozmów nie jest w open source. Albo platforma Enterprise, albo własne tabele.
  • Narzędzia frontendowe dziedziczą uprawnienia użytkownika, narzędzia serwerowe nie. Kod wykonywany w runtimie działa z tożsamością runtime'u, więc autoryzację trzeba tam napisać od zera. Ta asymetria jest łatwa do przeoczenia i to najkrótsza droga do przypadkowej eskalacji uprawnień.
  • Bez useDefaultRenderTool wywołania narzędzi bez własnego renderera są w czacie niewidoczne. Przy narzędziach z serwerów MCP to szczególnie dokuczliwe.
  • Model decyduje o wywołaniu narzędzia. Każda funkcja, którą zarejestrujesz, jest funkcją, którą model może wywołać w nieprzewidzianym momencie i z nieprzewidzianymi argumentami. Operacje nieodwracalne stawiaj za bramką useInterrupt albo za autoryzacją serwerową, nigdy za samym opisem w description.
  • Prompt injection przez kontekst. useAgentContext wkłada dane aplikacji do promptu systemowego. Jeśli wśród nich są treści wpisane przez użytkowników — komentarze, opisy zgłoszeń, nazwy plików — to jest wektor ataku na Twoje narzędzia.
  • Dokumentacja jest zduplikowana per framework (osobne drzewa dla LangGrapha, CrewAI, Agno, AG2 i pozostałych) — łatwo czytać wariant dla frameworka, którego nie używasz. Nazwa frameworka jest w adresie URL.
  • 222 otwarte pull requesty i 360 otwartych zgłoszeń przy tym tempie wydań. Zanim zgłosisz błąd, sprawdź, czy nie jest już naprawiony w wersji wydanej wczoraj.

Kiedy to ma sens, a kiedy nie

Ma sens, gdy agent musi działać w aplikacji, a nie tylko o niej rozmawiać: wypełnić formularz, ustawić filtry, przygotować dokument, przejść z użytkownikiem przez konfigurację, pokazać wykres w środku rozmowy. Wtedy narzędzia frontendowe, generative UI i stan dzielony oszczędzają tygodnie pracy, których nie widać w prototypie, ale widać w trzecim miesiącu.

Nie ma sensu, gdy potrzebujesz okienka czatu odpowiadającego na pytania z dokumentacji. Do tego wystarczy własny komponent i strumieniowanie z endpointu w Laravelu — cały ten stack będzie wtedy kosztem, nie oszczędnością. Zwłaszcza jeśli w infrastrukturze nie ma jeszcze Node'a.

Podsumowanie

CopilotKit rozwiązuje problem, który przy budowie funkcji AI w istniejącej aplikacji pojawia się zawsze i zawsze zjada więcej czasu, niż ktokolwiek zakładał: jak połączyć agenta z konkretnym interfejsem, konkretnym stanem i konkretnymi uprawnieniami zalogowanego człowieka. Protokół AG-UI, wydzielony do osobnego projektu z własną licencją MIT, jest tu najmocniejszym argumentem — sprawia, że wybór frameworka agentowego przestaje być decyzją, której nie da się cofnąć.

Co daje:

  • gotowe komponenty czatu (CopilotChat, CopilotSidebar, CopilotPopup, CopilotThreadsDrawer) i pełne API headless, gdy gotowe nie wystarczą,
  • kontekst aplikacji podawany agentowi przez useAgentContext, scalany z wielu komponentów i aktualizowany automatycznie,
  • narzędzia wykonywane w przeglądarce, ze schematem Zoda jako kontraktem i walidacją w jednym,
  • generative UI: własne komponenty Reacta renderowane w miejscu wywołań narzędzi, ze stanem pośrednim, plus renderer zbiorczy,
  • dwa wzorce human-in-the-loop — inicjowany przez model i wymuszony przez graf,
  • dwustronny stan dzielony przez migawki i różnice AG-UI, bez dodatkowej konfiguracji backendu,
  • subskrypcję pełnego strumienia 16 typów zdarzeń pod własną telemetrię i audyt,
  • runtime z adapterami do Next.js, Express, Hono, Buna, Deno i Cloudflare Workers, z hookiem onRequest na autoryzację,
  • wymienny backend agenta: BuiltInAgent albo LangGraph, Mastra, CrewAI, Pydantic AI, Microsoft Agent Framework, AWS Strands, Google ADK,
  • SDK dla Reacta, Angulara, Vue i React Native, plus kanały Slacka i Microsoft Teams.

Licencja: plik LICENSE w repozytorium to MIT (copyright Atai Barkai), i to samo MIT deklarują metadane npm wszystkich paczek w wersji 1.68.2, które sprawdziliśmy: react-core, react-ui, runtime i shared. Strona dokumentacji porównująca open source z ofertą komercyjną mówi natomiast o Apache 2.0. Obie licencje są permisywne i przy komercyjnym użyciu różnica jest niewielka — MIT wymaga zachowania noty licencyjnej, Apache 2.0 dodatkowo daje wyraźną licencję patentową i wymaga oznaczania zmian. Jeśli jednak prowadzisz formalny audyt licencyjny i potrzebujesz jednej odpowiedzi, wiążący jest plik LICENSE, a rozbieżność warto zgłosić projektowi.

Osobno i wyraźnie: Enterprise Intelligence Platform nie jest objęta tą licencją. To zamknięta usługa backendowa, płatna, i przechodzi przez nią wszystko, co dotyczy trwałych wątków, synchronizacji w czasie rzeczywistym, hostowanego inspectora, wielodostępności oraz selfManagedAgents. Granica jest przy tym uczciwie postawiona i dobrze udokumentowana — samodzielnie działającą aplikację agentową zbudujesz na samym open source, a przełączenie na platformę nie wymaga przepisywania kodu aplikacji, tylko zmiany konfiguracji runtime'u.