Przejdź do głównej zawartości
Claude Code Autor: 18 min czytania
Opublikowano:

Claude Agent SDK po polsku, budowa agentów Python i TypeScript 2026

Pierwszy polski tutorial Claude Agent SDK. Architektura agent loop, tools, memory, multi-step, Python + TypeScript code samples, deployment w CI/cron, antywzorce.

Spis treści

Aktualizacja: maj 2026. Claude Agent SDK to biblioteka, z której budujesz własne autonomiczne agenty oparte na modelu Claude, działające headless w cronie, GitHub Action, webhooku, serverless lambdzie. W tym tutorialu pokazuję architekturę agent loop, definicję własnych tools (Python decorator i TypeScript schema), memory management na dłuższe sesje, multi-step error handling, subagents, deployment do produkcji oraz realne koszty z mojej praktyki. Wszystkie code samples są working, sprawdzone, kopiuj i odpalaj.

TL;DR, Claude Agent SDK w 7 punktach:

  • Biblioteka Python i TypeScript, do budowy własnych agentów Claude
  • Headless (no terminal UI), produkcyjny, działa w cronie i CI
  • Agent loop: planning, tool use, observation, retry, stop
  • Custom tools, decorator w Pythonie, schema w TypeScript
  • Wspiera MCP servers, prompt caching, streaming, subagents
  • Typowy koszt: poniżej 1 dolara dziennie dla agenta godzinowego
  • Polski kurs: /kurs-claude-code/ (moduł Agent SDK + 3 projekty)

Czym jest Claude Agent SDK

Claude Agent SDK to oficjalna biblioteka Anthropic do budowy autonomicznych agentów opartych na modelu Claude. Dostępna w dwóch językach, Python (claude-agent-sdk) i TypeScript (@anthropic-ai/claude-agent-sdk). Pod spodem opakowuje Messages API w pętlę agenta: model dostaje cel, planuje, woła narzędzia, czyta rezultaty, decyduje co dalej, aż uzna zadanie za zakończone.

SDK powstał z dokładnie tej samej bazy, na której zbudowane jest Claude Code CLI. Jeśli używałeś Claude Code w terminalu, znasz już doświadczenie agentowe, tyle że jako użytkownik. SDK pozwala ci postawić się po drugiej stronie i zbudować własny Claude Code, dopasowany do twojego workflow, z twoimi narzędziami, działający bez ciebie 24/7.

Trzy warstwy ekosystemu Anthropic

Najczęstsze pytanie nowych użytkowników: kiedy używać czego z poniższych trzech?

Anthropic Messages API vs Claude Agent SDK vs Claude Code CLI
Narzędzie Co to jest Kiedy użyć
Anthropic Messages API Niskopoziomowe HTTP API, jeden request to jedna odpowiedź modelu Single-shot generation, chat, klasyfikacja, brak agentic loop
Claude Agent SDK Biblioteka z pętlą agenta, tool use, planning, retry Autonomiczne agenty w CI, cron, webhook, własne tools, multi-step
Claude Code CLI Gotowy interaktywny agent w terminalu, z hookami i slash commands Praca developera, refactor, debug, ad-hoc taski lokalne

Mental model: API to "model", SDK to "agent", CLI to "produkt". W tym artykule koncentruję się na środku, czyli SDK. Tutorial CLI jest w osobnym artykule.

Architektura agent loop

Cała magia agentów Claude sprowadza się do prostej pętli. Zrozumienie tej pętli jest kluczowe, bo każdy bug, każdy nieoczekiwany koszt, każdy infinite loop wynika z czegoś, co się w niej dzieje.

  1. Planning. Model dostaje system prompt, user prompt i listę dostępnych narzędzi. Generuje pierwszą odpowiedź, która może zawierać text reasoning i/lub tool_use blocks.
  2. Tool execution. SDK wykonuje narzędzia wywołane przez model (lokalne funkcje, MCP, builtin). Zwraca tool_result do modelu.
  3. Observation. Model widzi rezultat narzędzia, planuje następny krok. Może wywołać kolejne narzędzia, zwrócić text dla użytkownika, albo zakończyć.
  4. Stop. Agent kończy się, gdy model nie wywołuje już narzędzi (stop_reason: end_turn) albo gdy SDK uderzy w max_turns / timeout.

To wszystko. Nie ma magii, nie ma ukrytej AI orkiestracji. Każdy turn to jedno wywołanie Messages API. SDK po prostu pakuje response, wykonuje tools, wraca do API z rezultatami, powtarza.

Z tego mental modelu wynikają trzy praktyczne wnioski:

  • Każdy turn kosztuje, czyli twój budżet to liczba turn × średni koszt jednego turna. Nieskończona pętla to nieskończony rachunek.
  • Cały kontekst jest re-wysyłany każdy turn, bo Messages API jest stateless. Dlatego prompt caching jest kluczowy, bez niego płacisz wielokrotnie za to samo.
  • Tools to interfejs między modelem a światem. Jakość ich opisu (description, parametry, error messages) determinuje jakość agenta.

Stop conditions, kiedy agent się kończy

Agent loop ma cztery naturalne stop conditions, każdy z innym semantycznym znaczeniem dla twojego kodu:

  1. end_turn, model uznał, że zadanie jest skończone, ostatnia odpowiedź to text dla użytkownika. Happy path.
  2. max_turns, SDK przerwało, bo agent przekroczył limit. Zazwyczaj symptom źle zaprojektowanego promptu albo nieidempotentnych tools.
  3. tool_use_error, model wywołał tool, ale wykonanie rzuciło exception nieobsłużony. Domyślnie SDK wraca z błędem do modelu, ale możesz nadpisać behavior.
  4. process_timeout, watchdog na poziomie procesu (cron, GitHub Action) ubił proces. Najgorsza opcja, bo zostawia stan w połowie zmiany. Zawsze ustaw watchdog wyższy niż max_turns × max_turn_time.

Loguj stop_reason przy każdym uruchomieniu agenta, to twoja pierwsza linia diagnostyki. Jeśli widzisz większość max_turns, masz problem z designem. Jeśli widzisz większość end_turn, działasz zdrowo.

Instalacja Python i TypeScript SDK

Python

# Wymaga Python 3.10+
pip install claude-agent-sdk

# Ustaw API key
export ANTHROPIC_API_KEY="sk-ant-..."

# Test
python -c "from claude_agent_sdk import query; print('ok')"

Dla projektów produkcyjnych polecam uv zamiast pip (10× szybszy resolver) lub poetry. Pin wersji w pyproject.toml: claude-agent-sdk = "^0.1".

TypeScript / Node

# Wymaga Node 20+
npm install @anthropic-ai/claude-agent-sdk

# .env
ANTHROPIC_API_KEY=sk-ant-...

# Test
node -e "import('@anthropic-ai/claude-agent-sdk').then(m => console.log('ok'))"

W projekcie TypeScript dodaj "type": "module" w package.json, SDK używa ESM. Dla bundlowania pod Vercel Edge / Cloudflare Workers sprawdź flagi runtime, część SDK wymaga Node API (fs, child_process), niedostępnych w edge.

Twój pierwszy agent

Python, prosty agent z query()

Najmniejszy działający agent w Pythonie to 15 linii. Dostaje cel jako string, agent loop kończy się sam.

# first_agent.py
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions

async def main():
    options = ClaudeAgentOptions(
        model="claude-sonnet-4-6",
        system_prompt="Jesteś asystentem DevOps. Krótkie odpowiedzi, konkretne komendy.",
        max_turns=10,
    )
    prompt = "Wymień 5 komend do diagnostyki wysokiego CPU usage na Linuxie."

    async for message in query(prompt=prompt, options=options):
        if message.type == "text":
            print(message.text)
        elif message.type == "tool_use":
            print(f"[TOOL] {message.name}({message.input})")

asyncio.run(main())

Uruchom: python first_agent.py. Agent wygeneruje listę komend, zakończy się, zamknie proces. Koszt poniżej 0.01 dolara dla pojedynczego wywołania.

TypeScript, prosty agent z query()

// first-agent.ts
import { query } from "@anthropic-ai/claude-agent-sdk";

const options = {
  model: "claude-sonnet-4-6" as const,
  systemPrompt: "Jesteś asystentem DevOps. Krótkie odpowiedzi, konkretne komendy.",
  maxTurns: 10,
};

const prompt = "Wymień 5 komend do diagnostyki wysokiego CPU usage na Linuxie.";

for await (const message of query({ prompt, options })) {
  if (message.type === "text") {
    console.log(message.text);
  } else if (message.type === "tool_use") {
    console.log(`[TOOL] ${message.name}(${JSON.stringify(message.input)})`);
  }
}

Uruchom: npx tsx first-agent.ts. API jest celowo symetryczne do Pythonowego, łatwo portować logikę między językami.

Kurs Claude Code obejmuje Agent SDK

W Kursie Claude Code po polsku dostajesz moduł 7 dedykowany Agent SDK: 30 stron PDF, 3 working projekty (triage issues, autogen docs, monitor produkcji), repo GitHub z pełnym kodem. Plus pozostałe moduły, hooks, MCP servers, slash commands, Anthropic API w produkcji.

Zobacz pełny program kursu →

Definiowanie własnych tools

Tools to interfejs między modelem a światem. Bez tools agent może tylko generować tekst. Z tools agent może wywoływać API, czytać pliki, robić commity, deployować, wysyłać Slacka. SDK ma builtin tools (Bash, Read, Edit, Write, Grep, Glob, WebFetch), ale prawdziwa wartość zaczyna się od własnych.

Python, dekorator @tool

# tools.py
from claude_agent_sdk import tool, query, ClaudeAgentOptions
import httpx

@tool
def get_github_issue(owner: str, repo: str, issue_number: int) -> dict:
    """Pobierz szczegóły issue z GitHuba.

    Use this when user asks about a specific GitHub issue.
    """
    url = f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}"
    response = httpx.get(url, timeout=10.0)
    response.raise_for_status()
    data = response.json()
    return {
        "title": data["title"],
        "body": data["body"],
        "state": data["state"],
        "labels": [l["name"] for l in data["labels"]],
    }

@tool
def post_comment(owner: str, repo: str, issue_number: int, body: str) -> str:
    """Dodaj komentarz do issue na GitHubie.

    Use this when you have a ready-to-post response for a GitHub issue.
    Returns the URL of the created comment.
    """
    # ... auth, POST request ...
    return "https://github.com/.../comments/123"

Dekorator @tool czyta type hints i docstring, generuje JSON Schema automatycznie. Docstring to jedyne, co model widzi przy wyborze narzędzia, więc opisuj kiedy użyć, nie tylko co robi.

Podpięcie tools do agenta

# triage_agent.py
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
from tools import get_github_issue, post_comment

async def main():
    options = ClaudeAgentOptions(
        model="claude-sonnet-4-6",
        tools=[get_github_issue, post_comment],
        system_prompt="Jesteś botem triage. Dla każdego issue oceń priorytet i postaw komentarz.",
        max_turns=15,
    )
    prompt = "Przeprowadź triage issue #42 w repo myorg/myproject."

    async for message in query(prompt=prompt, options=options):
        print(message)

asyncio.run(main())

Cztery zasady dobrego toola

  1. Opisuj kiedy, nie co. "Use this when user asks about X" pokonuje "returns X data". Model wybiera tool na bazie kiedy go potrzebuje, nie co dostanie.
  2. Type hints zamiast docstringów. Python @tool generuje schema z type hints. issue_number: int sprawia, że model nie wyśle stringa, gdzie powinien być integer.
  3. Małe, fokuśne tools. get_issue + add_labels + post_comment bije do_everything_with_issue. Modele lepiej komponują 3 proste tools niż jeden monstrum.
  4. Return strukturalne dane, nie freetext. Dict z polami zamiast tekstu, model parsuje to natywnie, ty łatwiej zlogujesz, łatwiej zwalidujesz.

TypeScript, definicja tools przez schema

// tools.ts
import { z } from "zod";
import { tool } from "@anthropic-ai/claude-agent-sdk";

export const getGithubIssue = tool({
  name: "get_github_issue",
  description: "Pobierz szczegóły issue z GitHuba. Use this when user asks about a specific issue.",
  inputSchema: z.object({
    owner: z.string(),
    repo: z.string(),
    issueNumber: z.number().int().positive(),
  }),
  async execute({ owner, repo, issueNumber }) {
    const res = await fetch(
      `https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}`,
      { headers: { Authorization: `Bearer ${process.env.GH_TOKEN}` } }
    );
    if (!res.ok) throw new Error(`GitHub API ${res.status}`);
    const data = await res.json();
    return {
      title: data.title,
      body: data.body,
      state: data.state,
      labels: data.labels.map((l: { name: string }) => l.name),
    };
  },
});

TypeScript wersja jest bardziej eksplicytna (musisz napisać schema), ale dostajesz pełne typowanie input i output. Zod jest opcjonalny, możesz użyć surowego JSON Schema, jeśli wolisz.

Memory management

Context window Sonnet 4.6 to 200K tokens, około 500-700 stron tekstu. Dla większości agentów jednorazowych to morze. Problem zaczyna się przy agentach długo działających (np. monitor produkcji), gdzie historia rośnie z każdą iteracją.

Trzy warstwy pamięci

  1. Context window, ulotna, ginie z końcem procesu. Domyślne miejsce dla aktualnej sesji.
  2. File-based state, agent zapisuje plan, decyzje, output do plików (np. ./.agent/state.json) i czyta je przy starcie. Idealne dla agentów uruchamianych cyklicznie.
  3. External memory, Postgres, Redis, vector DB. Wstrzykiwane jako tool, agent woła memory_query() i memory_store(). Skaluje się do milionów eventów.

Python, agent z file-based memory

# memory_agent.py
import asyncio
import json
from pathlib import Path
from claude_agent_sdk import query, ClaudeAgentOptions, tool

STATE_FILE = Path(".agent/state.json")

@tool
def load_state() -> dict:
    """Wczytaj poprzedni stan agenta (plan, ostatnie decyzje, todo).
    Use at the start of every session to recover context.
    """
    if not STATE_FILE.exists():
        return {"plan": [], "decisions": [], "todo": []}
    return json.loads(STATE_FILE.read_text())

@tool
def save_state(plan: list, decisions: list, todo: list) -> str:
    """Zapisz aktualny stan agenta do pliku.
    Use at the end of session to preserve state for next run.
    """
    STATE_FILE.parent.mkdir(exist_ok=True)
    STATE_FILE.write_text(json.dumps({
        "plan": plan, "decisions": decisions, "todo": todo
    }, indent=2))
    return f"State saved to {STATE_FILE}"

async def main():
    options = ClaudeAgentOptions(
        model="claude-sonnet-4-6",
        tools=[load_state, save_state],
        system_prompt=(
            "Jesteś długo żyjącym agentem. Zawsze zaczynaj od load_state(), "
            "kończ od save_state(). Trzymaj listę todo zwięzłą."
        ),
        max_turns=20,
    )
    async for msg in query(
        prompt="Kontynuuj pracę nad listą todo.",
        options=options
    ):
        print(msg)

asyncio.run(main())

Ten wzorzec sprawdza się w cronach, GitHub Actions i webhookach. Każde uruchomienie agenta jest tanie (Sonnet + cache), ale agent zachowuje continuity między uruchomieniami przez plik state.

Kiedy używać której warstwy memory

Warstwy pamięci, kiedy stosować
WarstwaCzas życiaSkalaTypowy use case
Context windowSingle session200K tokensJednorazowy agent, refactor, debug
File-based stateTygodnieMBCron, GitHub Action, agent cykliczny
External memory (Postgres)LataGBMulti-tenant agent, audit log, history search
External memory (vector DB)LataGBSemantic recall, RAG, agent zna twoją wiedzę

Real-world stack typowy dla produkcji: context window (default) + file-based state (per project) + Postgres (audit i historia decyzji) + opcjonalnie vector DB (jeśli agent ma "pamiętać" tysiące dokumentów). Każdą warstwę dodajesz, gdy poprzednia przestaje wystarczać, nie z góry "na zapas".

Prompt caching, must-have w produkcji

Każdy turn agent loop re-wysyła cały kontekst do API (system prompt, historia, tool definitions). Bez cachingu płacisz za każdy token, każdy turn. Z cachingiem płacisz 10% za cache hit. Włączasz przez cache_control: {"type": "ephemeral"} na statycznych częściach.

Real numbers z mojej produkcji: agent z 30K system prompt, 20 turn dziennie, bez cache, 4.50 USD/dzień, z cache (75% hit rate), 1.20 USD/dzień. Różnica 3.30 USD/dzień, 100 USD/miesiąc, na jednym agencie.

Multi-step tasks i error handling

Agent rzadko kończy zadanie w jednym kroku. Realne zadania (refactor, deploy, triage) wymagają sekwencji: zrób X, sprawdź czy się udało, jeśli nie, zrób Y. Trzy zasady robust agentów:

Zasada 1, idempotentne tools

Każdy tool powinien móc być wywołany 2 razy bez negatywnych efektów ubocznych. Bad: create_user(email), drugie wywołanie zwraca błąd "user already exists". Good: upsert_user(email), drugie wywołanie zwraca istniejącego użytkownika.

Agent czasem powtarza tool calls (przez confused state, timeout, retry). Idempotencja sprawia, że to nie kończy się katastrofą.

Zasada 2, jasne error messages

# BAD
raise Exception("Failed")

# GOOD
raise Exception(
    "GitHub API rate limit exceeded (5000/hour). "
    "Wait 15 min, or use authenticated request. "
    "Suggestion: switch to MCP github server with token."
)

Model widzi error message i decyduje co dalej. Bad error to agent zgaduje. Good error to agent działa.

Zasada 3, retry z backoffem na poziomie SDK

SDK ma builtin retry dla 429 i 5xx, ale dla własnych tools dodaj exponential backoff:

from tenacity import retry, stop_after_attempt, wait_exponential

@tool
@retry(stop=stop_after_attempt(3), wait=wait_exponential(min=1, max=30))
def call_flaky_api(payload: dict) -> dict:
    """..."""
    return httpx.post("https://api.example.com", json=payload).json()

Zasada 4, observability na poziomie SDK

Bez logowania każdego turn nigdy nie zdebugujesz produkcyjnego agenta. Standardowy minimum:

import logging, json, time
logger = logging.getLogger("agent")

async for message in query(prompt=prompt, options=options):
    logger.info(json.dumps({
        "ts": time.time(),
        "type": message.type,
        "tool_name": getattr(message, "name", None),
        "tokens_in": getattr(message, "input_tokens", None),
        "tokens_out": getattr(message, "output_tokens", None),
        "stop_reason": getattr(message, "stop_reason", None),
    }))

Format JSON lines, jeden message per linia. Łatwo parsujesz jq w terminalu, łatwo ładujesz do Datadog/Grafana. Bez tego pierwszy bug produkcyjny zajmie ci dzień, z tym, 15 minut.

Subagents i parallel execution

Subagent to wywołanie query() wewnątrz innego query(). Trzy najpopularniejsze powody, dla których ich używasz:

  1. Izolacja kontekstu, subagent dostaje 10K tokenów input zamiast 200K, działa szybciej, taniej.
  2. Parallel execution, 3 subagenty równolegle analizują 3 moduły, 3× szybciej niż sekwencyjnie.
  3. Specjalizacja, subagent z dedicated system prompt ("jesteś code reviewerem skupionym na security") daje lepsze odpowiedzi niż generalista.

Python, 3 subagenty równolegle

# parallel_subagents.py
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions

async def analyze_module(module_path: str, focus: str) -> str:
    options = ClaudeAgentOptions(
        model="claude-haiku-4-5",  # tani model do subagentów
        system_prompt=f"Jesteś reviewerem skupionym na: {focus}.",
        max_turns=5,
    )
    output = []
    async for msg in query(
        prompt=f"Przejrzyj {module_path} i zwróć top 3 problemy.",
        options=options
    ):
        if msg.type == "text":
            output.append(msg.text)
    return "\n".join(output)

async def main():
    results = await asyncio.gather(
        analyze_module("src/auth/", "security"),
        analyze_module("src/api/", "performance"),
        analyze_module("src/ui/", "accessibility"),
    )
    for focus, report in zip(["security", "perf", "a11y"], results):
        print(f"\n=== {focus} ===\n{report}")

asyncio.run(main())

3 wywołania równolegle, każde z innym focusem, każde z tańszym modelem (Haiku). Total cost mniejszy niż jedno Opus wywołanie, total time też mniejszy.

Więcej o subagentach w dedykowanym artykule, Claude Code subagents po polsku.

Deployment, cron, GitHub Action, webhook, serverless

GitHub Action, agent triage issues

Najpopularniejszy deployment Agent SDK to GitHub Action uruchamiany na issues.opened. Agent czyta nowy issue, klasyfikuje, dodaje labelki, postuje komentarz z next steps.

# .github/workflows/triage.yml
name: Triage new issues

on:
  issues:
    types: [opened]

jobs:
  triage:
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install claude-agent-sdk httpx
      - name: Run triage agent
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          ISSUE_NUMBER: ${{ github.event.issue.number }}
          ISSUE_TITLE: ${{ github.event.issue.title }}
          ISSUE_BODY: ${{ github.event.issue.body }}
        run: python scripts/triage_agent.py

Workflow uruchamia się przy każdym nowym issue, kontener instaluje SDK, agent czyta env vars i robi swoje. Koszt typowego triage: 0.02-0.05 dolara.

Cron, agent daily summary

Drugi popularny pattern, cron uruchamiający agenta raz dziennie. Klasyczny use case: podsumowanie aktywności w repo, wysłanie do Slacka.

# crontab
0 8 * * * cd /opt/agents && /usr/bin/python daily_summary.py >> /var/log/agent.log 2>&1

Webhook, agent reagujący na eventy

FastAPI / Express endpoint, który odbiera webhook (Linear, Stripe, custom) i odpala agenta inline. Pamiętaj o async + queue, agent może działać minutę, webhook ma 10 sekund na odpowiedź.

# webhook_agent.py (FastAPI)
from fastapi import FastAPI, BackgroundTasks
from claude_agent_sdk import query, ClaudeAgentOptions

app = FastAPI()

async def process_event(payload: dict):
    options = ClaudeAgentOptions(
        model="claude-sonnet-4-6",
        max_turns=10,
    )
    async for msg in query(
        prompt=f"Obsłuż event: {payload}",
        options=options,
    ):
        pass  # log/persist

@app.post("/webhook/linear")
async def linear_webhook(payload: dict, bg: BackgroundTasks):
    bg.add_task(process_event, payload)
    return {"ok": True}  # zwracaj natychmiast, agent leci w tle

Realny anti-pattern: synchronous wywołanie agenta z webhooka. Linear / Stripe retry-ują webhook po 10s timeout, dostajesz duplicate runs.

Serverless, Vercel / Cloudflare Workers

TypeScript SDK działa w Vercel Edge i Cloudflare Workers przy ograniczeniach: brak fs, brak child_process, max execution time (zazwyczaj 30 s). Dobre dla krótkich agentów z 1-3 turn, złe dla długo żyjących z dziesiątkami turn.

TypeScript, agent z MCP integration

// agent-with-mcp.ts
import { query } from "@anthropic-ai/claude-agent-sdk";

const options = {
  model: "claude-sonnet-4-6" as const,
  systemPrompt: "Jesteś asystentem GitHub. Używaj MCP do operacji na repo.",
  maxTurns: 15,
  mcpServers: {
    github: {
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-github"],
      env: { GITHUB_PERSONAL_ACCESS_TOKEN: process.env.GH_TOKEN! },
    },
  },
};

for await (const msg of query({
  prompt: "Wymień 5 ostatnich PRów w myorg/myproject z statusem open.",
  options,
})) {
  console.log(msg);
}

SDK automatycznie podnosi serwer MCP jako subprocess, wystawia jego narzędzia agentowi, sprząta po sobie na końcu. Więcej o MCP w Claude Code MCP Server po polsku.

Koszty i optymalizacja

Cennik Anthropic dla rodziny Claude 4 w maju 2026 (per million tokens):

Ceny modeli Claude 4, maj 2026
Model Input Output Cache write Cache read
Haiku 4.5$1$5$1.25$0.10
Sonnet 4.6$3$15$3.75$0.30
Opus 4.7$15$75$18.75$1.50

Trzy dźwignie kosztów

  1. Model selection, Haiku do prostych klasyfikacji, Sonnet do większości pracy, Opus tylko do najtrudniejszych. 80% agentów obejdzie się Sonnetem.
  2. Prompt caching, włącz na statycznym system prompt i dłuższych tool definitions. Cache read 90% taniej niż input. Realna oszczędność 50-75% na long-running agentach.
  3. Batch API, dla agentów asynchronicznych (nie real-time) Anthropic daje 50% rabatu, jeśli zgodzisz się na 24h opóźnienie. Idealne do nightly jobów.

Anti-pattern, drogie tokeny które łatwo skasować

Cztery najczęstsze powody, dla których agent kosztuje 5× więcej, niż powinien:

  • Brak cache_control na system prompt. Każdy turn re-wysyła 30K tokenów system promptu. Dodaj cache, dostajesz 90% rabat na re-wysyłki.
  • Opus jako default. Opus jest 5× droższy od Sonneta. Większość zadań Sonnet robi tak samo dobrze, tylko trochę wolniej.
  • Pakowanie całej historii do prompta. Agent ma 50 turn historii, każdy turn wysyła 50 turn poprzednich. Trzymaj historię w pliku, agent czyta tylko relevant fragmenty.
  • Brak max_turns, infinite loops potrafią wykręcić 50 USD w godzinę na Opusie. max_turns=20 to default minimum.

Realne koszty z mojej produkcji

  • Agent triage issues, 50 issues/dzień, Sonnet + cache: 0.50-0.80 USD/dzień
  • Agent autogen docs, uruchamiany przy PR, 10 PR/dzień, Sonnet + cache: 0.30-0.60 USD/dzień
  • Agent monitor produkcji, co 5 min, Haiku, 288 iteracji: 0.15-0.30 USD/dzień
  • Agent code reviewer, Opus na każdym PR, 5 PR/dzień: 2.50-4.00 USD/dzień

Suma 4 agentów w typowym setup: 3-6 USD/dzień, około 100-180 USD/miesiąc. Tańsze niż jeden junior developer godzinowo.

Antywzorce, czego unikać

  1. Brak max_turns, agent wpada w pętlę, faktura rośnie. Zawsze ustaw max_turns i timeout na poziomie procesu.
  2. Brak observability, jeśli nie logujesz każdego turn (tool name, input, output, latency), nie zdebugujesz produkcyjnego agenta. Standardowe APM + structured logs.
  3. Zbyt dużo narzędzi, 20+ tools dezorientuje model. 5-10 dobrze opisanych narzędzi pokonuje 30 słabo opisanych.
  4. Tools bez idempotencji, agent powtarza wywołania, dane się duplikują. Każdy mutacyjny tool powinien być idempotentny (UPSERT, nie INSERT).
  5. Brak prompt cachingu, długi system prompt × wiele turn = przepalenie budżetu. Cache statycznych części to default w produkcji.
  6. Pakowanie historii do każdego prompta, kasuje cache, mnoży input tokens. Lepiej trzymać state w plikach albo zewnętrznej pamięci.
  7. Ignorowanie niedeterminizmu, agent czasem zachowuje się inaczej, code expecting deterministic output break. Pisz testy E2E, nie unit assert ścisłych stringów.
  8. Brak fallbacku, jeśli agent nie kończy w 30 min, co się dzieje? Sensowna default: alert + zatrzymanie procesu + log z ostatnim turn.

Checklist przed deployem agenta do produkcji

  • Ustawione max_turns (typowo 10-30)
  • Watchdog timeout na poziomie procesu (15-30 min)
  • Prompt caching włączony na system prompt
  • Każdy tool idempotentny (UPSERT, nie INSERT)
  • Structured logging (JSON lines, tool name, latency, tokens)
  • Error messages w toolach z hint co dalej
  • Sekrety w secrets manager, nie hardcoded
  • Cost alarm w Anthropic dashboardzie (np. 10 USD/dzień)
  • Test smoke w CI przed merge do main
  • Rollback plan, jeśli agent zaczyna robić głupoty

Case study, agent autonomicznie triage GitHub issues

Realny projekt z mojej praktyki. Repo open source, 5-10 nowych issues dziennie, większość to "doesn't work" bez powtarzalnego stepu. Maintainer (ja) spędzał 30-45 min dziennie na odpisywanie z prośbą o more info, repro steps, env details.

Rozwiązanie

GitHub Action uruchamiany na issues.opened. Agent dostaje treść issue, klasyfikuje (bug, feature, question, duplicate), sprawdza, czy ma wszystkie potrzebne info, jeśli nie, postuje template z konkretnymi pytaniami.

System prompt agenta to 200 linii: konwencje labeli w repo, przykłady dobrego i złego issue, link do CONTRIBUTING.md. Tools: get_issue, add_labels, post_comment, search_duplicates.

Anatomia system prompta dla triage agenta

Większość jakości agenta jest w system prompcie. Mój triage prompt ma sześć sekcji:

  1. Persona, "Jesteś botem triage open source repo XYZ. Twoje audytorium to maintainerzy i kontrybutorzy."
  2. Klasyfikacja, lista 5 etykiet (bug, feature, question, duplicate, invalid) z przykładem każdej.
  3. Required info per typ, dla bug: repro steps + env + expected vs actual. Dla feature: motivation + proposed API.
  4. Templates komentarzy, 3 gotowe szablony "missing repro", "looks like duplicate of #X", "thanks, accepting".
  5. Konwencje repo, link do CONTRIBUTING.md, code style, branch naming.
  6. Granice decyzji, "Nigdy nie zamykaj issue. Jeśli niepewny, dodaj label 'needs-maintainer' i poczekaj."

Sekcja 6 jest najważniejsza, definiuje gdzie agent ma się zatrzymać i przekazać sterowanie człowiekowi. Bez niej agent może np. zamknąć legitne issue jako "duplicate" przez błędne rozpoznanie.

Wynik po miesiącu

  • Issues poprawnie sklasyfikowane, 87% bez interwencji człowieka
  • Średni response time, 12 sekund (vs 4-8 godzin przedtem)
  • Czas maintainera zaoszczędzony, ~25 min/dzień, ~12.5h/miesiąc
  • Koszt, 18 USD/miesiąc (200 issues × ~0.09 USD per triage)
  • Ratio, 12.5h pracy maintainera za 18 USD, około 1.5 USD/h

Pełny kod tego agenta (system prompt, tools, workflow YAML, testy) znajdziesz w module 7 Kursu Claude Code po polsku.

Lessons learned z pierwszego miesiąca produkcji

  • System prompt urósł 4× w ciągu miesiąca, każdy edge case dodawał kilka linii. Wersjonuj go w Gicie jak każdy inny kod.
  • Najwięcej błędów dawała klasyfikacja "feature vs question". Dodanie 5 jaskrawych przykładów każdej kategorii poprawiło accuracy o 12 punktów procentowych.
  • Cache hit rate stabilizował się na 72% po tygodniu. Pierwsze dni 30-40%, bo zmieniałeś prompt co kilka godzin.
  • Najgorszy bug, agent zaczął odpowiadać po angielsku, mimo polskiego prompta. Fix: explicit "Always respond in Polish, regardless of issue language."
  • Najlepszy ROI, dodanie tool search_duplicates z fuzzy search. 30% issues to były duplikaty, agent szybko je wyłapywał.

FAQ

Wszystkie pytania, które dostaję od polskich developerów wchodzących w Agent SDK po raz pierwszy, są w widgetach FAQ poniżej i schemach JSON-LD strony. Jeśli czegoś brakuje, napisz na /kontakt/, dorzucę do następnej rewizji.

Co dalej, plan nauki na 14 dni

  1. Dzień 1-2, instalacja SDK (Python lub TS), uruchom pierwszego agenta z query()
  2. Dzień 3-4, dodaj 2 własne tools, przetestuj różne formy docstringów
  3. Dzień 5-7, file-based memory + prompt caching, mierz koszty
  4. Dzień 8-10, deployment do GitHub Action, agent triage issues w twoim repo
  5. Dzień 11-14, subagents i parallel execution, agent code reviewer

Powiązane tutoriale: Claude Code tutorial po polsku, Claude Code hooks po polsku, Claude Code MCP Server po polsku, Claude Code subagents po polsku.

Pełen, uporządkowany program z 3 working projektami dostajesz w Kursie Claude Code po polsku, 220 stron PDF, moduł 7 (Agent SDK) ma 30 stron + repo template. 349 zł brutto, dożywotni dostęp.

Zobacz pełny program kursu →

Chcesz profesjonalnie nauczyć się tworzenia video AI?

6 modułów PDF + społeczność Discord. Dożywotni dostęp.

249 zł 399 zł
Zobacz kurs →