AI Agents · Pelajaran

Membangun Marketplace Plugin Agen

Toko alat terpusat: menerbitkan, menilai, dan mendistribusikan plugin agen.

Pelajaran 4 dari 413 langkah

Membangun Marketplace Plugin Agen adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.

Apa Itu Pasar Pengaya Agen?

Pasar pengaya adalah registri terpusat tempat pengembang menerbitkan alat yang dapat dibagikan, pengembang lain menemukannya melalui pencarian, dan sistem agen memasangnya secara otomatis. Anggap saja seperti npm untuk alat agen: terbitkan sekali, gunakan di mana saja.

Arsitektur Pasar

Pasar ini memiliki empat layanan utama: Registri (menyimpan metadata pengaya dalam basis data), Penyimpanan (menyimpan arsip pengaya dalam penyimpanan objek), Pencarian (indeks teks lengkap), dan Keamanan (menandatangani dan memverifikasi paket). Semuanya tersedia melalui 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}')

Menerbitkan Pengaya

Titik akhir penerbitan memvalidasi arsip pengaya, memeriksa manifes, memverifikasi identitas penerbit (melalui kunci API), memindai pola yang diketahui berbahaya, menandatangani paket, lalu menyimpannya. Penerbitan bersifat atomik—seluruh pengunggahan berhasil atau tidak ada yang disimpan.

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

Validasi Sisi Server Saat Penerbitan

Server registri memvalidasi setiap pengajuan: manifes dapat diuraikan dan lengkap, versi tersebut belum ada, ukuran arsip tidak melebihi batas, dan pemindaian keamanan dasar berhasil. Server hanya menerima pengunggahan setelah semua pemeriksaan selesai.

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

Penandatanganan dan Verifikasi Paket

Tandatangani setiap paket yang diterbitkan dengan kunci penerbit. Klien memverifikasi tanda tangan sebelum memasang paket untuk memastikan paket tersebut tidak dirusak selama pengiriman atau penyimpanan.

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

Menemukan Pengaya melalui Pencarian

API pencarian menerima kueri teks bebas dan filter tag. API ini mengembalikan hasil yang diurutkan berdasarkan skor berbobot: kecocokan nama persis memiliki peringkat tertinggi, diikuti kecocokan tag, lalu kecocokan kata kunci dalam deskripsi.

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

Memasang Pengaya

Proses pemasangan: unduh arsip, verifikasi tanda tangan, ekstrak ke direktori pengaya, validasi manifes, periksa dependensi, lalu daftarkan ke registri alat lokal. Semua langkah harus berhasil atau pemasangan dibatalkan.

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

Sistem Penilaian dan Ulasan

Sistem penilaian membantu pengembang memilih pengaya berkualitas tinggi. Terapkan penilaian 1–5 bintang dengan ulasan teks opsional. Data penilaian gabungan (mean, jumlah) disimpan dalam registri dan dikembalikan dalam hasil pencarian.

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

Menarik Versi (Menghentikan Penggunaannya)

Jika versi yang telah diterbitkan memiliki bug kritis atau kerentanan keamanan, tarik versi tersebut: tandai sebagai tersembunyi dalam registri agar pemasangan baru tidak dapat menggunakannya, tetapi pemasangan yang sudah ada tetap berfungsi. Cara ini lebih aman daripada menghapusnya, yang akan merusak agen yang sudah ada.

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

Alat CLI Pasar

Antarmuka baris perintah memudahkan penggunaan pasar dari terminal atau pipeline CI. Terapkan perintah marketplace install, marketplace search, marketplace publish, dan 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)

Tata Kelola Pasar

Pasar publik memerlukan aturan tata kelola: penggunaan ruang nama (untuk mencegah pembajakan nama), moderasi konten (tanpa kode berbahaya), pemindaian keamanan (analisis statis saat pengunggahan), dan proses penurunan konten (untuk insiden hukum atau keamanan). Hal-hal ini sama besarnya merupakan persoalan organisasi dan teknis.

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

Uji Pemahaman

Apa perbedaan antara menarik versi pengaya dan menghapusnya?

Rekap: Membangun Pasar Pengaya Agen

Selamat telah menyelesaikan pelajaran ini! Poin-poin penting:

  • Alur penerbitan: validasi arsip → verifikasi tanda tangan → pemindaian → simpan + indeks
  • Penandatanganan paket: tanda tangan HMAC memastikan integritas; klien memverifikasinya sebelum pemasangan
  • Pencarian: pencarian teks lengkap dengan pemfilteran tag dan pengurutan berdasarkan relevansi
  • Pemasangan: unduh → verifikasi → ekstrak → validasi → daftarkan (batalkan jika gagal)
  • Penilaian: 1–5 bintang + ulasan teks yang digabungkan dalam registri
  • Penarikan: sembunyikan dari pemasangan baru tanpa merusak pemasangan yang sudah ada

Kursus terakhir: Jalan Menuju Sistem Otonom.

Gratis untuk memulai

Belajar AI Agents dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
60
Pelajaran
239

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Membangun Marketplace Plugin Agen” gratis?

Ya — teks lengkap “Membangun Marketplace Plugin Agen” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Membangun Marketplace Plugin Agen”?

Toko alat terpusat: menerbitkan, menilai, dan mendistribusikan plugin agen. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Agents?

Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.

Berapa lama pelajaran “Membangun Marketplace Plugin Agen” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?

Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Merancang Alat Agen yang Dapat Dibagikan
  2. Penemuan dan Pendaftaran Plugin
  3. Pemberian Versi dan Kompatibilitas Alat
  4. Membangun Marketplace Plugin Agen
← Kembali ke AI Agents