Przejdź do treści
sobolewski.proAI dziś, o 20:00Zapisz się

Raz dziennie, wypiszesz się jednym kliknięciem. Polityka prywatności

Jak zbudować agenta AI w Pythonie: Claude Agent SDK krok po kroku

Jak zbudować agenta AI, który sam czyta i poprawia kod? Instalujemy Claude Agent SDK, piszemy pierwszego agenta, dodajemy własne narzędzie i MCP. Krok po kroku.

8 min czytania

Ten artykuł w innych językach:العربيةDeutschEnglishEspañolFrançaisItaliano日本語简体中文

W tym artykule
  1. Czym jest agent AI z punktu widzenia programisty?
  2. Krok 1: jak zainstalować Claude Agent SDK?
  3. Krok 2: jak ustawić klucz API?
  4. Krok 3: jak napisać pierwszego agenta AI?
  5. Krok 4: jak ustawić, co agent może robić sam?
  6. Krok 5: jak dodać agentowi własne narzędzie?
  7. Krok 6: jak podłączyć agenta do serwera MCP?
  8. Co dalej po pierwszym agencie?
  9. Na co zwrócić uwagę?
  10. FAQ

Jak zbudować agenta AI bez pisania całej pętli od zera? Najkrótsza droga, jaką znam, to Claude Agent SDK, czyli biblioteka dla Pythona i TypeScriptu, która daje nam te same narzędzia, pętlę agenta i zarządzanie kontekstem, na których działa Claude Code. Piszemy kilkanaście linijek kodu, a agent sam czyta pliki, poprawia błędy i uruchamia komendy.

W tym poradniku budujemy pierwszego agenta w Pythonie, ustawiamy mu uprawnienia, dodajemy własne narzędzie i serwer MCP. Wszystkie komendy i fragmenty kodu pochodzą z oficjalnego quickstartu Agent SDK i stron dokumentacji, do których linkuję po drodze.

Czym jest agent AI z punktu widzenia programisty?

Według dokumentacji agent to aplikacja, która wykonuje zadanie, sama planując kolejne kroki i wywołując narzędzia: czyta pliki, uruchamia komendy albo edytuje kod. Szerzej, bez kodu, opisałem to w poradniku Co to jest agent AI.

Z punktu widzenia programisty najważniejsza jest pętla: model myśli, wywołuje narzędzie, ogląda wynik i decyduje, co dalej. Agent SDK przejmuje tę pętlę, wykonywanie narzędzi, zarządzanie kontekstem i ponawianie zapytań, a my tylko czytamy strumień wiadomości.

Dokumentacja odróżnia przy tym cztery sposoby pracy z Claude:

  1. Agent SDK, czyli biblioteka, która uruchamia agenta Claude Code w naszej aplikacji (w procesie, którym sami zarządzamy),
  2. Claude Code CLI, czyli terminal do codziennej, interaktywnej pracy (o nim jest poradnik Claude Code),
  3. Client SDK, czyli bezpośredni dostęp do Claude API, gdzie pętlę narzędzi piszemy sami (albo zlecamy ją tzw. „tool runnerowi” w becie),
  4. Managed Agents, czyli agent hostowany przez Anthropic i konfigurowany przez API.

Ten poradnik dotyczy pierwszej opcji.

Krok 1: jak zainstalować Claude Agent SDK?

Potrzebujemy Pythona 3.10+ (albo Node.js 18.14+ dla TypeScriptu) i konta w Claude Console. Najpierw tworzymy folder projektu:

mkdir my-agent
cd my-agent

Agent ma domyślnie dostęp do plików w tym katalogu i jego podkatalogach. Dokumentacja poleca menedżer pakietów uv:

uv init
uv add claude-agent-sdk

Wersja ze zwykłym pip (macOS i Linux) wygląda tak:

python3 -m venv .venv
source .venv/bin/activate
pip install claude-agent-sdk

Co ciekawe, osobna instalacja Claude Code zwykle nie jest potrzebna: oba SDK mają w paczce natywny plik binarny Claude Code. Wyjątkiem są instalacje bez gotowej paczki dla danej platformy, np. na Windowsie ARM64 (wtedy instalujemy Claude Code ręcznie, a SDK znajdzie go w PATH).

Krok 2: jak ustawić klucz API?

Klucz tworzymy w Claude Console i ustawiamy jako zmienną środowiskową w terminalu, w którym uruchomimy agenta:

export ANTHROPIC_API_KEY=your-api-key

SDK nie wczytuje plików .env automatycznie, więc jeśli trzymamy klucz w .env, musimy go załadować sami (np. pakietem dotenv). Zamiast klucza Anthropic można też użyć Amazon Bedrock, Claude Platform on AWS, Google Cloud albo Microsoft Foundry, ustawiając odpowiednią zmienną, np. CLAUDE_CODE_USE_BEDROCK=1.

Jedno zastrzeżenie z dokumentacji: bez wcześniejszej zgody Anthropic nie pozwala, żeby produkty zbudowane na Agent SDK oferowały logowanie kontem claude.ai albo korzystały z limitów subskrypcji. Agent działa na kluczu API i płacimy za tokeny (jak je śledzić, pisałem przy okazji kosztów Claude API).

Krok 3: jak napisać pierwszego agenta AI?

Przykład z quickstartu to agent, który znajduje i naprawia błędy w kodzie. Najpierw tworzymy plik utils.py z dwoma celowymi błędami:

def calculate_average(numbers):
    total = 0
    for num in numbers:
        total += num
    return total / len(numbers)


def get_user_name(user):
    return user["name"].upper()

calculate_average([]) wywali się na dzieleniu przez zero, a get_user_name(None) na TypeError. Teraz właściwy agent, czyli plik agent.py:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ResultMessage


async def main():
    # Agentic loop: streams messages as Claude works
    async for message in query(
        prompt="Review utils.py for bugs that would cause crashes. Fix any issues you find.",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Edit", "Glob"],  # Auto-approve these tools
            permission_mode="acceptEdits",  # Auto-approve file edits
        ),
    ):
        # Print human-readable output
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if hasattr(block, "text"):
                    print(block.text)  # Claude's reasoning
                elif hasattr(block, "name"):
                    print(f"Tool: {block.name}")  # Tool being called
        elif isinstance(message, ResultMessage):
            print(f"Done: {message.subtype}")  # Final result


asyncio.run(main())

Kod ma trzy części:

  1. query tworzy pętlę agenta i zwraca asynchroniczny iterator, więc wiadomości czytamy na bieżąco przez async for,
  2. prompt to zadanie. Claude sam decyduje, których narzędzi użyć,
  3. options to konfiguracja: tu allowed_tools z góry zatwierdza Read, Edit i Glob, a permission_mode="acceptEdits" automatycznie akceptuje zmiany w plikach.

Uruchamiamy:

uv run agent.py

(albo python agent.py w aktywnym środowisku venv). Agent wypisuje swoje rozumowanie i każde wywołane narzędzie, a na końcu Done: success. Po wszystkim w utils.py znajdziemy obsługę pustej listy i braku użytkownika. Agent sam przeczytał plik, znalazł przypadki brzegowe i poprawił kod, a my nie napisaliśmy ani jednej funkcji do obsługi narzędzi.

Jeśli zobaczymy błąd Not logged in albo Invalid API key, prawie na pewno zmienna ANTHROPIC_API_KEY nie jest ustawiona w tym terminalu.

Krok 4: jak ustawić, co agent może robić sam?

O tym, co agent potrafi, decydują narzędzia. Dokumentacja podaje trzy typowe zestawy:

  1. Read, Glob, Grep, czyli tylko analiza, bez zmian w plikach,
  2. Read, Edit, Glob, czyli analiza i edycja kodu,
  3. Read, Edit, Bash, Glob, Grep, czyli pełna automatyzacja z komendami w terminalu.

Żeby agent mógł np. szukać w sieci albo uruchamiać testy, wystarczy dopisać narzędzie i zmienić prompt:

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Edit", "Glob", "Bash"], permission_mode="acceptEdits"
)

Z włączonym Bash quickstart proponuje zadanie „Write unit tests for utils.py, run them, and fix any failures”. Można też nadać agentowi rolę przez system_prompt, np. doświadczonego programisty Pythona, który pilnuje PEP 8.

Drugą dźwignią jest tryb uprawnień (permission_mode):

  1. "default" przekazuje każde niezatwierdzone wywołanie do naszej funkcji canUseTool, a bez niej odmawia,
  2. "acceptEdits" akceptuje edycje plików i proste komendy typu mkdir czy mv w katalogu roboczym,
  3. "plan" każe agentowi najpierw zbadać kod i przygotować plan,
  4. "dontAsk" nigdy nie pyta: działa tylko to, co zatwierdziliśmy z góry, reszta jest odrzucana (dobre dla agentów bez człowieka przy klawiaturze),
  5. "auto" przepuszcza akcje przez klasyfikator, który każdą przegląda i blokuje albo zezwala,
  6. "bypassPermissions" wykonuje wszystko bez pytania i według dokumentacji nadaje się tylko do odizolowanych środowisk, takich jak CI albo kontenery.

Złota zasada z dokumentacji: "acceptEdits" na komputerze deweloperskim, "bypassPermissions" tylko tam, gdzie agent nie może zaszkodzić niczemu ważnemu. Więcej o tym, dlaczego to ma znaczenie, w poradniku o bezpieczeństwie agentów AI.

Warto też od razu ustawić limity: max_turns ogranicza liczbę tur, a max_budget_usd zatrzymuje pętlę po przekroczeniu szacowanego kosztu. Bez nich agent działa, dopóki sam nie skończy, co przy otwartych zadaniach typu „ulepsz ten projekt” może potrwać ;)

Krok 5: jak dodać agentowi własne narzędzie?

Wbudowane narzędzia to dopiero początek. Własne narzędzie definiujemy dekoratorem @tool (nazwa, opis, schemat wejścia i funkcja), a potem pakujemy je w serwer MCP działający w tym samym procesie. Przykład z dokumentacji pobiera temperaturę z API Open-Meteo, więc najpierw dodajemy bibliotekę httpx:

uv add httpx

Definicja narzędzia:

from typing import Annotated, Any
import httpx
from claude_agent_sdk import tool, create_sdk_mcp_server


# Define a tool: name, description, input schema, handler
@tool(
    "get_temperature",
    "Get the current temperature at a location",
    {
        "latitude": Annotated[float, "Latitude coordinate"],
        "longitude": Annotated[float, "Longitude coordinate"],
    },
)
async def get_temperature(args: dict[str, Any]) -> dict[str, Any]:
    async with httpx.AsyncClient() as client:
        response = await client.get(
            "https://api.open-meteo.com/v1/forecast",
            params={
                "latitude": args["latitude"],
                "longitude": args["longitude"],
                "current": "temperature_2m",
                "temperature_unit": "fahrenheit",
            },
        )
        data = response.json()

    # Return a content array - Claude sees this as the tool result
    return {
        "content": [
            {
                "type": "text",
                "text": f"Temperature: {data['current']['temperature_2m']}°F",
            }
        ]
    }


# Wrap the tool in an in-process MCP server
weather_server = create_sdk_mcp_server(
    name="weather",
    version="1.0.0",
    tools=[get_temperature],
)

W tym samym pliku przekazujemy serwer do agenta. Pełna nazwa narzędzia ma format mcp__{serwer}__{narzędzie} i to ją wpisujemy do allowed_tools, żeby działało bez pytania o zgodę:

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def main():
    options = ClaudeAgentOptions(
        mcp_servers={"weather": weather_server},
        allowed_tools=["mcp__weather__get_temperature"],
    )

    async for message in query(
        prompt="What's the temperature in San Francisco?",
        options=options,
    ):
        # ResultMessage is the final message after all tool calls complete
        if isinstance(message, ResultMessage) and message.subtype == "success":
            print(message.result)


asyncio.run(main())

Agent wywołuje nasze narzędzie i na podstawie wyniku odpowiada. W miejsce pogody możemy podpiąć cokolwiek: naszą bazę danych, wewnętrzne API albo skrypt.

Krok 6: jak podłączyć agenta do serwera MCP?

Gotowe serwery MCP (o samym protokole pisałem w poradniku Co to jest MCP) podłączamy w opcji mcp_servers. Przykład z dokumentacji łączy agenta ze zdalnym serwerem dokumentacji Claude Code przez HTTP:

options = ClaudeAgentOptions(
    mcp_servers={
        "claude-code-docs": {
            "type": "http",
            "url": "https://code.claude.com/docs/mcp",
        }
    },
    allowed_tools=["mcp__claude-code-docs__*"],
)

Gwiazdka w allowed_tools zatwierdza wszystkie narzędzia z danego serwera. Z promptem „Use the docs MCP server to explain what hooks are in Claude Code” agent przeszukuje dokumentację i zwraca odpowiedź.

Co dalej po pierwszym agencie?

Agent SDK ma też resztę funkcji Claude Code:

  1. hooki, czyli własny kod uruchamiany przed albo po wywołaniu narzędzia,
  2. subagenty do wydzielonych podzadań,
  3. sesje: identyfikator z ResultMessage.session_id pozwala wznowić rozmowę z pełnym kontekstem albo ją rozgałęzić,
  4. skille, komendy i pamięć wczytywane z katalogu .claude/, tak jak w Claude Code.

Gotowe przykładowe aplikacje (m.in. asystent poczty i agent badawczy) są w repozytorium claude-agent-sdk-demos.

Na co zwrócić uwagę?

Po pierwsze, na koszty. Kontekst rośnie z każdą turą, a duży plik albo gadatliwa komenda potrafią zjeść tysiące tokenów naraz. Stałe części (prompt systemowy, definicje narzędzi) są automatycznie cache’owane, ale max_budget_usd i tak warto ustawić od pierwszego dnia (cap może zostać przekroczony o koszt jednej odpowiedzi, więc zostawmy zapas).

Po drugie, na uprawnienia. Agent z Bash i bypassPermissions na zwykłym laptopie to proszenie się o kłopoty, więc pełną automatyzację zostawmy dla kontenerów.

Po trzecie, na branding. Według dokumentacji produkt zbudowany na SDK może się nazywać np. „Claude Agent” albo „ Powered by Claude”, ale nie „Claude Code” i nie może udawać produktu Anthropic.

FAQ

Jak zbudować agenta AI bez pisania pętli od zera?

Najprościej przez bibliotekę, która tę pętlę już ma, np. Claude Agent SDK. Instalujemy claude-agent-sdk, ustawiamy ANTHROPIC_API_KEY i wywołujemy query() z promptem oraz listą dozwolonych narzędzi. Resztę, czyli wywoływanie narzędzi i zarządzanie kontekstem, robi SDK.

Czy Claude Agent SDK jest darmowy?

Sama biblioteka nie kosztuje nic, ale agent korzysta z Claude API, więc płacimy za zużyte tokeny. Bez zgody Anthropic nie można go podpiąć pod subskrypcję claude.ai.

Czym różni się Agent SDK od Claude API?

W zwykłym Client SDK (Claude API) pętlę narzędzi piszemy sami albo korzystamy z tool runnera w becie. Agent SDK ma wbudowane narzędzia Claude Code (czytanie i edycję plików, komendy, wyszukiwanie w sieci), uprawnienia, sesje i hooki.

Czy agenta można napisać w TypeScripcie?

Tak. Pakiet to @anthropic-ai/claude-agent-sdk, wymaga Node.js 18.14+, a opcje w przykładach z dokumentacji nazywają się tak samo jak w Pythonie, tylko w camelCase (allowedTools, permissionMode).

  • AI
  • agenci AI
  • Claude
  • programowanie
  • poradnik

AI dziś, o 20:00

Codziennie wieczorem najważniejsze wiadomości ze świata AI i nowe wpisy z bloga. Krótko, ze źródłami.

Raz dziennie, wypiszesz się jednym kliknięciem. Polityka prywatności