튜토리얼 카테고리 Skills 소개
ZH EN JA KO
스킬 플러그인

OpenClaw 확장 개발 시작하기

· 10 분 소요

개요

OpenClaw의 확장(Extension) 시스템은 개발자가 AI 에이전트에 맞춤형 기능을 추가할 수 있도록 합니다. 확장을 통해 새로운 도구를 등록하고, 시스템 프롬프트 조각을 주입하며, 특정 이벤트를 처리하고, 도구 파이프라인의 동작을 수정할 수도 있습니다. 이 글에서는 OpenClaw 확장을 개발, 테스트, 배포하는 방법을 처음부터 안내합니다.

확장 로드 방식

OpenClaw은 두 가지 확장 로드 방식을 지원합니다:

프로그래밍 방식 로드

코드로 직접 확장을 등록하는 방식으로, OpenClaw과 깊이 통합하는 시나리오에 적합합니다:

const { OpenClaw } = require('openclaw');

const app = new OpenClaw();

app.registerExtension({
  name: 'my-extension',
  version: '1.0.0',
  description: '나의 맞춤형 확장',
  setup: async (context) => {
    // 확장 초기화 로직
  }
});

디스크 경로 로드

확장을 지정된 디렉토리에 배치하면 OpenClaw 시작 시 자동으로 감지하고 로드합니다:

extensions:
  path: /data/openclaw/extensions
  autoLoad: true
  allowedExtensions:
    - my-extension
    - another-extension

확장 디렉토리 구조:

/data/openclaw/extensions/
  my-extension/
    index.js
    package.json
    manifest.yaml

확장 구조

manifest.yaml

모든 확장은 메타 정보와 기능을 선언하는 매니페스트 파일을 포함해야 합니다:

name: my-extension
version: 1.0.0
description: 예시 확장입니다
author: 개발자 이름
minOpenClawVersion: 2.0.0

capabilities:
  tools: true
  prompts: true
  events: true

permissions:
  network: false
  filesystem:
    read: ["/data/openclaw/workspace"]
    write: ["/tmp/openclaw/my-extension"]

config:
  apiEndpoint:
    type: string
    required: true
    description: API 엔드포인트 주소
  maxRetries:
    type: number
    default: 3
    description: 최대 재시도 횟수

진입 파일

확장의 진입 파일은 확장 컨텍스트 객체를 인자로 받는 setup 함수를 내보냅니다:

module.exports = {
  setup: async (ctx) => {
    // 도구 등록
    ctx.registerTool({
      name: 'my_custom_tool',
      description: '맞춤형 도구의 기능 설명',
      parameters: {
        type: 'object',
        properties: {
          query: { type: 'string', description: '검색 내용' }
        },
        required: ['query']
      },
      execute: async (params, toolCtx) => {
        const result = await doSomething(params.query);
        return { content: result };
      }
    });

    // 프롬프트 주입
    ctx.registerPrompt({
      position: 'tools',
      content: '사용자가 특정 기능이 필요할 때 my_custom_tool 도구를 사용하세요.'
    });

    // 이벤트 리스닝
    ctx.on('session:start', async (session) => {
      console.log(`새 세션 시작: ${session.id}`);
    });
  }
};

도구 등록 상세

도구 정의

도구를 등록할 때 JSON Schema 규격에 맞는 매개변수 정의를 제공해야 합니다. 이 정의는 7단계 도구 파이프라인의 Schema 검증 단계에서 확인되며, 부적합한 정의는 거부됩니다.

실행 함수

도구의 실행 함수는 두 개의 인자를 받습니다:

  • params: 사용자가 전달한 도구 매개변수로, Schema 검증을 거친 상태
  • toolCtx: 도구 컨텍스트로, 다음 내용을 포함:
    • session: 현재 세션 객체
    • channel: 현재 채널 정보
    • user: 현재 사용자 정보
    • abortSignal: 중단 시그널 (파이프라인 7단계에서 제공)
    • config: 확장 설정

반환 형식

도구 실행 함수는 객체를 반환해야 합니다. 일반적인 형식은 다음과 같습니다:

// 텍스트 결과
return { content: '작업이 성공적으로 완료되었습니다' };

// 구조화된 데이터
return { content: JSON.stringify(data), metadata: { type: 'json' } };

// 오류 결과
return { error: '작업 실패: 구체적인 원인' };

// 첨부 파일이 포함된 결과
return {
  content: '이미지가 생성되었습니다',
  attachments: [{ path: '/tmp/output.png', type: 'image/png' }]
};

프롬프트 주입

확장은 시스템 프롬프트의 여러 위치에 내용을 주입할 수 있습니다:

ctx.registerPrompt({
  position: 'system',    // 시스템 수준 프롬프트
  content: '당신은 특정 기능을 갖추고 있습니다...',
  priority: 10           // 우선순위, 숫자가 클수록 앞에 위치
});

ctx.registerPrompt({
  position: 'tools',     // 도구 사용 지침
  content: 'xxx 도구를 사용할 때 주의할 점...'
});

이러한 프롬프트 조각은 buildAgentSystemPrompt()에 의해 수집되어 최종 시스템 프롬프트에 통합됩니다.

이벤트 시스템

OpenClaw의 이벤트 시스템을 통해 확장이 다양한 시스템 이벤트에 응답할 수 있습니다:

  • session:start — 새 세션 시작
  • session:end — 세션 종료
  • message:receive — 새 메시지 수신
  • message:send — 메시지 전송
  • tool:before — 도구 실행 전
  • tool:after — 도구 실행 후
  • tool:error — 도구 실행 오류
ctx.on('tool:before', async (event) => {
  console.log(`도구 실행 예정: ${event.toolName}`);
  // 매개변수를 수정하거나 실행을 취소할 수 있음
});

확장 간 통신

여러 확장 간에 공유 컨텍스트를 통해 통신할 수 있습니다:

// 확장 A: 데이터 게시
ctx.shared.set('weather:current', weatherData);

// 확장 B: 데이터 읽기
const weather = ctx.shared.get('weather:current');

테스트

단위 테스트

OpenClaw은 격리된 환경에서 확장을 테스트할 수 있는 테스트 도구 키트를 제공합니다:

const { createTestContext } = require('openclaw/testing');

describe('my-extension', () => {
  it('should execute tool correctly', async () => {
    const ctx = createTestContext();
    await extension.setup(ctx);

    const result = await ctx.executeTool('my_custom_tool', {
      query: 'test'
    });

    expect(result.content).toBeDefined();
  });
});

통합 테스트

OpenClaw의 개발 모드로 서비스를 시작하여 확장을 실제로 로드하고 대화를 통해 기능을 테스트합니다.

세션 영속화

확장이 생성한 데이터는 OpenClaw의 세션 영속화 메커니즘(JSONL 형식)을 활용하여 저장할 수 있습니다. 세션 데이터가 압축(compaction)될 때 확장은 session:compact 이벤트를 통해 압축 과정에 참여하여 보존할 데이터를 결정할 수 있습니다.

게시 및 공유

개발이 완료된 확장은 패키징하여 OpenClaw 스킬 마켓플레이스(Skill Marketplace)에 게시할 수 있으며, 다른 사용자가 설치하여 사용할 수 있습니다. 게시 전 기본적인 보안 심사와 기능 검증을 통과해야 합니다.

모범 사례

  1. 최소 권한: 확장이 실제로 필요한 권한만 선언
  2. 우아한 오류 처리: 모든 비동기 작업에 오류 처리 포함
  3. 중단 시그널 응답: 장시간 실행되는 작업은 주기적으로 abortSignal 확인
  4. 문서 완비: 도구에 대해 명확한 설명과 매개변수 안내 작성
  5. 버전 호환: 매니페스트에 최소 OpenClaw 버전 요구 사항 명시

정리

OpenClaw의 확장 시스템은 강력하고 유연한 커스터마이징 기능을 제공합니다. 새 도구를 추가하거나, 동작을 수정하거나, 외부 서비스를 통합하는 등 모든 작업을 모듈 방식으로 구현할 수 있습니다. 확장 개발을 숙달하면 OpenClaw을 어떤 시나리오에든 적용할 수 있는 열쇠를 갖게 됩니다.

OpenClaw는 무료 오픈소스 개인 AI 어시스턴트로, WhatsApp, Telegram, Discord 등 다양한 플랫폼을 지원합니다