Sebelum memulai praktik, pastikan Anda telah memahami konsep dasar pada materi kelas AI Agent & PHP di infokoding.

BAB 14

Tool REST API Eksternal

Membangun tool REST API untuk AI Agent PHP: mengintegrasikan berbagai API eksternal seperti GitHub API, Currency API, dan Weather API dengan client HTTP yang robust.

Terakhir diperbarui:

TL;DR (Ringkasan Cepat)

  • Buat HttpClient helper class yang reusable untuk semua API tools.
  • Simpan semua API Key di .env, jangan hardcode.
  • Implementasikan timeout dan retry logic untuk menangani kegagalan jaringan.
  • Cache respons API yang tidak sering berubah untuk menghemat kuota API.

HttpClient Helper

<?php

namespace App\Http;

class HttpClient
{
    private int $timeout;
    private array $defaultHeaders;

    public function __construct(int $timeout = 15, array $defaultHeaders = [])
    {
        $this->timeout        = $timeout;
        $this->defaultHeaders = $defaultHeaders;
    }

    public function get(string $url, array $params = [], array $headers = []): array
    {
        if (!empty($params)) {
            $url .= '?' . http_build_query($params);
        }

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER     => $this->mergeHeaders($headers),
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_TIMEOUT        => $this->timeout,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS      => 3,
        ]);

        $body     = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error    = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new \RuntimeException("HTTP Error: $error");
        }

        return [
            'status' => $httpCode,
            'body'   => json_decode($body, true) ?? $body,
            'ok'     => $httpCode >= 200 && $httpCode < 300,
        ];
    }

    private function mergeHeaders(array $extra): array
    {
        $headers = array_merge($this->defaultHeaders, $extra);
        return array_map(fn($k, $v) => "$k: $v", array_keys($headers), $headers);
    }
}

Tool GitHub API

<?php

namespace App\Tools;

use App\Http\HttpClient;

class GitHubTool implements ToolInterface
{
    private HttpClient $http;
    private string $token;

    public function __construct(string $githubToken = '')
    {
        $this->token = $githubToken;
        $this->http  = new HttpClient(timeout: 10, defaultHeaders: [
            'Accept'        => 'application/vnd.github.v3+json',
            'Authorization' => $githubToken ? "token $githubToken" : '',
            'User-Agent'    => 'PHP-AI-Agent/1.0',
        ]);
    }

    public function getDefinition(): array
    {
        return [
            'type'     => 'function',
            'function' => [
                'name'        => 'github_search',
                'description' => 'Mencari repository atau user di GitHub.',
                'parameters'  => [
                    'type'       => 'object',
                    'properties' => [
                        'type'  => ['type' => 'string', 'enum' => ['repositories', 'users']],
                        'query' => ['type' => 'string', 'description' => 'Kata kunci pencarian'],
                    ],
                    'required' => ['type', 'query'],
                ],
            ],
        ];
    }

    public function execute(array $args): mixed
    {
        $type  = $args['type'] ?? 'repositories';
        $query = $args['query'] ?? '';

        $result = $this->http->get(
            "https://api.github.com/search/$type",
            ['q' => $query, 'per_page' => 5]
        );

        if (!$result['ok']) {
            return ['error' => 'GitHub API request gagal'];
        }

        $items = $result['body']['items'] ?? [];
        return [
            'total_count'  => $result['body']['total_count'] ?? 0,
            'results'      => array_slice($items, 0, 5),
        ];
    }
}

Tool Currency API

<?php

namespace App\Tools;

use App\Http\HttpClient;

class CurrencyTool implements ToolInterface
{
    private HttpClient $http;

    public function __construct()
    {
        $this->http = new HttpClient(timeout: 10);
    }

    public function getDefinition(): array
    {
        return [
            'type'     => 'function',
            'function' => [
                'name'        => 'convert_currency',
                'description' => 'Mengkonversi jumlah uang dari satu mata uang ke mata uang lain menggunakan kurs terkini.',
                'parameters'  => [
                    'type'       => 'object',
                    'properties' => [
                        'amount' => ['type' => 'number', 'description' => 'Jumlah yang akan dikonversi'],
                        'from'   => ['type' => 'string', 'description' => 'Kode mata uang asal (misal: USD, IDR)'],
                        'to'     => ['type' => 'string', 'description' => 'Kode mata uang tujuan (misal: IDR, EUR)'],
                    ],
                    'required' => ['amount', 'from', 'to'],
                ],
            ],
        ];
    }

    public function execute(array $args): mixed
    {
        $amount = (float) ($args['amount'] ?? 0);
        $from   = strtoupper($args['from'] ?? 'USD');
        $to     = strtoupper($args['to'] ?? 'IDR');

        // Menggunakan ExchangeRate-API (gratis, tidak perlu API key untuk tier dasar)
        $result = $this->http->get("https://api.exchangerate-api.com/v4/latest/$from");

        if (!$result['ok']) {
            return ['error' => 'Gagal mengambil data kurs mata uang'];
        }

        $rate          = $result['body']['rates'][$to] ?? null;
        if (!$rate) {
            return ['error' => "Kode mata uang '$to' tidak ditemukan"];
        }

        $converted = $amount * $rate;
        return [
            'from'      => $from,
            'to'        => $to,
            'amount'    => $amount,
            'rate'      => $rate,
            'converted' => round($converted, 2),
        ];
    }
}

Poin Kunci Bab 14

Tool REST API adalah salah satu yang paling berguna dalam arsenal AI Agent Anda. Dengan pola HttpClient yang reusable, menambahkan integrasi API baru hanya butuh beberapa baris kode tambahan.