메인 콘텐츠로 건너뛰기

Copilot 대응 Laravel 앱을 처음 만들기

이 가이드에서는 Laravel Copilot SDK를 사용해 커맨드라인 어시스턴트를 만듭니다. 1개의 프롬프트 전송부터 시작해서 세션, 이벤트, 도구로 진행합니다.

사전 조건

시작하기 전에 다음을 확인하세요.
  • GitHub Copilot CLI가 설치되어 있고 인증되어 있을 것
  • PHP 8.4+
  • Laravel 13.x
CLI가 사용 가능한지 확인합니다.
copilot --version

SDK 설치

Composer로 패키지를 설치합니다.
composer require revolution/laravel-copilot-sdk
필요에 따라 설정을 게시합니다.
php artisan vendor:publish --tag=copilot-config
필요하다면 .env에서 CLI 경로를 설정합니다.
COPILOT_CLI_PATH=copilot

최초 메시지 보내기

명령어를 만들고 Copilot::run()을 호출합니다.
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Revolution\Copilot\Facades\Copilot;

class CopilotDemo extends Command
{
    protected $signature = 'copilot:demo';
    protected $description = 'Demo Copilot SDK';

    public function handle()
    {
        $response = Copilot::run(prompt: 'What is 2 + 2?');

        $this->info($response->content());
    }
}
명령어를 실행합니다.
php artisan copilot:demo

세션에서 컨텍스트 유지

하나의 대화에서 여러 프롬프트를 사용할 때는 Copilot::start()를 사용합니다.
use Revolution\Copilot\Contracts\CopilotSession;
use Revolution\Copilot\Facades\Copilot;

Copilot::start(function (CopilotSession $session) {
    $response = $session->sendAndWait(prompt: 'What is 2 + 2?');
    $this->info('Answer: '.$response->content());

    $response = $session->sendAndWait(prompt: 'Now multiply that by 3');
    $this->info('Answer: '.$response->content());
});

세션 이벤트 처리

on()으로 이벤트 핸들러를 등록해 어시스턴트의 메시지나 실패를 확인합니다.
use Revolution\Copilot\Contracts\CopilotSession;
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Types\SessionEvent;

Copilot::start(function (CopilotSession $session) {
    $session->on(function (SessionEvent $event): void {
        if ($event->isAssistantMessage()) {
            $this->info($event->content());
        } elseif ($event->failed()) {
            $this->error($event->errorMessage() ?? 'Unknown error');
        }
    });

    $session->sendAndWait(prompt: 'Tell me a short Laravel joke');
});

커스텀 도구 추가

JSON 스키마와 핸들러를 사용해 도구를 정의합니다.
use Illuminate\JsonSchema\JsonSchema;
use Revolution\Copilot\Contracts\CopilotSession;
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Types\SessionConfig;
use Revolution\Copilot\Types\Tool;

$parameters = JsonSchema::object([
    'topic' => JsonSchema::string()
        ->description('Topic to look up')
        ->required(),
])->toArray();

$config = new SessionConfig(
    tools: [
        Tool::define(
            name: 'lookup_fact',
            description: 'Returns a fact for a topic.',
            parameters: $parameters,
            handler: function (array $params): array {
                $topic = $params['topic'] ?? '';

                return [
                    'textResultForLlm' => "Fact for {$topic}",
                    'resultType' => 'success',
                    'sessionLog' => "lookup_fact: {$topic}",
                    'toolTelemetry' => [],
                ];
            },
        ),
    ],
);

Copilot::start(function (CopilotSession $session) {
    $response = $session->sendAndWait(
        prompt: 'Use lookup_fact to tell me something about Laravel.'
    );

    $this->info($response->content());
}, config: $config);

대화형 어시스턴트 만들기

세션, 이벤트, 도구를 조합하면 대화형 Artisan 명령어를 만들 수 있습니다.
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\JsonSchema\JsonSchema;
use Revolution\Copilot\Contracts\CopilotSession;
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Types\SessionConfig;
use Revolution\Copilot\Types\SessionEvent;
use Revolution\Copilot\Types\Tool;
use Revolution\Copilot\Types\ToolResultObject;

use function Laravel\Prompts\error;
use function Laravel\Prompts\info;
use function Laravel\Prompts\note;
use function Laravel\Prompts\spin;
use function Laravel\Prompts\text;

class CopilotAssistant extends Command
{
    protected $signature = 'copilot:assistant';
    protected $description = 'Interactive Copilot assistant';

    public function handle()
    {
        $facts = [
            'PHP' => 'A popular general-purpose scripting language for web development.',
            'Laravel' => 'A web application framework with expressive, elegant syntax.',
            'Composer' => 'Dependency manager for PHP.',
        ];

        $parameters = JsonSchema::object([
            'topic' => JsonSchema::string()
                ->description('Topic to look up')
                ->required(),
        ])->toArray();

        $config = new SessionConfig(
            tools: [
                Tool::define(
                    name: 'lookup_fact',
                    description: 'Returns a fun fact about a given topic.',
                    parameters: $parameters,
                    handler: function (array $params) use ($facts) {
                        $topic = $params['topic'] ?? '';
                        $fact = $facts[$topic] ?? "No fact available for {$topic}.";

                        return new ToolResultObject(
                            textResultForLlm: $fact,
                            resultType: 'success',
                            sessionLog: "lookup_fact: {$topic}",
                            toolTelemetry: [],
                        );
                    },
                ),
            ],
        );

        Copilot::start(function (CopilotSession $session) {
            info('Copilot assistant');
            info("Session: {$session->id()}");
            info("Try: Use lookup_fact to tell me about Laravel");

            $session->on(function (SessionEvent $event): void {
                if ($event->isAssistantMessage()) {
                    note($event->content());
                } elseif ($event->failed()) {
                    error($event->errorMessage() ?? 'Unknown error');
                }
            });

            while (true) {
                $prompt = text(
                    label: 'You',
                    placeholder: 'Ask me anything...',
                    required: true,
                    hint: 'Ctrl+C to exit',
                );

                spin(
                    callback: fn () => $session->sendAndWait($prompt),
                    message: 'Thinking...',
                );

                echo "\n";
            }
        }, config: $config);
    }
}
명령어를 실행합니다.
php artisan copilot:assistant

도구의 구조

도구를 정의할 때는 다음 3가지를 지정합니다.
  1. 도구가 무엇을 하는지.
  2. 어떤 매개변수를 받는지.
  3. 어떤 핸들러 코드를 실행하는지.
Copilot은 사용자 입력에 따라 도구 호출을 판단하고, SDK가 핸들러를 실행해 결과를 반환합니다.

다음에 시도해볼 기능

MCP 서버 연결

use Revolution\Copilot\Types\SessionConfig;

$config = new SessionConfig(
    mcpServers: [
        'github' => [
            'type' => 'http',
            'url' => 'https://api.githubcopilot.com/mcp/',
        ],
    ],
);

커스텀 에이전트 만들기

use Revolution\Copilot\Types\SessionConfig;

$config = new SessionConfig(
    customAgents: [
        [
            'name' => 'pr-reviewer',
            'displayName' => 'PR Reviewer',
            'description' => 'Reviews pull requests for best practices',
            'prompt' => 'You are an expert code reviewer. Focus on security, performance, and maintainability.',
        ],
    ],
);

시스템 메시지 커스터마이즈

use Revolution\Copilot\Types\SessionConfig;
use Revolution\Copilot\Types\SystemMessageConfig;

$config = new SessionConfig(
    systemMessage: new SystemMessageConfig(
        content: 'You are a helpful assistant for our engineering team. Always be concise.',
    ),
);

외부 CLI 서버에 접속

Copilot CLI를 서버 모드로 기동합니다.
copilot --headless --port 4321
그리고 .env에서 접속처 URL을 설정합니다.
COPILOT_URL=tcp://127.0.0.1:4321
COPILOT_URL을 설정하면 SDK는 새로운 CLI 프로세스를 기동하지 않고 기존 서버에 접속합니다.

텔레메트리와 관측성

config/copilot.php에서 텔레메트리를 설정합니다.
'telemetry' => [
    'otlpEndpoint' => 'http://localhost:4318',
],
또는 직접 설정합니다.
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Types\TelemetryConfig;

Copilot::useStdio([
    'telemetry' => new TelemetryConfig(
        otlpEndpoint: 'http://localhost:4318',
    ),
]);

더 알아보기

다음 단계

인증

로컬 환경과 CI에 적합한 인증 방식을 선택합니다.

SessionConfig

모델, 훅, MCP 서버, 런타임 동작을 설정합니다.

SessionEvent

Laravel 고유의 이벤트 헬퍼와 라이프사이클 처리를 이해합니다.

권한 요청

명시적 승인으로 도구를 실행하는 권한 흐름을 확인합니다.

도구

Copilot에서 애플리케이션 코드를 호출합니다.

MCP

MCP 서버의 기성 도구를 연결합니다.
여기까지 단발 프롬프트에서 도구 연동 세션까지 Laravel Copilot SDK의 핵심 흐름을 한 번씩 확인했습니다.
마지막 수정일 2026년 7월 13일