AI-agenter · Lektion

Design af delbare agentværktøjer

Standarder for tool-schemas, dokumentationskrav og pakning til genbrug.

Lektion 1 af 413 trin

Design af delbare agentværktøjer er en gratis AI-agenter-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i AI-agenter, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. AI-agenter-kurset indeholder 4 lektioner i alt.

Hvad gør et værktøj delbart

Et agentværktøj, der kan deles, er et værktøj, som andre udviklere kan føje til deres agentsystemer uden at læse kildekoden. Det har et tydeligt, maskinlæsbart skema, en README, der er let at forstå, veldefinerede fejlkoder og forudsigelig adfærd. Tænk på det som et bibliotek, ikke som et script.

Standarder for værktøjsskemaer

Alle værktøjer, der kan deles, skal have et skema, der beskriver deres inddata, uddata og metadata. Skemaet er kontrakten mellem værktøjets udvikler og den agent, der bruger det. Basér det på JSON Schema for at opnå størst mulig kompatibilitet med alle større agentrammer.

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'])

Fejlkoder

Definér et standardformat for fejlbeskeder. Alle værktøjer bør returnere den samme fejlstruktur: kode, meddelelse og valgfri detaljer. Det gør det muligt for agenten at håndtere fejl programmatisk uden at kende værktøjets interne implementering.

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())

Validering af inddata

Validér inddata mod skemaet før udførelsen. Brug jsonschema til automatisk validering. Afslut hurtigt med en beskrivende fejl i stedet for at lade ugyldige inddata føre til uforståelige fejl dybt inde i værktøjslogikken.

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())

Anvendelseseksempler i skemaet

Føj konkrete eksempler til værktøjsskemaet. Eksempler har to formål: De hjælper mennesker med hurtigt at forstå værktøjet, og de kan indsættes i agentens kontekst som few-shot-eksempler for at forbedre nøjagtigheden af værktøjskald.

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']}")

Hastighedsbegrænsning i værktøjer

Værktøjer, der kalder eksterne API'er, skal overholde hastighedsbegrænsninger. Implementér en hastighedsbegrænser pr. værktøj ved hjælp af en token bucket eller et glidende vindue. Returnér en standardfejl med RATE_LIMITED og antallet af sekunder, der skal ventes før et nyt forsøg, når grænsen overskrides.

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})

Pakning som en Python-pakke

Strukturér dit værktøj som en Python-pakke, der kan installeres, så andre udviklere kan føje det til deres agenter med en enkelt pip install. Pakken eksponerer funktionerne get_tool_definition() og execute(params) som den offentlige 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()

Skrivning af værktøjets README

En tydelig README er afgørende for udbredelsen. Medtag: hvad værktøjet gør, installationskommandoen, nødvendige API-nøgler eller legitimationsoplysninger, alle parametre med typer og standardværdier, alle fejlkoder samt mindst ét komplet anvendelseseksempel.

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])

Test af et værktøj, der kan deles

Et værktøj, der kan deles, skal have automatiserede test, der dækker det normale succesforløb, hver fejlkode, kanttilfælde (tomme strenge, maksimumsværdier) og adfærden ved hastighedsbegrænsning. Test er dokumentation — de viser præcis, hvordan værktøjet fungerer.

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 kompatibelt med OpenAIs funktionskald

For at sikre kompatibilitet med OpenAIs og Claudes indbyggede API'er til værktøjsbrug skal du sikre, at værktøjsskemaet har præcis det format, som disse API'er forventer. Metoden get_openai_schema() konverterer dit interne skema til det OpenAI-kompatible format.

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'])

Versionsstyring af dit værktøj

Brug semantisk versionsstyring: MAJOR.MINOR.PATCH. Forøg MAJOR ved ændringer, der bryder kompatibiliteten, MINOR ved tilføjelse af valgfrie parametre og PATCH ved fejlrettelser. Gem versionen i skemaet, og eksponér den via 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

Videnstjek

Hvilken del af et skema gør det muligt for agentrammen automatisk at validere inddata, før værktøjets udførelsesfunktion kaldes?

Opsummering: Design af agentværktøjer, der kan deles

Vigtigste pointer fra lektionen:

  • Skema: navn, beskrivelse, version, parametre (JSON Schema), returværdier, rate_limit
  • Fejlkoder: standardiseret ToolError med code, message, details
  • Validering af inddata: jsonschema validerer mod parameters-skemaet før udførelsen
  • Eksempler: inkluderet i skemaet som few-shot-kontekst
  • Hastighedsbegrænsning: glidende vindue med RATE_LIMITED-fejl og retry_after
  • Pakning: pip-installerbar pakke med README, test og versionsstyring

Næste emne: plugin-registrering og dynamisk indlæsning af værktøjer.

Gratis at komme i gang

Lær AI-agenter med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
60
Lektioner
239

Ofte stillede spørgsmål

Er lektionen “Design af delbare agentværktøjer” gratis?

Ja — hele teksten til “Design af delbare agentværktøjer” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af AI-agenter-kurset, skal du opgradere til CoddyKit PRO. AI-agenter-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Design af delbare agentværktøjer”?

Standarder for tool-schemas, dokumentationskrav og pakning til genbrug. Du øver dig i AI-agenter med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på AI-agenter?

Der kræves ingen tidligere erfaring. AI-agenter på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.

Hvor lang tid tager lektionen “Design af delbare agentværktøjer”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne AI-agenter-lektion?

Ja. Alle AI-agenter-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Design af delbare agentværktøjer
  2. Opdagelse og registrering af plugins
  3. Versionering og kompatibilitet for værktøjer
  4. Opbygning af en markedsplads for agentplugins
← Tilbage til AI-agenter