AI Agents · Lezione

Creazione di un marketplace di plugin per agenti

Store centralizzato degli strumenti: pubblicazione, valutazione e distribuzione dei plugin per agenti.

Lezione 4 di 413 passaggi

Creazione di un marketplace di plugin per agenti è una lezione AI Agents gratuita su CoddyKit. Questa è la lezione 4 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 cos'è un marketplace di plugin per agenti?

Un marketplace di plugin è un registro centralizzato in cui gli sviluppatori pubblicano strumenti condivisibili, altri sviluppatori li trovano effettuando ricerche e i sistemi ad agenti li installano automaticamente. È come npm per gli strumenti degli agenti: pubblichi una volta e utilizzi ovunque.

Architettura del marketplace

Il marketplace dispone di quattro servizi principali: Registro (archivia i metadati dei plugin in un database), Storage (archivia gli archivi dei plugin in un object storage), Ricerca (indice full-text) e Sicurezza (firma e verifica i pacchetti). Tutti sono esposti tramite una REST API.

# Marketplace REST API endpoints:
API_ROUTES = {
    'POST /plugins': 'Publish a new plugin version',
    'GET /plugins': 'List all plugins (paginated)',
    'GET /plugins/search?q=weather': 'Search by keyword',
    'GET /plugins/{name}': 'Get plugin metadata',
    'GET /plugins/{name}/{version}': 'Get specific version metadata',
    'GET /plugins/{name}/{version}/download': 'Download plugin archive',
    'POST /plugins/{name}/{version}/reviews': 'Submit a rating/review',
    'GET /plugins/{name}/reviews': 'Get all reviews',
    'DELETE /plugins/{name}/{version}': 'Yank (hide) a version',
}

for route, description in API_ROUTES.items():
    print(f'{route}: {description}')

Pubblicazione di un plugin

L'endpoint di pubblicazione convalida l'archivio del plugin, verifica il manifest, verifica l'identità del publisher (tramite API key), cerca pattern noti come dannosi, firma il pacchetto e lo archivia. La pubblicazione è atomica: o il caricamento completo riesce, oppure non viene archiviato nulla.

import hashlib
import hmac
import os

def publish_plugin(
    archive_path: str,
    api_key: str,
    registry_url: str = 'https://registry.agenttools.io'
) -> dict:
    import requests

    # Compute checksum for integrity
    with open(archive_path, 'rb') as f:
        data = f.read()
    sha256 = hashlib.sha256(data).hexdigest()

    # Sign the archive with the developer's API key
    signature = hmac.new(
        api_key.encode(), data, hashlib.sha256
    ).hexdigest()

    response = requests.post(
        f'{registry_url}/plugins',
        files={'archive': (os.path.basename(archive_path), data, 'application/zip')},
        headers={
            'X-API-Key': api_key,
            'X-Signature': signature,
            'X-Checksum-SHA256': sha256
        },
        timeout=60
    )
    response.raise_for_status()
    return response.json()

Convalida lato server durante la pubblicazione

Il server del registro convalida ogni invio: il manifest deve essere analizzabile e completo, la versione non deve esistere già, l'archivio non deve superare il limite di dimensione e una scansione di sicurezza di base deve avere esito positivo. Il server accetta il caricamento solo dopo aver completato tutti i controlli.

import zipfile
import io
import json

MAX_ARCHIVE_SIZE_MB = 50

def validate_plugin_archive(archive_bytes: bytes) -> dict:
    errors = []

    # Size check
    size_mb = len(archive_bytes) / 1024 / 1024
    if size_mb > MAX_ARCHIVE_SIZE_MB:
        errors.append(f'Archive too large: {size_mb:.1f}MB (max {MAX_ARCHIVE_SIZE_MB}MB)')
        return {'valid': False, 'errors': errors}

    # Must be a valid zip
    try:
        zf = zipfile.ZipFile(io.BytesIO(archive_bytes))
    except zipfile.BadZipFile:
        errors.append('Not a valid zip archive')
        return {'valid': False, 'errors': errors}

    file_list = zf.namelist()

    # Must contain plugin.json
    if 'plugin.json' not in file_list:
        errors.append('Missing plugin.json in archive root')

    # Basic security scan: no .pyc files, no hidden dirs
    suspicious = [f for f in file_list if f.startswith('.') or '__pycache__' in f]
    if suspicious:
        errors.append(f'Suspicious files: {suspicious[:3]}')

    return {'valid': len(errors) == 0, 'errors': errors, 'files': len(file_list)}

if __name__ == '__main__':
    buf = io.BytesIO()
    with zipfile.ZipFile(buf, 'w') as zf:
        zf.writestr('plugin.json', '{"name": "demo-plugin"}')
    archive_bytes = buf.getvalue()
    print('Validation result:', validate_plugin_archive(archive_bytes))

Firma e verifica dei pacchetti

Firmi ogni pacchetto pubblicato con la chiave del publisher. I client verificano la firma prima dell'installazione, per garantire che il pacchetto non sia stato manomesso durante il trasferimento o nell'archivio.

import hashlib
import hmac

def sign_package(archive_bytes: bytes, secret_key: str) -> str:
    return hmac.new(
        secret_key.encode(), archive_bytes, hashlib.sha256
    ).hexdigest()

def verify_package(
    archive_bytes: bytes,
    signature: str,
    secret_key: str
) -> bool:
    expected = sign_package(archive_bytes, secret_key)
    return hmac.compare_digest(expected, signature)

# Example:
package_data = b'fake plugin archive bytes'
developer_key = 'developer_secret_key_abc123'

sig = sign_package(package_data, developer_key)
print(f'Signature: {sig[:20]}...')

# Verify (registry or installer):
valid = verify_package(package_data, sig, developer_key)
print(f'Signature valid: {valid}')

# Tampered data:
tampered = b'tampered bytes'
print(f'Tampered valid: {verify_package(tampered, sig, developer_key)}')

Ricerca dei plugin

L'API di ricerca accetta query di testo libero e filtri per tag. Restituisce risultati ordinati in base a un punteggio ponderato: la corrispondenza esatta con il nome ha la priorità maggiore, seguita dalle corrispondenze con i tag e poi dalle corrispondenze tra le parole chiave della descrizione.

import requests

def search_marketplace(
    query: str,
    tags: list = None,
    page: int = 0,
    per_page: int = 20,
    registry_url: str = 'https://registry.agenttools.io'
) -> dict:
    params = {
        'q': query,
        'page': page,
        'per_page': per_page
    }
    if tags:
        params['tags'] = ','.join(tags)

    response = requests.get(
        f'{registry_url}/plugins/search',
        params=params,
        timeout=10
    )
    response.raise_for_status()
    return response.json()

# Usage:
results = search_marketplace('weather forecast', tags=['iot', 'weather'])
# {
#   'total': 12,
#   'results': [
#     {'name': 'weather-tools', 'version': '2.1.0', 'score': 0.98, ...},
#     ...
#   ]
# }
print(f'Total results: {results.get("total", 0)}')

Installazione di un plugin

Il processo di installazione prevede: scaricare l'archivio, verificarne la firma, estrarlo nella directory dei plugin, convalidare il manifest, controllare le dipendenze e registrarlo nel registro locale degli strumenti. Tutti i passaggi devono riuscire; in caso contrario, l'installazione viene annullata.

import requests
import zipfile
import io
import shutil
import os

def install_plugin(
    plugin_name: str,
    version: str = 'latest',
    plugins_dir: str = 'plugins',
    registry_url: str = 'https://registry.agenttools.io'
) -> bool:
    # Step 1: Get metadata including expected signature
    meta = requests.get(
        f'{registry_url}/plugins/{plugin_name}/{version}',
        timeout=10
    ).json()

    # Step 2: Download archive
    archive_resp = requests.get(
        meta['download_url'], timeout=60
    )
    archive_bytes = archive_resp.content

    # Step 3: Verify signature
    if not verify_package(archive_bytes, meta['signature'], meta['public_key']):
        print('Signature verification FAILED — aborting install')
        return False

    # Step 4: Extract
    install_path = os.path.join(plugins_dir, plugin_name)
    if os.path.exists(install_path):
        shutil.rmtree(install_path)  # remove old version
    with zipfile.ZipFile(io.BytesIO(archive_bytes)) as zf:
        zf.extractall(install_path)

    print(f'Installed {plugin_name} v{version} to {install_path}')
    return True

Sistema di valutazione e recensioni

Un sistema di valutazione aiuta gli sviluppatori a scegliere plugin di alta qualità. Implementi valutazioni da 1 a 5 stelle con recensioni testuali facoltative. I dati aggregati delle valutazioni (media e conteggio) vengono archiviati nel registro e restituiti nei risultati di ricerca.

import requests

def submit_review(
    plugin_name: str,
    stars: int,
    review_text: str = '',
    api_key: str = '',
    registry_url: str = 'https://registry.agenttools.io'
) -> dict:
    if not 1 <= stars <= 5:
        raise ValueError('Stars must be 1-5')
    payload = {
        'stars': stars,
        'review': review_text[:500]  # truncate to max length
    }
    response = requests.post(
        f'{registry_url}/plugins/{plugin_name}/reviews',
        json=payload,
        headers={'X-API-Key': api_key},
        timeout=10
    )
    response.raise_for_status()
    return response.json()

def get_reviews(plugin_name: str, registry_url: str = 'https://registry.agenttools.io') -> dict:
    response = requests.get(
        f'{registry_url}/plugins/{plugin_name}/reviews',
        timeout=10
    )
    return response.json()

# Example response structure:
# {'average_stars': 4.3, 'total_reviews': 47,
#  'reviews': [{'stars': 5, 'review': 'Works great!', 'date': '...'}]}
print('Review system ready')

Ritiro (deprecazione) di una versione

Se una versione pubblicata contiene un bug critico o una vulnerabilità di sicurezza, la ritiri: la contrassegni come nascosta nel registro, in modo che le nuove installazioni non possano utilizzarla, mentre quelle esistenti continuano a funzionare. È più sicuro che eliminarla, poiché l'eliminazione interromperebbe il funzionamento degli agenti esistenti.

import requests

def yank_version(
    plugin_name: str,
    version: str,
    reason: str,
    api_key: str,
    registry_url: str = 'https://registry.agenttools.io'
) -> dict:
    response = requests.delete(
        f'{registry_url}/plugins/{plugin_name}/{version}',
        json={'reason': reason},
        headers={'X-API-Key': api_key},
        timeout=10
    )
    response.raise_for_status()
    return response.json()

# Yanked versions:
# - Still downloadable by users who have them pinned
# - Not returned in 'latest' queries
# - Search results show a 'yanked' badge with reason
# - Install of yanked version requires explicit --allow-yanked flag

print('Yanking removes a version from new installs without breaking existing ones.')
print('Always provide a reason: "Security vulnerability in API key handling"')

Strumento CLI del marketplace

Un'interfaccia a riga di comando rende il marketplace facile da utilizzare dal terminale o nelle pipeline CI. Implementi i comandi marketplace install, marketplace search, marketplace publish e marketplace list.

import argparse
import sys

def main():
    parser = argparse.ArgumentParser(description='Agent Tool Marketplace CLI')
    subparsers = parser.add_subparsers(dest='command')

    # Search
    search_parser = subparsers.add_parser('search', help='Search plugins')
    search_parser.add_argument('query', help='Search query')
    search_parser.add_argument('--tag', action='append', dest='tags')

    # Install
    install_parser = subparsers.add_parser('install', help='Install a plugin')
    install_parser.add_argument('plugin', help='Plugin name')
    install_parser.add_argument('--version', default='latest')
    install_parser.add_argument('--plugins-dir', default='plugins')

    # Publish
    publish_parser = subparsers.add_parser('publish', help='Publish plugin')
    publish_parser.add_argument('archive', help='Path to .zip archive')
    publish_parser.add_argument('--api-key', required=True)

    args = parser.parse_args()
    if args.command == 'search':
        results = search_marketplace(args.query, tags=args.tags or [])
        for r in results.get('results', []):
            print(f'{r["name"]} v{r["version"]} ({r.get("average_stars", "?")} stars)')
    elif args.command == 'install':
        install_plugin(args.plugin, args.version, args.plugins_dir)
    elif args.command == 'publish':
        result = publish_plugin(args.archive, args.api_key)
        print('Published:', result)

Governance del marketplace

Un marketplace pubblico ha bisogno di regole di governance: gestione dei namespace (per prevenire l'accaparramento dei nomi), moderazione dei contenuti (nessun codice dannoso), scansione di sicurezza (analisi statica durante il caricamento) e una procedura di rimozione (per incidenti legali o di sicurezza). Si tratta di aspetti tanto organizzativi quanto tecnici.

MARKETPLACE_POLICIES = {
    'namespace_policy': (
        'Plugin names must be unique across the registry. '
        'Names are claimed on first publish. '
        'Transfers require proof of original authorship.'
    ),
    'security_scanning': (
        'All uploads are scanned with bandit (Python security linter). '
        'Critical vulnerabilities block publish. '
        'High vulnerabilities generate a warning visible to installers.'
    ),
    'rate_limits': {
        'publish_per_hour': 10,
        'search_per_minute': 60,
        'install_per_minute': 30
    },
    'takedown_process': (
        'Maintainers can yank versions at any time. '
        'Legal/security takedowns processed within 48 hours. '
        'Appeals via security@agenttools.io'
    )
}

for policy, detail in MARKETPLACE_POLICIES.items():
    if isinstance(detail, str):
        print(f'{policy}: {detail[:80]}...')
    else:
        print(f'{policy}: {detail}')

Verifica delle conoscenze

Qual è la differenza tra ritirare una versione di un plugin ed eliminarla?

Riepilogo: creazione di un marketplace di plugin per agenti

Congratulazioni per aver completato questa lezione! Concetti chiave:

  • Pipeline di pubblicazione: convalida dell'archivio → verifica della firma → scansione → archiviazione e indicizzazione
  • Firma dei pacchetti: la firma HMAC garantisce l'integrità; i client la verificano prima dell'installazione
  • Ricerca: ricerca full-text con filtri per tag e ordinamento per rilevanza
  • Installazione: download → verifica → estrazione → convalida → registrazione (annullamento in caso di errore)
  • Valutazioni: da 1 a 5 stelle e recensioni testuali aggregate nel registro
  • Ritiro: nasconde il plugin dalle nuove installazioni senza interrompere quelle esistenti

Corso finale: la strada verso i sistemi autonomi.

Gratis per iniziare

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 «Creazione di un marketplace di plugin per agenti» è gratuita?

Sì — il testo completo di «Creazione di un marketplace di plugin 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 «Creazione di un marketplace di plugin per agenti»?

Store centralizzato degli strumenti: pubblicazione, valutazione e distribuzione dei plugin per agenti. 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 4 di 4.

Quanto tempo richiede la lezione «Creazione di un marketplace di plugin 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

  1. Progettazione di strumenti condivisibili per agenti
  2. Individuazione e registrazione dei plugin
  3. Versionamento e compatibilità degli strumenti
  4. Creazione di un marketplace di plugin per agenti
← Torna a AI Agents