Progettazione di strumenti condivisibili per agenti
Standard per gli schemi degli strumenti, requisiti di documentazione e pacchettizzazione per il riutilizzo.
Progettazione di strumenti condivisibili per agenti è una lezione AI Agents gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Agents, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Agents include 4 lezioni in totale.
Che cosa rende condivisibile uno strumento?
Uno strumento per agenti condivisibile è uno strumento che altri sviluppatori possono integrare nei propri sistemi di agenti senza leggere il codice sorgente. Dispone di uno schema chiaro e leggibile automaticamente, di un README leggibile dagli esseri umani, di codici di errore ben definiti e di un comportamento prevedibile. Lo consideri una libreria, non uno script.
Standard per gli schemi degli strumenti
Ogni strumento condivisibile deve avere uno schema che descriva input, output e metadati. Lo schema è il contratto tra l'autore dello strumento e l'agente che lo utilizza. Lo basi su JSON Schema per ottenere la massima compatibilità con tutti i principali framework per agenti.
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'])
Codici di errore
Definisca un formato standard per le risposte di errore. Ogni strumento dovrebbe restituire la stessa struttura di errore: codice, messaggio e dettagli facoltativi. In questo modo l'agente può gestire gli errori a livello programmatico senza conoscere i dettagli interni dello strumento.
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())Convalida degli input
Convalidi gli input rispetto allo schema prima dell'esecuzione. Utilizzi jsonschema per la convalida automatica. Interrompa subito l'esecuzione con un errore descrittivo invece di lasciare che gli input non validi causino errori criptici in profondità nella logica dello strumento.
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())Esempi d'uso nello schema
Aggiunga esempi concreti allo schema dello strumento. Gli esempi hanno due scopi: aiutano le persone a comprendere rapidamente lo strumento e possono essere inseriti nel contesto dell'agente come dimostrazioni few-shot per migliorare l'accuratezza delle chiamate allo strumento.
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']}")
Limitazione della frequenza negli strumenti
Gli strumenti che chiamano API esterne devono rispettare i limiti di frequenza. Implementi un limitatore della frequenza per ogni strumento utilizzando un token bucket o una finestra scorrevole. Restituisca un errore standard RATE_LIMITED con il numero di secondi da attendere prima di riprovare quando il limite viene superato.
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})Creazione del pacchetto Python
Strutturi lo strumento come un pacchetto Python installabile, in modo che altri sviluppatori possano aggiungerlo ai propri agenti con un singolo comando pip install. Il pacchetto espone una funzione get_tool_definition() e una funzione execute(params) come API pubblica.
# 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()Scrittura del README dello strumento
Un README chiaro è essenziale per favorire l'adozione. Includa: una descrizione delle funzioni dello strumento, il comando di installazione, le chiavi API o le credenziali necessarie, tutti i parametri con tipi e valori predefiniti, tutti i codici di errore e almeno un esempio completo di utilizzo.
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 di uno strumento condivisibile
Uno strumento condivisibile deve avere test automatizzati che coprano: il percorso di esecuzione corretto, ogni codice di errore, i casi limite (stringhe vuote, valori massimi) e il comportamento relativo alla limitazione della frequenza. I test sono documentazione: mostrano esattamente come si comporta lo strumento.
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 allowedFormato compatibile con il function calling di OpenAI
Per garantire la compatibilità con le API native di utilizzo degli strumenti di OpenAI e Claude, verifichi che lo schema dello strumento sia nel formato esatto previsto da queste API. Il metodo get_openai_schema() converte lo schema interno nel formato compatibile con 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'])Versionamento dello strumento
Utilizzi il versionamento semantico: MAJOR.MINOR.PATCH. Incrementi MAJOR in caso di modifiche incompatibili allo schema, MINOR quando aggiunge parametri facoltativi e PATCH per le correzioni di bug. Memorizzi la versione nello schema ed esponga la versione tramite 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.1Verifica delle conoscenze
Quale parte dello schema di uno strumento condivisibile consente al framework dell'agente di convalidare automaticamente gli input prima di chiamare la funzione di esecuzione dello strumento?
Riepilogo: progettazione di strumenti per agenti condivisibili
Punti chiave di questa lezione:
- Schema: nome, descrizione, versione, parametri (JSON Schema), valori restituiti, rate_limit
- Codici di errore: ToolError standard con code, message e details
- Convalida degli input: jsonschema convalida gli input rispetto allo schema dei parametri prima dell'esecuzione
- Esempi: inclusi nello schema come contesto few-shot
- Limitazione della frequenza: finestra scorrevole con errore RATE_LIMITED e retry_after
- Creazione del pacchetto: pacchetto installabile con pip, README, test e versionamento
Prossimo argomento: individuazione dei plugin e caricamento dinamico degli strumenti.
Impara AI Agents con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 60
- Lezioni
- 239
Domande Frequenti
La lezione «Progettazione di strumenti condivisibili per agenti» è gratuita?
Sì — il testo completo di «Progettazione di strumenti condivisibili per agenti» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Agents, passa a CoddyKit PRO. Il corso AI Agents include 4 lezioni in totale.
Cosa imparerò in «Progettazione di strumenti condivisibili per agenti»?
Standard per gli schemi degli strumenti, requisiti di documentazione e pacchettizzazione per il riutilizzo. Eserciti AI Agents con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Agents?
Non è richiesta alcuna esperienza precedente. AI Agents su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «Progettazione di strumenti condivisibili per agenti»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Agents?
Sì. Ogni lezione AI Agents include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Progettazione di strumenti condivisibili per agenti
- Individuazione e registrazione dei plugin
- Versionamento e compatibilità degli strumenti
- Creazione di un marketplace di plugin per agenti