Jak zbudować agenta AI w Pythonie krok po kroku (76 linii kodu)
Buduję agenta AI bez frameworka: pliki, kalkulator, kurs NBP, strona WWW, limit kroków i log. Potem ten sam agent na OpenAI Agents SDK i Claude Agent SDK.

👁 114 przeczytań
- Agent AI w Pythonie to pętla: model dostaje zadanie i narzędzia, wybiera narzędzie, kod je wykonuje, wynik wraca do modelu - cały agent mieści się w 76 liniach kodu.
- Jedno zadanie rozwiązane przez agenta z modelem gpt-5.6-luna przez OpenRouter kosztuje 0,0008-0,0013 USD, a wersja z Claude Haiku 4.5 kosztuje 0,013-0,018 USD.
- Agent ma dwa obowiązkowe bezpieczniki: twardy limit kroków (domyślnie 8) zapobiegający zapętleniu oraz plik agent_log.jsonl zapisujący każdą decyzję modelu.
Agent AI w Pythonie to pętla: model dostaje zadanie i listę narzędzi, wybiera narzędzie, Twój kod je wykonuje, wynik wraca do modelu, a model decyduje, co dalej. Zbudowałem takiego agenta w 76 liniach, bez żadnego frameworka: przeszukuje pliki, liczy, czyta strony WWW, ma limit kroków i zapisuje log decyzji. Potem przepisałem go na OpenAI Agents SDK i Claude Agent SDK. Wszystkie przebiegi poniżej są prawdziwe, z 4 października 2026. To trzeci krok ścieżki Agenci AI od zera.
Stan na 4 października 2026
- Środowisko: Windows 11, Python 3.13,
openai3.24.0,openai-agents0.23.1,claude-agent-sdk0.2.163. - Model:
openai/gpt-5.6-lunaprzez OpenRouter (0,20 USD za milion tokenów wejścia, 1,20 USD za milion wyjścia). Wersja na Claude Agent SDK: Claude Haiku 4.5. - Jedno rozwiązane zadanie kosztowało 0,0008-0,0013 USD (Luna) i 0,013-0,018 USD (Claude Agent SDK z Haiku).
- Cały kod: paczka promptowy-agenci-starter, pliki
02_agent_bez_frameworka.pyi03_agent_openai_sdk.py.
Czym agent różni się od zwykłego skryptu z AI
Zwykły skrypt z AI ma z góry ustalone kroki: „pobierz maila, streść, zapisz”. Model wypełnia tylko jedno okienko. W agencie kolejność kroków wybiera model. Dostaje cel („policz wydatki z faktur”) i narzędzia, a sam ustala, że najpierw przejrzy pliki, potem sprawdzi kurs euro, a na końcu policzy sumę. Szerzej o tym, czym jest agent i gdzie się psuje, piszę w tekście Agent AI: co to jest.
Technicznie agent to function calling zamknięty w pętli. Jeśli nie wiesz, jak model prosi o wywołanie funkcji, przeczytaj najpierw tamten tekst. Tutaj zakładam, że to już jest jasne.
Pętla agenta w czterech ruchach
- Model czyta zadanie i dotychczasową historię.
- Decyzja: albo prosi o narzędzie (z argumentami), albo uznaje, że skończył, i pisze odpowiedź.
- Narzędzie: Twój kod wykonuje funkcję.
- Obserwacja: wynik funkcji trafia do historii i wracamy do punktu 1.
Do tego dwa bezpieczniki, bez których nie puszczam żadnego agenta: limit kroków (żeby nie kręcił się w kółko i nie palił pieniędzy) i log decyzji (żeby po fakcie wiedzieć, co zrobił i dlaczego).
Krok 1: przygotowanie środowiska
- Zainstaluj Pythona 3.11-3.13 ze strony python.org (zaznacz „Add python.exe to PATH”).
- W folderze projektu utwórz środowisko:
python -m venv .venv, potem.venv\Scripts\activate. - Zainstaluj biblioteki:
pip install openai requests beautifulsoup4 python-dotenv. - Załóż klucz na OpenRouter i wpisz go do pliku
.envjakoOPENROUTER_API_KEY=.... Ustaw na kluczu limit kredytów, np. 2 USD. Jak działa OpenRouter i ile kosztuje, opisuje tekst OpenRouter. - Do folderu
dane/fakturywrzuć kilka plików tekstowych. W paczce są trzy fikcyjne faktury: dwie w złotych i jedna na 120 EUR.
Krok 2: narzędzia, czyli zwykłe funkcje
Agent dostaje trzy narzędzia. Każde to zwykła funkcja Pythona, która zwraca tekst:
szukaj_plikowpokazuje pliki .txt z folderudane/. Agent nie widzi nic poza tym folderem;kalkulatorliczy wyrażenia przez modułast(bez niebezpiecznegoeval). Modele nadal mylą się w arytmetyce, więc każę im liczyć narzędziem;czytaj_stronepobiera stronę albo odpowiedź API i obcina ją do 4000 znaków, bo każdy znak wraca do modelu jako płatne tokeny.
Krok 3: cały agent w 76 liniach
"""02 - Agent AI bez frameworka: pętla model -> narzędzie -> obserwacja -> decyzja.
Uruchom: python 02_agent_bez_frameworka.py "Zsumuj kwoty brutto z faktur w folderze dane/faktury."
"""
import ast, json, operator, os, pathlib, sys, time
import requests
from bs4 import BeautifulSoup
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
MODEL, MAX_KROKOW = os.getenv("MODEL", "openai/gpt-5.6-luna"), int(os.getenv("MAX_KROKOW", 8))
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key=os.environ["OPENROUTER_API_KEY"])
KATALOG = pathlib.Path("dane").resolve() # agent widzi tylko ten folder
def szukaj_plikow(fraza: str = "") -> str:
"""Lista plików w dane/ (z zawartością), opcjonalnie tylko te, w których jest fraza."""
wynik = []
for p in sorted(KATALOG.rglob("*.txt")):
tekst = p.read_text(encoding="utf-8")
if fraza.lower() in tekst.lower() or fraza.lower() in p.name.lower():
wynik.append(f"== {p.relative_to(KATALOG)} ==\n{tekst[:1500]}")
return "\n".join(wynik) or "brak plików"
OPS = {ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, ast.USub: operator.neg}
def kalkulator(wyrazenie: str) -> str:
def licz(n):
if isinstance(n, ast.Constant): return n.value
if isinstance(n, ast.BinOp): return OPS[type(n.op)](licz(n.left), licz(n.right))
if isinstance(n, ast.UnaryOp): return OPS[type(n.op)](licz(n.operand))
raise ValueError("tylko liczby i + - * /")
return str(round(licz(ast.parse(wyrazenie, mode="eval").body), 4))
def czytaj_strone(url: str) -> str:
r = requests.get(url, timeout=20, headers={"User-Agent": "promptowy-agenci-starter/1.0"})
tekst = BeautifulSoup(r.text, "html.parser").get_text(" ", strip=True)
return tekst[:4000] # przycinamy: długie strony zjadają tokeny
NARZEDZIA = {"szukaj_plikow": szukaj_plikow, "kalkulator": kalkulator, "czytaj_strone": czytaj_strone}
def opis(nazwa, tekst, param, typ="string"):
return {"type": "function", "function": {"name": nazwa, "description": tekst,
"parameters": {"type": "object", "properties": {param: {"type": typ}}, "required": [param]}}}
TOOLS = [opis("szukaj_plikow", "Pokazuje pliki .txt z folderu dane/ i ich treść. Pusta fraza = wszystkie pliki.", "fraza"),
opis("kalkulator", "Liczy wyrażenie, np. 2214+1180.8. Zawsze licz tym narzędziem.", "wyrazenie"),
opis("czytaj_strone", "Pobiera tekst strony WWW lub odpowiedź API spod adresu URL.", "url")]
def agent(zadanie: str) -> str:
messages = [{"role": "system", "content": "Jesteś agentem. Rozwiąż zadanie, używając narzędzi. Przed każdym "
"narzędziem napisz jednym zdaniem, po co go używasz. Kursy walut bierz z API NBP: "
"https://api.nbp.pl/api/exchangerates/rates/a/{kod}/?format=json. Odpowiadaj po polsku."},
{"role": "user", "content": zadanie}]
log = open("agent_log.jsonl", "a", encoding="utf-8")
koszt = 0.0
for krok in range(1, MAX_KROKOW + 1):
r = client.chat.completions.create(model=MODEL, messages=messages, tools=TOOLS)
koszt += getattr(r.usage, "cost", 0) or 0
msg = r.choices[0].message
messages.append(msg.model_dump(exclude_none=True))
if not msg.tool_calls:
print(f"--- koniec po {krok} krokach, koszt {koszt:.5f} USD")
return msg.content
if msg.content: print(f"[krok {krok}] MYŚL: {msg.content.strip()[:300]}")
for call in msg.tool_calls:
args = json.loads(call.function.arguments or "{}")
try:
obs = NARZEDZIA[call.function.name](**args)
except Exception as e:
obs = f"BŁĄD: {e}"
print(f"[krok {krok}] AKCJA: {call.function.name}({json.dumps(args, ensure_ascii=False)})")
print(f"[krok {krok}] OBSERWACJA: {obs[:160]!r}")
log.write(json.dumps({"t": time.strftime("%H:%M:%S"), "krok": krok, "narzedzie": call.function.name,
"args": args, "obserwacja": obs[:500]}, ensure_ascii=False) + "\n")
messages.append({"role": "tool", "tool_call_id": call.id, "content": obs})
return f"Przerwano: limit {MAX_KROKOW} kroków (koszt {koszt:.5f} USD)."
if __name__ == "__main__":
print("\nWYNIK:\n" + agent(" ".join(sys.argv[1:]) or "Zsumuj kwoty brutto z faktur w folderze dane/faktury."))Najważniejsze miejsca w kodzie:
for krok in range(1, MAX_KROKOW + 1)to pętla agenta z twardym limitem (domyślnie 8);if not msg.tool_calls: model nie prosi o narzędzia, więc to odpowiedź końcowa;- błąd narzędzia nie przerywa programu, tylko wraca do modelu jako obserwacja „BŁĄD: …”. Model zwykle sam się poprawia;
- każde wywołanie trafia do
agent_log.jsonl(czas, krok, narzędzie, argumenty, wynik); - polecenie systemowe każe modelowi napisać jednym zdaniem, po co sięga po narzędzie. To jest „myśl” widoczna w logu i bardzo pomaga w debugowaniu.
Przebieg 1: faktury w dwóch walutach
> python 02_agent_bez_frameworka.py "Policz, ile łącznie wydałem w złotych na faktury z folderu dane. Fakturę w euro przelicz po dzisiejszym kursie NBP."
[krok 1] MYŚL: Najpierw odczytam wszystkie pliki faktur z folderu `dane` oraz pobiorę dzisiejszy kurs EUR z API NBP, aby móc zsumować kwoty w złotych.
[krok 1] AKCJA: szukaj_plikow({"fraza": ""})
[krok 1] OBSERWACJA: '== faktury\\FV_2026_09_014.txt ==\nFAKTURA VAT nr FV/2026/09/014 (dane przykładowe)\nData wystawienia: 2026-09-12\nSprzedawca: Studio Przykładowe Sp. z o.o.\nNabywca'
[krok 1] AKCJA: czytaj_strone({"url": "https://api.nbp.pl/api/exchangerates/rates/a/eur/?format=json"})
[krok 1] OBSERWACJA: '{"table":"A","currency":"euro","code":"EUR","rates":[{"no":"192/A/NBP/2026","effectiveDate":"2026-10-02","mid":4.3745}]}'
[krok 2] MYŚL: Teraz przeliczę fakturę na 120 EUR po kursie 4,3745 PLN/EUR i dodam ją do dwóch faktur opiewających na 2 214,00 zł oraz 1 180,80 zł.
[krok 2] AKCJA: kalkulator({"wyrazenie": "2214+1180.8+120*4.3745"})
[krok 2] OBSERWACJA: '3919.74'
--- koniec po 3 krokach, koszt 0.00104 USD
WYNIK:
Łącznie wydałeś **3 919,74 zł**.
Obliczenie:
- Faktura 1: **2 214,00 zł**
- Faktura 2: **1 180,80 zł**
- Faktura w EUR: 120 × 4,3745 zł = **524,94 zł**
**Suma: 2 214,00 + 1 180,80 + 524,94 = 3 919,74 zł**
Kurs EUR NBP: **4,3745 zł** (z dnia 2026-10-02).Agent sam ustalił plan: w kroku 1 równolegle przeczytał pliki i pobrał kurs euro z API NBP (tabela 192/A/NBP/2026 z 2 października, bo 4 października to niedziela). W kroku 2 policzył wszystko jednym wyrażeniem w kalkulatorze. W kroku 3 napisał odpowiedź. Wynik 3919,74 zł sprawdziłem ręcznie: 2214 + 1180,80 + 120 × 4,3745 = 3919,74. Trzy zapytania do modelu, 0,001 USD.
Przebieg 2: strona WWW plus pliki
> python 02_agent_bez_frameworka.py "Przeczytaj stronę https://pl.wikipedia.org/wiki/Model_Context_Protocol i streść w 3 punktach, do czego służy MCP. Potem sprawdź w folderze dane, czy mam jakąś notatkę z terminem, i podaj ile dni zostało do tego terminu od 4 października 2026."
[krok 1] MYŚL: Przeczytam wskazaną stronę Wikipedii, aby streścić w 3 punktach, do czego służy MCP.
[krok 1] AKCJA: czytaj_strone({"url": "https://pl.wikipedia.org/wiki/Model_Context_Protocol"})
[krok 1] OBSERWACJA: 'Model Context Protocol - Wikipedia, wolna encyklopedia Przejdź do zawartości Menu główne Menu główne przypnij ukryj Nawigacja Strona główna Losuj artykuł Katego'
[krok 2] MYŚL: Przeszukam folder „dane”, aby znaleźć notatkę zawierającą termin.
[krok 2] AKCJA: szukaj_plikow({"fraza": ""})
[krok 2] OBSERWACJA: '== faktury\\FV_2026_09_014.txt ==\nFAKTURA VAT nr FV/2026/09/014 (dane przykładowe)\nData wystawienia: 2026-09-12\nSprzedawca: Studio Przykładowe Sp. z o.o.\nNabywca'
[krok 3] MYŚL: Obliczę różnicę między 4 a 7 października 2026, aby podać dokładną liczbę dni.
[krok 3] AKCJA: kalkulator({"wyrazenie": "7-4"})
[krok 3] OBSERWACJA: '3'
--- koniec po 4 krokach, koszt 0.00130 USD
WYNIK:
**MCP służy do:**
1. Standaryzowania sposobu, w jaki systemy AI, w tym duże modele językowe, łączą się z zewnętrznymi narzędziami, systemami i źródłami danych.
2. Udostępniania modelom uniwersalnego interfejsu do odczytywania plików, wykonywania funkcji i korzystania z kontekstu.
3. Integracji AI z praktycznymi zastosowaniami, takimi jak dokumenty firmowe, systemy CRM, bazy danych oraz środowiska programistyczne.
W pliku `dane/faktury/notatka.txt` znalazłem termin: **wysłać faktury za wrzesień księgowej do 7 października 2026**.
Od **4 października 2026** do tego terminu zostały **3 dni**.Tu agent połączył dwa niezależne źródła. Ciekawostka z logu: początek strony Wikipedii to menu („Przejdź do zawartości, Menu główne…”), a nie treść artykułu. Przy 4000 znakach limitu zostało dość miejsca na właściwy tekst, ale przy dłuższych stronach warto wycinać tylko element <main> albo <article>. Odejmowanie 7 - 4 kalkulatorem wygląda zabawnie, ale tak ma być: model liczy narzędziem, nie w pamięci.
Przebieg 3: agent uderza w limit kroków
Mam to spisane w całości
Zebrałem te rzeczy w ebookach, które możesz pobrać za darmo - bez zapisu na listę, bez haczyka.
Ustawiłem limit na 2 kroki i dołożyłem do zadania przeliczenie na dolary:
> MAX_KROKOW=2 python 02_agent_bez_frameworka.py "Policz, ile łącznie wydałem w złotych na faktury z folderu dane. Fakturę w euro przelicz po dzisiejszym kursie NBP, a potem sprawdź też kurs dolara i podaj sumę w USD."
[krok 1] MYŚL: Najpierw pobieram treść wszystkich plików z folderu `dane` oraz równolegle dzisiejsze kursy EUR i USD z API NBP, aby zidentyfikować kwoty i wykonać przeliczenia.
[krok 1] AKCJA: szukaj_plikow({"fraza": ""})
[krok 1] OBSERWACJA: '== faktury\\FV_2026_09_014.txt ==\nFAKTURA VAT nr FV/2026/09/014 (dane przykładowe)\nData wystawienia: 2026-09-12\nSprzedawca: Studio Przykładowe Sp. z o.o.\nNabywca'
[krok 1] AKCJA: czytaj_strone({"url": "https://api.nbp.pl/api/exchangerates/rates/a/eur/?format=json"})
[krok 1] OBSERWACJA: '{"table":"A","currency":"euro","code":"EUR","rates":[{"no":"192/A/NBP/2026","effectiveDate":"2026-10-02","mid":4.3745}]}'
[krok 1] AKCJA: czytaj_strone({"url": "https://api.nbp.pl/api/exchangerates/rates/a/usd/?format=json"})
[krok 1] OBSERWACJA: '{"table":"A","currency":"dolar amerykański","code":"USD","rates":[{"no":"192/A/NBP/2026","effectiveDate":"2026-10-02","mid":3.8881}]}'
[krok 2] MYŚL: Na podstawie faktur uwzględniam trzy kwoty brutto: 2 214,00 zł, 1 180,80 zł oraz 120 EUR; teraz obliczam wartość faktury euro i łączną sumę w złotych.
[krok 2] AKCJA: kalkulator({"wyrazenie": "2214+1180.80+120*4.3745"})
[krok 2] OBSERWACJA: '3919.74'
WYNIK:
Przerwano: limit 2 kroków (koszt 0.00079 USD).Agent nie zdążył, więc program przerwał pętlę i zwrócił jasny komunikat zamiast kręcić się dalej. W prawdziwym agencie limit ustawiam z zapasem (8-15 kroków), a przy przekroczeniu zapisuję cały stan do logu, żeby można było wznowić. Tak wygląda log decyzji z tego przebiegu:
> type agent_log.jsonl (ostatnie 3 wpisy)
{"t": "13:50:52", "krok": 1, "narzedzie": "czytaj_strone", "args": {"url": "https://api.nbp.pl/api/exchangerates/rates/a/eur/?format=json"}, "obserwacja": "{\"table\":\"A\",\"currency\":\"euro\",\"code\":\"EUR\",\"rates\":[{\"no\":\"192/A/NBP/2026\",\"effectiveDate\":\"2026-10-02\",\"mid\":4.3745}]}"}
{"t": "13:50:52", "krok": 1, "narzedzie": "czytaj_strone", "args": {"url": "https://api.nbp.pl/api/exchangerates/rates/a/usd/?format=json"}, "obserwacja": "{\"table\":\"A\",\"currency\":\"dolar amerykański\",\"code\":\"USD\",\"rates\":[{\"no\":\"192/A/NBP/2026\",\"effectiveDate\":\"2026-10-02\",\"mid\":3.8881}]}"}
{"t": "13:50:56", "krok": 2, "narzedzie": "kalkulator", "args": {"wyrazenie": "2214+1180.80+120*4.3745"}, "obserwacja": "3919.74"}Co się psuje w agentach (i jak to łatać)
| Problem | Jak go zauważysz | Co działa |
|---|---|---|
| Pętla bez końca | te same wywołania w logu kilka razy | limit kroków, wykrywanie powtórzeń argumentów |
| Zbyt długie wyniki narzędzi | rosnący koszt każdego kroku | przycinanie, streszczanie, zwracanie tylko potrzebnych pól |
| Model liczy w pamięci | brak wywołania kalkulatora, dziwne grosze | „zawsze licz narzędziem” w opisie funkcji |
| Prompt injection z treści strony | agent robi coś, o co nie prosiłeś | narzędzia tylko do odczytu, potwierdzenie człowieka przy zapisie |
| Zła interpretacja danych | poprawna arytmetyka na złych liczbach | test na danych, które znasz, zanim dasz prawdziwe |
Ten sam agent na OpenAI Agents SDK
Kiedy rozumiesz pętlę, framework przestaje być magią. OpenAI Agents SDK robi dokładnie to, co moje 76 linii: woła model, wykonuje narzędzia, pilnuje limitu (max_turns), zbiera log. Opis funkcji generuje sam z sygnatury i docstringa (dekorator @function_tool). Działa też z modelami spoza OpenAI, jeśli podasz klienta wskazującego na OpenRouter:
"""03 - Ten sam agent co w 02, ale na OpenAI Agents SDK (pakiet openai-agents).
Pętlę, wywołania narzędzi i limit kroków robi za nas Runner.
Uruchom: python 03_agent_openai_sdk.py "Policz, ile łącznie wydałem na faktury z folderu dane."
"""
import asyncio, os, sys
from dotenv import load_dotenv
from openai import AsyncOpenAI
from agents import Agent, OpenAIChatCompletionsModel, Runner, function_tool, set_tracing_disabled
import importlib
narz = importlib.import_module("02_agent_bez_frameworka") # bierzemy te same funkcje-narzędzia
load_dotenv()
set_tracing_disabled(True) # śledzenie wysyła dane do OpenAI - przy OpenRouterze wyłączamy
model = OpenAIChatCompletionsModel(
model=os.getenv("MODEL", "openai/gpt-5.6-luna"),
openai_client=AsyncOpenAI(base_url="https://openrouter.ai/api/v1", api_key=os.environ["OPENROUTER_API_KEY"]))
@function_tool
def szukaj_plikow(fraza: str = "") -> str:
"""Pokazuje pliki .txt z folderu dane/ i ich treść. Pusta fraza = wszystkie pliki."""
return narz.szukaj_plikow(fraza)
@function_tool
def kalkulator(wyrazenie: str) -> str:
"""Liczy wyrażenie arytmetyczne, np. 2214+1180.8. Zawsze licz tym narzędziem."""
return narz.kalkulator(wyrazenie)
@function_tool
def czytaj_strone(url: str) -> str:
"""Pobiera tekst strony WWW lub odpowiedź API spod adresu URL."""
return narz.czytaj_strone(url)
agent = Agent(
name="Asystent faktur",
instructions="Rozwiąż zadanie narzędziami. Kursy walut: https://api.nbp.pl/api/exchangerates/rates/a/{kod}/?format=json. "
"Odpowiadaj po polsku.",
model=model, tools=[szukaj_plikow, kalkulator, czytaj_strone])
async def main():
zadanie = " ".join(sys.argv[1:]) or "Policz, ile łącznie wydałem w złotych na faktury z folderu dane."
wynik = await Runner.run(agent, zadanie, max_turns=8)
for item in wynik.new_items: # log: co agent zrobił po drodze
if item.type == "tool_call_item":
print("AKCJA:", item.raw_item.name, item.raw_item.arguments)
elif item.type == "tool_call_output_item":
print("OBSERWACJA:", str(item.output)[:120].replace("\n", " "))
u = wynik.context_wrapper.usage
print(f"\nWYNIK:\n{wynik.final_output}\n\nzapytań do modelu: {u.requests}, tokeny: {u.input_tokens} we / {u.output_tokens} wy")
asyncio.run(main())> python 03_agent_openai_sdk.py "Policz, ile łącznie wydałem w złotych na faktury z folderu dane. Fakturę w euro przelicz po dzisiejszym kursie NBP."
AKCJA: szukaj_plikow {"fraza":""}
AKCJA: czytaj_strone {"url":"https://api.nbp.pl/api/exchangerates/rates/a/EUR/?format=json"}
OBSERWACJA: == faktury\FV_2026_09_014.txt == FAKTURA VAT nr FV/2026/09/014 (dane przykładowe) Data wystawienia: 2026-09-12 Sprzedawc
OBSERWACJA: {"table":"A","currency":"euro","code":"EUR","rates":[{"no":"192/A/NBP/2026","effectiveDate":"2026-10-02","mid":4.3745}]}
AKCJA: kalkulator {"wyrazenie":"2214+1180.8"}
AKCJA: kalkulator {"wyrazenie":"120*4.3745"}
AKCJA: kalkulator {"wyrazenie":"2214+1180.8+120*4.3745"}
OBSERWACJA: 3394.8
OBSERWACJA: 524.94
OBSERWACJA: 3919.74
WYNIK:
Łącznie wydałeś **3 919,74 zł**.
Obliczenia:
- Faktury w złotych: 2 214,00 zł + 1 180,80 zł = **3 394,80 zł**
- Faktura w euro: 120 EUR × kurs NBP 4,3745 = **524,94 zł**
- Razem: **3 394,80 zł + 524,94 zł = 3 919,74 zł**
zapytań do modelu: 3, tokeny: 1970 we / 323 wyWynik ten sam, 3 zapytania do modelu, 1970 tokenów wejścia i 323 wyjścia. Dwie rzeczy, które warto wiedzieć:
set_tracing_disabled(True): SDK domyślnie wysyła ślady przebiegów do OpenAI. Przy OpenRouterze bez klucza OpenAI dostałbyś błędy w konsoli, a przy danych firmowych możesz po prostu nie chcieć ich nigdzie wysyłać;OpenAIChatCompletionsModel: SDK domyślnie mówi do API Responses od OpenAI. Inni dostawcy (w tym OpenRouter) obsługują Chat Completions, dlatego owijam klienta tą klasą.
Wersja na Claude Agent SDK
Claude Agent SDK to silnik Claude Code wystawiony jako biblioteka. Ma wbudowane narzędzia do plików i terminala, a własne narzędzia podpinasz jako mały serwer MCP w pamięci. Kod jest w paczce w frameworki/e_claude_agent_sdk.py, a porównanie ze wszystkimi frameworkami w tekście Frameworki agentów AI. Na Windows trafiłem na dwie pułapki:
- SDK uruchamia program
claudejako podproces i odmawia uruchomienia plikuclaude.cmd, który instaluje npm (ze względów bezpieczeństwa). Trzeba wskazaćclaude.exeparametremcli_pathalbo zainstalować Claude Code natywnie; - SDK wczytuje ustawienia z
~/.claude/settings.json. Jeśli masz tam własnyANTHROPIC_BASE_URL, zapytania polecą tam, a nie tam, gdzie wskazujesz w kodzie. Pomagasetting_sources=[].
Z Claude Haiku 4.5 przez OpenRouter zadanie z fakturami zajęło 15-18 sekund i kosztowało 0,013-0,018 USD (3 przebiegi). Moja pętla bez frameworka z tym samym modelem Haiku: 7,1 s i 0,007 USD. Różnica to dodatkowe instrukcje i myślenie, które dokłada silnik Claude Code. Za to dostajesz gotowe narzędzia do plików, uprawnienia, sesje i podagentów.
Kiedy pisać agenta samemu, a kiedy brać SDK
- Sam: do nauki (koniecznie), do prostych agentów z 2-5 narzędziami, kiedy chcesz pełnej kontroli nad każdym tokenem.
- OpenAI Agents SDK: kiedy potrzebujesz przekazywania zadań między agentami (handoffs), zabezpieczeń (guardrails) i śledzenia przebiegów.
- Claude Agent SDK: kiedy agent ma pracować na plikach i w terminalu jak Claude Code.
- LangGraph: kiedy przepływ ma rozgałęzienia, punkty kontrolne i zatwierdzanie przez człowieka.
- Bez kodu: n8n, Make albo Gumloop, jeśli wolisz klikać niż pisać.
Najczęstsze pytania
Czy do zbudowania agenta AI trzeba umieć programować?
Do zrozumienia, jak działa, wystarczy umieć czytać prosty kod. Ten w tekście ma 76 linii i możesz go uruchomić bez zmian. Do budowania bez kodu są n8n i Gumloop.
Ile kosztuje działanie agenta AI?
Zależy od modelu i liczby kroków. Mój agent z tanim modelem płacił 0,001 USD za zadanie. Te same kroki na Claude Haiku kosztowały 0,007-0,018 USD. Na drogich modelach rzędu 5 USD za milion tokenów wejścia koszt rośnie kilkadziesiąt razy. Każdy krok wysyła całą dotychczasową historię, więc koszt rośnie szybciej niż liczba kroków.
Jaki model wybrać do agenta?
Taki, który dobrze obsługuje function calling. Do nauki wystarczy najtańszy model z filtrem „tools” na OpenRouterze. Do zadań z wieloma krokami i niejasnymi danymi lepiej sprawdzają się mocniejsze modele, bo rzadziej gubią plan.
Czy agent może działać na lokalnym modelu?
Tak. Ollama ma API zgodne z OpenAI (http://localhost:11434/v1), więc w kodzie zmieniasz tylko base_url i nazwę modelu. Małe modele lokalne częściej mylą argumenty narzędzi.
Jak sprawić, żeby agent nie zrobił czegoś groźnego?
Dawaj mu tylko narzędzia, których potrzebuje, najlepiej tylko do odczytu. Ograniczaj ścieżki (u mnie tylko folder dane/). Akcje nieodwracalne puszczaj przez potwierdzenie człowieka. Loguj wszystko.
Agent AI po polsku: czy działa tak samo?
Tak. Polecenia, opisy narzędzi i odpowiedzi miałem po polsku, model nie miał z tym problemu. Polskie znaki trzymaj w treści, a w nazwach funkcji używaj liter bez ogonków.
Google · Twoje źródłaPromptowy wyżej w Twoim Google - jednym kliknięciemDodaj do preferowanych źródeł →Źródła i data sprawdzenia
- Anthropic: Building effective agents (sprawdzone 4.10.2026).
- OpenAI Agents SDK, dokumentacja (sprawdzone 4.10.2026).
- Claude Agent SDK, dokumentacja (sprawdzone 4.10.2026).
- Kursy walut: API NBP, tabela A.
- Przebiegi: mój komputer, 4 października 2026, 13:50-13:55.
Cały tydzień w AI, w jednym mailu
Wybrane premiery, narzędzia i analizy. Raz w tygodniu, prosto do skrzynki.
Zapisz się za darmo →
