GitHub Copilot SDK — silnik Copilot CLI w sześciu językach
Ten sam silnik agentowy, który napędza Copilot CLI, udostępniony jako biblioteka dla sześciu języków — z planowaniem, wywoływaniem narzędzi i edycją plików po stronie GitHuba. PHP na tej liście nie ma, ale architektura oparta na JSON-RPC do lokalnego serwera daje obejście. Omawiamy je, a także rozliczanie za prompt, tryb z własnym kluczem oraz domyślnie otwarty zestaw narzędzi.
Agenty przestały być czatem, a stały się środowiskiem uruchomieniowym. Różnica jest praktyczna: czat odpowiada na pytanie, a agent planuje, wywołuje narzędzia, czyta i zapisuje pliki, poprawia się po błędzie i wraca z wynikiem. Napisanie takiej pętli samodzielnie — z obsługą przerwań, ponowień, uprawnień i strumieniowania — to miesiące pracy, a potem stałe utrzymanie.
GitHub Copilot SDK (github.com/github/copilot-sdk) sprzedaje dokładnie tę pętlę jako bibliotekę. Obietnica jest w README postawiona bez ozdób: to ten sam silnik, który stoi za Copilot CLI — sprawdzone w produkcji środowisko agentowe, które można wywołać programowo. Ty definiujesz zachowanie agenta, a planowanie, wywoływanie narzędzi i edycję plików bierze na siebie Copilot.
Dla nas jest tu jedna zła wiadomość i jedno obejście, więc od nich zacznę po opisie stanu.
Stan projektu
Dane z API GitHuba na 13 października 2026:
- repozytorium oficjalne, w organizacji GitHuba, założone 14 stycznia 2026 — dziewięć miesięcy,
- 10 465 gwiazdek i 1435 forków w tym czasie, licencja MIT,
- ostatni push dzień przed napisaniem tego tekstu, wersja 1.0.13 z 4 września 2026, poprzedzona czterema wydaniami zapoznawczymi w ciągu dziewięciu dni,
- 290 otwartych zgłoszeń,
- projekt określa się jako ogólnie dostępny, z wersjonowaniem semantycznym.
Commity z ostatnich dni mówią o dojrzałości więcej niż deklaracje: stabilizacja testu cyklu uwierzytelniania w Javie, testu wznawiania strumienia w Pythonie, naprawa podatnej zależności w SDK dla .NET oraz dołożenie pokrycia dla architektury ARM64 z biblioteką musl. To jest praca utrzymaniowa poważnego projektu, nie demonstracja możliwości.
Sześć języków i architektura, która wyjaśnia wszystko
Oficjalne biblioteki są dla Node.js z TypeScriptem, Pythona, Go, .NET, Javy i Rusta, każda w osobnym rejestrze pakietów swojego ekosystemu. Do tego README wymienia dwie nieoficjalne, społecznościowe — dla Clojure i C++ — z jasnym zastrzeżeniem, że GitHub ich nie wspiera.
Kluczowa jest jednak nie lista, a to, jak te biblioteki działają:
Twoja aplikacja
↓
klient SDK
↓ JSON-RPC
Copilot CLI (tryb serwera)Wszystkie sześć bibliotek rozmawia z Copilot CLI po JSON-RPC. Nie ma tu sześciu implementacji silnika — jest jeden silnik w postaci procesu CLI i sześć cienkich klientów. SDK zarządza przy tym cyklem życia procesu automatycznie: startuje go i zatrzymuje wtedy, kiedy trzeba.
Detal instalacyjny, który wynika z tej konstrukcji i który warto znać przed pierwszą próbą: dla Node.js, Pythona i .NET CLI jest dociągane automatycznie jako zależność, a dla Go, Javy i Rusta trzeba zainstalować je samodzielnie albo zapewnić obecność w ścieżce systemowej. Go i Rust udostępniają dodatkowo mechanizm dołączania CLI na poziomie aplikacji.
Pięć linii, a potem własne narzędzia
Najprostsze użycie dokumentacja opisuje jako „około pięciu linii kodu" i nie przesadza:
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({ model: "auto" });
const response = await session.sendAndWait({ prompt: "What is 2 + 2?" });
console.log(response?.data.content);
await client.stop();Warto zauważyć wartość model: "auto" — wybór modelu można zostawić usłudze, co przy narzędziu żyjącym kilka generacji modeli jest właściwym domyślnym zachowaniem.
Ciekawiej jest tam, gdzie agent dostaje dostęp do naszego kodu. Własne narzędzie definiuje się nazwą, opisem, schematem parametrów i funkcją obsługującą:
const getWeather = defineTool("get_weather", {
description: "Get the current weather for a city",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "The city name" },
},
required: ["city"],
},
handler: async (args) => {
// tutaj wchodzi wywołanie naszego API
return { city: args.city, temperature: "18°C", condition: "cloudy" };
},
});
const session = await client.createSession({
model: "auto",
streaming: true,
tools: [getWeather],
});Kto pracował z wywoływaniem funkcji przez model, rozpozna ten wzorzec od razu — schemat parametrów jest zwykłym schematem JSON. Różnica polega na tym, co dzieje się dalej: pętlą decyzyjną, ponowieniami i łączeniem wyników z kilku narzędzi zajmuje się silnik, a nie nasz kod. To jest właśnie ta praca, której nie trzeba pisać.
Strumieniowanie odpowiedzi obsługuje się nasłuchem na zdarzenia sesji — przyrostów treści oraz zakończenia pracy:
session.on("assistant.message_delta", (event) => {
process.stdout.write(event.data.deltaContent);
});
session.on("session.idle", () => console.log());Przy funkcji w panelu klienta ma to znaczenie praktyczne: zadanie agentowe trwa dziesiątki sekund, więc różnica między przyrostowym pokazywaniem postępu a kręcącym się kółkiem decyduje o tym, czy użytkownik poczeka.
Obserwowalność, bez której agent jest czarną skrzynką
Funkcja, którą doceniłem najbardziej, bo rozwiązuje problem pojawiający się dokładnie wtedy, gdy jest najdroższy. Biblioteka obsługuje OpenTelemetry do rozproszonego śledzenia: wystarczy podać konfigurację telemetrii przy tworzeniu klienta, wskazując adres kolektora — i samo podanie tej konfiguracji jest włączeniem, bez osobnej flagi.
const client = new CopilotClient({
telemetry: { otlpEndpoint: "http://localhost:4318" },
});Eksportowane są przy tym ślady z procesu CLI, a nie tylko z naszego kodu, wraz z automatyczną propagacją kontekstu śledzenia w standardzie W3C między biblioteką a CLI. Do tego dochodzi eksport do pliku, gdy kolektora nie ma.
Znaczenie tego jest bardzo konkretne. Agent, który przez czterdzieści sekund coś robił i zwrócił zły wynik, bez śladów jest nie do zdiagnozowania — nie wiadomo, ile było kroków, które narzędzia zawiodły i gdzie poszedł czas. Ze śladami staje się to zwykłym problemem do przeczytania w narzędziu, którego zespół już używa. Przy usłudze rozliczanej za prompt jest to również jedyna droga do odpowiedzi na pytanie, dlaczego rachunek wygląda tak, a nie inaczej.
Nie ma SDK dla PHP — i co z tym zrobić
Powiedzmy to wprost: PHP nie ma i nic nie wskazuje, żeby miało być. Lista sześciu języków to Node, Python, Go, .NET, Java i Rust, a dwie nieoficjalne biblioteki społecznościowe też PHP nie obejmują.
Architektura daje jednak dwie drogi obejścia i warto rozumieć różnicę między nimi, bo mają zupełnie inny profil ryzyka.
Droga pierwsza: rozmawiać z serwerem bezpośrednio. CLI potrafi działać jako serwer, uruchamiany jedną komendą:
copilot --headless --port 4321Bez podanego portu wybierany jest losowy wolny. Skoro protokołem jest JSON-RPC, to nic nie zabrania rozmawiać z tym serwerem z PHP — to zwykłe wywołania po sieci lokalnej. Ryzyko jest jednak realne: protokół nie jest udokumentowanym kontraktem publicznym, a udokumentowanym interfejsem są biblioteki. Każde wydanie może go zmienić bez ostrzeżenia, bo formalnie nikomu tego nie obiecano.
Droga druga, którą wybrałbym w projekcie klienckim: cienki serwis pomocniczy w Node.js. Kilkadziesiąt linii, oficjalna biblioteka w środku, własne API HTTP na zewnątrz, wołane z Laravela jak każda inna usługa wewnętrzna. Kosztuje jeden dodatkowy proces w infrastrukturze, a w zamian oficjalna biblioteka wchłania zmiany protokołu za nas — i to jest dokładnie to, za co się w takich układach płaci.
Dokumentacja podaje przy tym trzy powody, dla których nawet w językach obsługiwanych warto uruchamiać serwer osobno, a wszystkie trzy pasują do naszych realiów: diagnostyka (serwer żyje między restartami aplikacji, więc logi zostają), współdzielenie zasobów (wiele klientów do jednego serwera) oraz rozwój z odrębnymi ustawieniami.
Uwaga na wystawienie serwera
Domyślnie serwer przyjmuje połączenia wyłącznie z pętli zwrotnej, więc klient musi działać na tej samej maszynie. Do pracy z kontenera albo z innego hosta służy przełącznik wiążący z innym adresem:
copilot --headless --host 0.0.0.0 --port 4321Dokumentacja stawia tu ostrzeżenie, które warto przeczytać dwa razy: wystawienie serwera na adresie innym niż pętla zwrotna czyni go osiągalnym dla każdego, kto potrafi do tego adresu trafić, i wymaga własnych zabezpieczeń sieciowych oraz uwierzytelniania odpowiedniego do środowiska.
Innymi słowy: serwer nie ma wbudowanego uwierzytelniania. To, co za nim stoi, jest agentem z dostępem do plików i narzędzi, więc jego wystawienie bez zapory i warstwy uwierzytelniającej jest jednym z gorszych pomysłów, jakie da się w infrastrukturze zrealizować. W naszym układzie serwis pomocniczy z drogi drugiej rozwiązuje to naturalnie: serwer zostaje na pętli zwrotnej, a uwierzytelnianie robi nasz kod.
Domyślnie otwarty zestaw narzędzi
To najważniejsza sekcja z punktu widzenia odpowiedzialności i cytuję ją, bo dokumentacja jest tu wzorowo szczera. Domyślnie SDK udostępnia pierwszoplanowe narzędzia Copilot CLI — „podobnie jak uruchomienie CLI z przełącznikiem --allow-all". Wykonanie narzędzia podlega przy tym obsłudze uprawnień właściwej dla danej biblioteki, więc aplikacja może zatwierdzać, odrzucać i dostosowywać wywołania.
Trzeba jednak zauważyć, co robią przykłady w dokumentacji: sesja jest w nich tworzona z pomocniczą funkcją zatwierdzającą wszystko. Jest to wygodne w przykładzie i całkowicie niewłaściwe w produkcji.
Obsługa uprawnień jest tu jedyną granicą bezpieczeństwa. Agent, który potrafi czytać i zapisywać pliki oraz uruchamiać narzędzia, wbudowany w aplikację obsługującą cudze dane, wymaga listy dozwolonych operacji ustalonej świadomie — a nie funkcji zatwierdzającej wszystko przeniesionej z przykładu. To jest pierwsza rzecz, którą sprawdzałbym w przeglądzie takiego kodu.
Dostępność narzędzi da się przy tym ograniczyć konfiguracją klienta, włączając i wyłączając konkretne pozycje — czyli oprócz zatwierdzania po fakcie można też po prostu nie dawać agentowi tego, czego nie potrzebuje. Przy funkcji, która ma streszczać zgłoszenia, dostęp do zapisu plików nie jest potrzebny w żadnym wariancie.
Rozliczanie i tryb z własnym kluczem
Ta część rozstrzyga o wycenie projektu, a odpowiedzi są w dokumentacji jednoznaczne.
Subskrypcja Copilota jest wymagana — z jednym wyjątkiem, o którym za chwilę. Rozliczanie działa tak samo jak w Copilot CLI: każdy prompt liczy się do przydziału, a istnieje darmowy poziom z ograniczonym użyciem. Warto to przełożyć na realia projektu: agent wykonujący zadanie wykonuje wiele promptów — planuje, woła narzędzia, poprawia się — więc jedno „zadanie użytkownika" nie równa się jednemu promptowi w rozliczeniu.
Wyjątkiem jest tryb z własnym kluczem: można skonfigurować bibliotekę tak, żeby korzystała z własnych kluczy API u obsługiwanych dostawców — wymienieni są OpenAI, Microsoft Foundry i Anthropic — i wtedy uwierzytelnianie w GitHubie nie jest w ogóle potrzebne. Dla klienta, który ma już umowę z dostawcą modeli, to jest istotna informacja: silnik agentowy bierzesz od GitHuba, a za tokeny płacisz tam, gdzie już płacisz.
Jest tu jednak ograniczenie, które przy klientach korporacyjnych bywa rozstrzygające i dokumentacja podaje je wprost: tryb z własnym kluczem obsługuje wyłącznie uwierzytelnianie kluczem. Microsoft Entra ID, tożsamości zarządzane i zewnętrzni dostawcy tożsamości nie są obsługiwane. Klient z polityką zakazującą trzymania statycznych kluczy w konfiguracji usług usłyszy więc „nie", i lepiej dowiedzieć się o tym przed wyceną.
Metody uwierzytelniania w wariancie standardowym są cztery: poświadczenia użytkownika zalogowanego w CLI, tokeny użytkowników z własnej aplikacji OAuth GitHuba — co pozwala działać w imieniu użytkowników naszej aplikacji — zmienne środowiskowe oraz wspomniany tryb z własnym kluczem.
Rozszerzenia i modele
- Własne agenty, umiejętności i narzędzia są obsługiwane, wraz z protokołem MCP w dokumentacji funkcji,
- Modele: dostępne są wszystkie te, które obsługuje Copilot CLI, a biblioteka udostępnia metodę zwracającą listę dostępnych modeli w czasie działania. To ważniejsze, niż wygląda — pozwala nie wpisywać nazw modeli na stałe w kod, który przeżyje kilka ich generacji,
- Punkty zaczepienia na zdarzenia cyklu życia sesji, opisane w dokumentacji funkcji obok agentów i umiejętności.
Osobno warto odnotować rzecz, którą w tej serii widzę już po raz kolejny: GitHub publikuje osobne instrukcje dla asystentów kodujących, dla każdego języka SDK, w oddzielnym repozytorium z materiałami. Czyli producent biblioteki zakłada, że kod z jej użyciem będzie pisany z asystentem, i dostarcza mu wiedzę o własnym API zamiast liczyć na to, że model ją zna. To jest już wzorzec, nie ciekawostka.
Pułapki
- Nie ma biblioteki dla PHP, a te społecznościowe są nieoficjalne i niewspierane,
- Protokół JSON-RPC nie jest publicznym kontraktem — rozmawianie z serwerem wprost działa, ale na własne ryzyko przy każdej aktualizacji,
- Serwer nie ma uwierzytelniania i domyślnie słucha tylko na pętli zwrotnej. Wystawienie go szerzej wymaga zapory i własnej warstwy uwierzytelniającej,
- Domyślny zestaw narzędzi jest otwarty, podobnie jak przy uruchomieniu CLI z zezwoleniem na wszystko,
- Funkcja zatwierdzająca wszystko z przykładów nie należy do produkcji — obsługa uprawnień jest jedyną granicą bezpieczeństwa,
- Rozliczanie jest za prompt, a jedno zadanie agenta to wiele promptów. Koszt trudno przewidzieć bez pomiaru,
- Tryb z własnym kluczem to wyłącznie klucze statyczne — bez Entra ID, tożsamości zarządzanych i zewnętrznych dostawców tożsamości,
- Dla Go, Javy i Rusta CLI nie jest dołączane i trzeba je zapewnić samodzielnie,
- 290 otwartych zgłoszeń przy dziewięciu miesiącach istnienia — projekt jest młody i intensywnie zgłaszany,
- Zależność od jednego dostawcy: to nie jest biblioteka do modeli, a klient konkretnej usługi. Tryb z własnym kluczem uwalnia od rachunku, ale nie od silnika.
Gdzie to ma sens w naszej pracy
- Zadania na kodzie w panelu klienta. „Popraw wszystkie opisy produktów według nowych wytycznych", „przygotuj migrację z tego pliku CSV" — czyli rzeczy, w których agent musi czytać, pisać i sprawdzać wynik, a nie tylko odpowiedzieć,
- Automatyzacja pracy w repozytorium. Skoro to silnik Copilot CLI, to naturalnym zastosowaniem jest uruchamianie go w potoku: aktualizacje zależności z poprawą kodu, migracje między wersjami frameworka, uzupełnianie testów,
- Serwis pomocniczy dla naszych aplikacji w Laravelu. Jeden mały proces w Node.js z oficjalną biblioteką, wołany po HTTP — najtańsza droga do wbudowania agenta w istniejący projekt PHP,
- Klient z istniejącą umową na Copilota. Jeśli zespół klienta już ma subskrypcje, silnik agentowy jest w cenie, a my dokładamy integrację. To jest dobry argument sprzedażowy,
- Klient z własnym kluczem u dostawcy modeli. Tryb z własnym kluczem oddziela wybór silnika od rachunku za tokeny.
Czego bym nie robił: nie wystawiałbym agenta z otwartym zestawem narzędzi na ścieżkę, którą chodzą użytkownicy końcowi, i nie wpisywałbym tej biblioteki w architekturę, w której zależność od jednego dostawcy jest problemem. Do prostego generowania tekstu albo klasyfikacji jest to zresztą narzędzie nieproporcjonalne — tam wystarcza zwykłe wywołanie modelu.
Podsumowanie
- Ten sam silnik, który napędza Copilot CLI, udostępniony programowo — z planowaniem, narzędziami i edycją plików,
- Sześć oficjalnych bibliotek: Node, Python, Go, .NET, Java, Rust. PHP nie ma,
- Wszystkie rozmawiają po JSON-RPC z CLI w trybie serwera — jeden silnik, sześć cienkich klientów,
- Z PHP najbezpieczniej przez cienki serwis w Node.js, nie przez protokół bezpośrednio,
- Serwer domyślnie tylko na pętli zwrotnej i bez uwierzytelniania,
- Domyślne narzędzia są otwarte, a obsługa uprawnień to jedyna granica — ustaw ją świadomie,
- Rozliczanie za prompt, przy czym jedno zadanie agenta to wiele promptów,
- Tryb z własnym kluczem znosi wymóg subskrypcji, ale obsługuje wyłącznie klucze statyczne,
- CLI dołączane automatycznie tylko dla Node, Pythona i .NET,
- Lista modeli dostępna w czasie działania, a
model: "auto"zdejmuje decyzję z kodu, - Własne narzędzia to schemat JSON plus funkcja, a pętlę decyzyjną prowadzi silnik,
- Włącz OpenTelemetry — bez śladów agent jest nie do zdiagnozowania i nie do rozliczenia,
- Projekt młody, ale utrzymywany poważnie: wersjonowanie semantyczne, ogólna dostępność, naprawy zależności i testy na wielu architekturach.
Licencja: biblioteki są na MIT, czyli w najwygodniejszym możliwym układzie: wolno używać komercyjnie, modyfikować, wpinać w produkty zamknięte i redystrybuować, przy zachowaniu noty licencyjnej. Przy projekcie prowadzonym przez GitHuba nie jest to zaskoczenie, ale w tym przypadku licencja kodu jest najmniej istotną częścią rachunku — i to jest najważniejsza rzecz do zrozumienia przed wdrożeniem. Biblioteka na MIT jest bowiem cienkim klientem sterującym komercyjną usługą: swobodę daje nam licencja, ale to, czy i za ile wolno z tego korzystać, rozstrzygają warunki GitHub Copilota oraz przydział promptów w subskrypcji. Wolny kod nie oznacza tu wolnego działania — bez subskrypcji albo bez trybu z własnym kluczem ten kod nie robi nic. Trzy rozgraniczenia warto więc postawić klientowi wprost. Po pierwsze, rozliczanie jest za prompt, a nie za zadanie, więc koszt trzeba zmierzyć na reprezentatywnym zadaniu, zanim się go zadeklaruje. Po drugie, w trybie z własnym kluczem obowiązują regulaminy dostawców modeli — OpenAI, Microsoft Foundry albo Anthropic — wraz z ich zasadami przetwarzania danych, bo to tam trafiają prompty. Po trzecie, kod klienta jest wolny, ale silnik nie: nie ma tu ścieżki do uruchomienia całości we własnej infrastrukturze, a przeniesienie się na inne rozwiązanie oznacza wymianę warstwy agentowej, nie zmianę konfiguracji. To nie zarzut, a cena, którą trzeba znać: kupujemy dojrzałe środowisko agentowe i płacimy przywiązaniem do jednego dostawcy.