0Pricing
AI Agents · Lekcja

Projektowanie narzędzi agentów do udostępniania

Standardy schematów narzędzi, wymagania dotyczące dokumentacji i pakowanie do ponownego użycia.

Projektowanie narzędzi agentów do udostępniania to bezpłatna lekcja AI Agents na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Agents, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Agents zawiera 4 lekcji w sumie.

Co sprawia, że narzędzie można udostępniać?

Narzędzie agenta, które można udostępniać, to takie, które inni programiści mogą dodać do swoich systemów agentowych bez czytania kodu źródłowego. Ma jasny, przeznaczony dla maszyn schemat, czytelny dla człowieka plik README, dobrze zdefiniowane kody błędów i przewidywalne działanie. Należy traktować je jak bibliotekę, a nie skrypt.

Standardy schematów narzędzi

Każde narzędzie przeznaczone do udostępniania musi mieć schemat opisujący jego dane wejściowe, dane wyjściowe i metadane. Schemat jest kontraktem między autorem narzędzia a agentem, który z niego korzysta. Należy oprzeć go na JSON Schema, aby zapewnić maksymalną zgodność ze wszystkimi głównymi frameworkami agentowymi.

TOOL_SCHEMA_TEMPLATE = {
    'name': 'get_weather',
    'description': 'Returns current weather conditions for a city. '
                   'Use when the user asks about weather or temperature.',
    'version': '1.2.0',
    'parameters': {
        'type': 'object',
        'properties': {
            'city': {
                'type': 'string',
                'description': 'City name (e.g., London, Tokyo)',
                'minLength': 1,
                'maxLength': 100
            },
            'units': {
                'type': 'string',
                'enum': ['celsius', 'fahrenheit'],
                'default': 'celsius',
                'description': 'Temperature unit'
            }
        },
        'required': ['city']
    },
    'returns': {
        'type': 'object',
        'properties': {
            'temperature': {'type': 'number'},
            'condition': {'type': 'string'},
            'humidity_pct': {'type': 'number'}
        }
    },
    'rate_limit': {'calls_per_minute': 60}
}

if __name__ == '__main__':
    print(f"Tool: {TOOL_SCHEMA_TEMPLATE['name']} (v{TOOL_SCHEMA_TEMPLATE['version']})")
    print('Description:', TOOL_SCHEMA_TEMPLATE['description'])
    print('Required params:', TOOL_SCHEMA_TEMPLATE['parameters']['required'])

Kody błędów

Należy zdefiniować standardowy format odpowiedzi z błędem. Każde narzędzie powinno zwracać tę samą strukturę błędu: kod, komunikat i opcjonalne szczegóły. Dzięki temu agent może programowo obsługiwać błędy bez znajomości wewnętrznego działania narzędzia.

from enum import Enum

class ToolErrorCode(Enum):
    INVALID_PARAMS = 'INVALID_PARAMS'
    NOT_FOUND = 'NOT_FOUND'
    RATE_LIMITED = 'RATE_LIMITED'
    UPSTREAM_ERROR = 'UPSTREAM_ERROR'
    TIMEOUT = 'TIMEOUT'
    UNAUTHORISED = 'UNAUTHORISED'
    INTERNAL_ERROR = 'INTERNAL_ERROR'

class ToolError(Exception):
    def __init__(self, code: ToolErrorCode, message: str, details: dict = None):
        self.code = code
        self.message = message
        self.details = details or {}

    def to_dict(self) -> dict:
        return {
            'error': True,
            'code': self.code.value,
            'message': self.message,
            'details': self.details
        }

try:
    raise ToolError(
        ToolErrorCode.NOT_FOUND,
        'City not found in database',
        {'city': 'Atlantis', 'suggestion': 'Did you mean Athens?'}
    )
except ToolError as e:
    print(e.to_dict())

Walidacja danych wejściowych

Dane wejściowe należy zwalidować względem schematu przed wykonaniem. Do automatycznej walidacji należy użyć jsonschema. Należy szybko zgłosić opisowy błąd, zamiast pozwolić, aby nieprawidłowe dane wejściowe powodowały niejasne awarie głęboko w logice narzędzia.

import jsonschema  # pip install jsonschema

def validate_tool_input(params: dict, schema: dict) -> dict:
    """
    Validate params against schema.
    Returns validated (and default-filled) params.
    Raises ToolError on validation failure.
    """
    try:
        # Fill in defaults
        filled = dict(params)
        for prop, definition in schema['properties'].items():
            if prop not in filled and 'default' in definition:
                filled[prop] = definition['default']

        # Validate against schema
        jsonschema.validate(instance=filled, schema=schema)
        return filled

    except jsonschema.ValidationError as e:
        raise ToolError(
            ToolErrorCode.INVALID_PARAMS,
            f'Validation failed: {e.message}',
            {'path': list(e.path), 'schema_path': list(e.schema_path)}
        )

# Example usage:
try:
    params = validate_tool_input({'city': 'London'}, TOOL_SCHEMA_TEMPLATE['parameters'])
    print('Valid params:', params)
except ToolError as e:
    print('Error:', e.to_dict())

Przykłady użycia w schemacie

Do schematu narzędzia należy dodać konkretne przykłady. Przykłady mają dwa zastosowania: pomagają ludziom szybko zrozumieć działanie narzędzia i mogą zostać wstrzyknięte do kontekstu agenta jako demonstracje few-shot, aby poprawić dokładność wywoływania narzędzi.

TOOL_WITH_EXAMPLES = {
    'name': 'search_knowledge_base',
    'description': 'Search the company knowledge base for documentation.',
    'parameters': {
        'type': 'object',
        'properties': {
            'query': {'type': 'string'},
            'top_k': {'type': 'integer', 'default': 5, 'minimum': 1, 'maximum': 20}
        },
        'required': ['query']
    },
    'examples': [
        {
            'description': 'Search for onboarding docs',
            'input': {'query': 'how to onboard new users', 'top_k': 3},
            'output': {'results': [{'title': 'User Onboarding Guide', 'score': 0.95}]}
        },
        {
            'description': 'Search with default top_k',
            'input': {'query': 'API authentication'},
            'output': {'results': [{'title': 'API Auth Docs', 'score': 0.88}]}
        }
    ]
}

if __name__ == '__main__':
    print('Tool:', TOOL_WITH_EXAMPLES['name'])
    for ex in TOOL_WITH_EXAMPLES['examples']:
        print(f" - {ex['description']}: input={ex['input']} -> output={ex['output']}")

Ograniczanie liczby żądań w narzędziach

Narzędzia wywołujące zewnętrzne interfejsy API muszą przestrzegać limitów liczby żądań. Należy zaimplementować ogranicznik liczby żądań dla każdego narzędzia, wykorzystując kubełek tokenów lub okno przesuwne. Po przekroczeniu limitu należy zwrócić standardowy błąd RATE_LIMITED z liczbą sekund do ponowienia żądania.

import time
from collections import deque

class SlidingWindowRateLimiter:
    def __init__(self, max_calls: int, window_seconds: int):
        self.max_calls = max_calls
        self.window = window_seconds
        self._calls = deque()  # timestamps of recent calls

    def check(self) -> tuple:
        """
        Returns (allowed: bool, retry_after_seconds: float)
        """
        now = time.time()
        # Remove calls outside the window
        while self._calls and self._calls[0] < now - self.window:
            self._calls.popleft()

        if len(self._calls) >= self.max_calls:
            oldest = self._calls[0]
            retry_after = (oldest + self.window) - now
            return False, round(retry_after, 1)

        self._calls.append(now)
        return True, 0.0

weather_limiter = SlidingWindowRateLimiter(max_calls=10, window_seconds=60)
allowed, retry = weather_limiter.check()
if not allowed:
    raise ToolError(ToolErrorCode.RATE_LIMITED,
                    f'Rate limit exceeded. Retry in {retry}s',
                    {'retry_after': retry})

Pakowanie jako pakiet Python

Należy zorganizować narzędzie jako instalowalny pakiet Python, aby inni programiści mogli dodać je do swoich agentów za pomocą pojedynczego polecenia pip install. Pakiet udostępnia funkcję get_tool_definition() oraz funkcję execute(params) jako publiczny interfejs API.

# Directory structure:
# agent_tool_weather/
#   __init__.py
#   tool.py
#   schema.py
#   pyproject.toml
#   README.md

# agent_tool_weather/tool.py
from .schema import SCHEMA
from .errors import ToolError, ToolErrorCode

def get_tool_definition() -> dict:
    return SCHEMA

def execute(params: dict) -> dict:
    validated = validate_tool_input(params, SCHEMA['parameters'])
    city = validated['city']
    units = validated['units']
    return _fetch_weather(city, units)

def _fetch_weather(city: str, units: str) -> dict:
    import requests
    url = f'https://api.weather.example.com/current?city={city}&units={units}'
    response = requests.get(url, headers={'X-API-Key': 'YOUR_KEY'}, timeout=5)
    if response.status_code == 404:
        raise ToolError(ToolErrorCode.NOT_FOUND, f'City not found: {city}')
    response.raise_for_status()
    return response.json()

Pisanie pliku README narzędzia

Jasny plik README ma kluczowe znaczenie dla rozpowszechnienia narzędzia. Należy uwzględnić: opis działania narzędzia, polecenie instalacji, wymagane klucze API lub dane uwierzytelniające, wszystkie parametry wraz z typami i wartościami domyślnymi, wszystkie kody błędów oraz co najmniej jeden kompletny przykład użycia.

README_TEMPLATE = '''
# agent-tool-weather

Get real-time weather conditions for any city.

## Installation

pip install agent-tool-weather

## Setup

import os
os.environ["WEATHER_API_KEY"] = "your-key-here"

## Usage

from agent_tool_weather import get_tool_definition, execute

# In your agent
tool_def = get_tool_definition()

# Execute
result = execute({"city": "Tokyo", "units": "celsius"})
print(result)
# {"temperature": 22.5, "condition": "Partly cloudy", "humidity_pct": 65}

## Parameters

| Name  | Type   | Required | Default  | Description     |
|-------|--------|----------|----------|-----------------|
| city  | string | Yes      | -        | City name       |
| units | string | No       | celsius  | celsius or fahrenheit |

## Error Codes

- INVALID_PARAMS: Parameter validation failed
- NOT_FOUND: City not found
- RATE_LIMITED: 60 calls/minute limit exceeded
- UPSTREAM_ERROR: Weather API unavailable
'''

print(README_TEMPLATE[:300])

Testowanie narzędzia przeznaczonego do udostępniania

Narzędzie przeznaczone do udostępniania musi mieć automatyczne testy obejmujące: poprawny przebieg, każdy kod błędu, przypadki brzegowe (puste ciągi znaków, wartości maksymalne) oraz działanie ograniczania liczby żądań. Testy są dokumentacją — dokładnie pokazują, jak zachowuje się narzędzie.

import pytest

def test_valid_city_returns_weather(mock_weather_api):
    result = execute({'city': 'London'})
    assert 'temperature' in result
    assert 'condition' in result
    assert isinstance(result['temperature'], (int, float))

def test_missing_required_param_raises_error():
    with pytest.raises(ToolError) as exc_info:
        execute({})  # city is required
    assert exc_info.value.code == ToolErrorCode.INVALID_PARAMS

def test_unknown_city_raises_not_found(mock_weather_api_404):
    with pytest.raises(ToolError) as exc_info:
        execute({'city': 'Atlantis'})
    assert exc_info.value.code == ToolErrorCode.NOT_FOUND

def test_default_units_is_celsius():
    params = validate_tool_input({'city': 'Paris'}, TOOL_SCHEMA_TEMPLATE['parameters'])
    assert params['units'] == 'celsius'

def test_rate_limit_enforced():
    limiter = SlidingWindowRateLimiter(max_calls=2, window_seconds=60)
    limiter.check()  # call 1
    limiter.check()  # call 2
    allowed, _ = limiter.check()  # call 3 — should fail
    assert not allowed

Format zgodny z wywoływaniem funkcji OpenAI

Aby zapewnić zgodność z natywnymi interfejsami API OpenAI i Claude do korzystania z narzędzi, należy upewnić się, że schemat narzędzia ma dokładnie format oczekiwany przez te interfejsy API. Metoda get_openai_schema() konwertuje wewnętrzny schemat na format zgodny z OpenAI.

def get_openai_schema(tool_schema: dict) -> dict:
    """Convert internal tool schema to OpenAI function-calling format."""
    return {
        'type': 'function',
        'function': {
            'name': tool_schema['name'],
            'description': tool_schema['description'],
            'parameters': tool_schema['parameters']
        }
    }

def get_anthropic_schema(tool_schema: dict) -> dict:
    """Convert to Anthropic tool format."""
    return {
        'name': tool_schema['name'],
        'description': tool_schema['description'],
        'input_schema': tool_schema['parameters']
    }

# Usage in an agent:
openai_tools = [get_openai_schema(t) for t in [TOOL_SCHEMA_TEMPLATE]]
anthropic_tools = [get_anthropic_schema(t) for t in [TOOL_SCHEMA_TEMPLATE]]
print('OpenAI format:', openai_tools[0]['function']['name'])
print('Anthropic format:', anthropic_tools[0]['name'])

Wersjonowanie narzędzia

Należy stosować wersjonowanie semantyczne: MAJOR.MINOR.PATCH. Wersję MAJOR należy zwiększać przy zmianach powodujących niezgodność schematu, MINOR przy dodawaniu opcjonalnych parametrów, a PATCH przy poprawkach błędów. Wersję należy przechowywać w schemacie i udostępniać za pomocą get_tool_definition().

VERSION = '1.2.0'

def bump_version(current: str, change_type: str) -> str:
    parts = list(map(int, current.split('.')))
    if change_type == 'major':
        return f'{parts[0]+1}.0.0'
    if change_type == 'minor':
        return f'{parts[0]}.{parts[1]+1}.0'
    if change_type == 'patch':
        return f'{parts[0]}.{parts[1]}.{parts[2]+1}'
    raise ValueError(f'Unknown change_type: {change_type}')

# Breaking change (removed required param) -> major
print(bump_version('1.2.0', 'major'))  # 2.0.0
# Added optional param -> minor
print(bump_version('1.2.0', 'minor'))  # 1.3.0
# Bug fix -> patch
print(bump_version('1.2.0', 'patch'))  # 1.2.1

Sprawdzenie wiedzy

Jaki element schematu narzędzia przeznaczonego do udostępniania pozwala frameworkowi agentowemu automatycznie zwalidować dane wejściowe przed wywołaniem funkcji wykonującej narzędzie?

Podsumowanie: projektowanie narzędzi agentowych przeznaczonych do udostępniania

Najważniejsze informacje z tej lekcji:

  • Schemat: nazwa, opis, wersja, parametry (JSON Schema), zwracane wartości, rate_limit
  • Kody błędów: standardowy ToolError z polami code, message i details
  • Walidacja danych wejściowych: jsonschema sprawdza dane względem schematu parametrów przed wykonaniem
  • Przykłady: uwzględnione w schemacie jako kontekst few-shot
  • Ograniczanie liczby żądań: okno przesuwne z błędem RATE_LIMITED i wartością retry_after
  • Pakowanie: pakiet instalowany za pomocą pip, zawierający README, testy i informacje o wersjonowaniu

Następny temat: wykrywanie wtyczek i dynamiczne ładowanie narzędzi.

Często zadawane pytania

Czy lekcja „Projektowanie narzędzi agentów do udostępniania” jest bezpłatna?

Tak — pełny tekst „Projektowanie narzędzi agentów do udostępniania” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Agents, przejdź na CoddyKit PRO. Kurs AI Agents zawiera 4 lekcji w sumie.

Co nauczysz się w „Projektowanie narzędzi agentów do udostępniania”?

Standardy schematów narzędzi, wymagania dotyczące dokumentacji i pakowanie do ponownego użycia. Ćwiczysz AI Agents z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć AI Agents?

Nie wymagamy żadnego doświadczenia. AI Agents w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Projektowanie narzędzi agentów do udostępniania”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji AI Agents?

Tak. Każda lekcja AI Agents zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Projektowanie narzędzi agentów do udostępniania
  2. Wykrywanie i rejestrowanie wtyczek
  3. Wersjonowanie narzędzi i zgodność
  4. Budowanie marketplace’u wtyczek agentów
← Powrót do AI Agents