Orkas Orkas
블로그 아키텍처
아키텍처

에이전트의 기반 다시 쓰기: Orkas의 전면 리팩터링

Orkas가 1.0 릴리스 계열에서 에이전트 기반을 다시 구축한 방법을 살펴봅니다. 프로세스 내 런타임, 제공업체 순환, 동적 그룹 채팅 오케스트레이션, 개방형 호스팅, 메모리, 자기 진화를 다룹니다.

AI 에이전트 제품이 성숙해질수록 가장 큰 비용이 드는 것은 기능이 아니라 기반입니다. 이 글에서는 Orkas가 1.0 릴리스 계열 전반에 걸쳐 진행한 전면 리팩터링, 즉 모델 호출, 에이전트 루프, 멀티 에이전트 오케스트레이션, 도구 생태계의 대대적인 개편과 각 결정에 따른 장단점을 살펴봅니다.

요약 다시 작성한 이유 그 결과가 지금 설치할 수 있는 앱입니다. MIT 라이선스의 오픈 소스이며 로컬 우선으로 작동하고, 원하면 자신의 제공업체 키로 실행할 수 있습니다.
Orkas 다운로드 — 무료

기반을 손본 이유

Orkas는 로컬 우선 데스크톱 AI 에이전트 작업 공간입니다. 모든 에이전트 작업은 사용자 컴퓨터의 프로세스 안에서 실행되고, 데이터는 로컬에 저장되며, 종단 간 클라우드 동기화는 필요할 때 이루어집니다. 초기 버전에는 스킬 라이브러리, 지식 베이스, 커넥터, 그룹 채팅 방식의 멀티 에이전트 등 기능이 빠르게 쌓였습니다. 하지만 개발이 진행될수록 진짜 병목은 개별 기능이 아니라 세 가지 "기반 수준"의 문제라는 점이 분명해졌습니다.

  1. 모델 호출 계층이 기존의 대화 방식을 따르면 잘못된 가정에 줄줄이 얽매입니다. 대형 모델을 "일문일답 채팅"처럼 호출하면 채팅에는 맞지만 에이전트에는 맞지 않는 기본 전제들이 따라 들어옵니다. 고정된 출력 토큰 상한, 순차적인 도구 호출, 숨겨진 타임아웃, 하나로 고정된 제공업체가 그렇습니다. 에이전트는 수십 턴을 연속으로 실행하고, 컨텍스트 창 한계에 자주 도달하며, 파일을 병렬로 읽어야 하고, 사용자가 언제든 개입할 수 있는 장시간 실행 흐름입니다. 이런 기본값 하나하나가 실제 운영에서 문제를 일으킵니다. 더 큰 문제는 정밀한 파일 조작, 로컬 검색, 셸 실행, 여러 작업자의 병렬 실행, 장기 작업 해결 등 데스크톱 에이전트의 가장 가치 있는 기능이 바로 이 가정의 계층에 의해 차단된다는 것입니다.

  2. 오케스트레이션은 "정적 계획" 방식이었습니다. 초기 버전은 계획/DAG 엔진이었습니다. 먼저 모델이 작업을 계획 그래프로 나눈 다음 실행기가 그래프에 따라 배정했습니다. 깔끔하게 들리지만 에이전트의 실제 작업은 매우 동적입니다. 파일 하나를 읽고 방향을 바꿔야 한다는 사실을 알게 되고, 하위 작업 하나의 결과가 다음 단계를 누가 맡을지 결정합니다. 미리 생성한 그래프에 결정을 고정하면 "계획이 현실을 따라가지 못하는" 모든 상황을 실행기 안에서 보완해야 합니다.

  3. 생태계는 닫힌 카탈로그였습니다. 스킬은 공식 마켓플레이스에서만 가져올 수 있었고, 커넥터는 하드코딩된 카탈로그였으며, 사용자 컴퓨터에 이미 있는 외부 에이전트 도구는 Orkas에 완전한 블랙박스였습니다. 사용자가 타사 프로젝트나 자체 MCP 서버를 연결하거나, 컴퓨터에 이미 있는 에이전트가 Orkas의 스킬과 지식 베이스를 다시 호출하게 하려 해도 아키텍처상 모두 불가능했습니다.

이번 리팩터링의 핵심은 간단합니다. 에이전트의 기반에 대한 통제권을 되찾는 것입니다. 구체적으로는 서로 얽힌 네 가지 방향으로 구현됩니다. 직접 만든 프로세스 내 런타임, 제공업체에 종속되지 않는 모델 계층, 동적 그룹 채팅 오케스트레이션, 닫힌 카탈로그에서 개방형 호스트로의 전환입니다. 하나씩 살펴보겠습니다.

1. 완전한 코딩 에이전트 기능을 데스크톱으로 가져오기

데스크톱은 에이전트가 능력을 발휘하기 좋은 환경입니다. 실제 파일 시스템, 실제 셸, 실제 로컬 도구 체인이 있습니다. 채팅만 할 수 있는 어시스턴트는 이 환경을 낭비합니다. 데스크톱의 이점을 실제로 활용하는 것은 완전한 코딩 에이전트 기능입니다. 문자 범위 단위의 파일 읽기와 쓰기, 파일 간 검색, bash 및 시스템 도구 실행, 여러 작업자의 병렬 가동, 복잡한 작업이 실제로 끝날 때까지 수십 턴을 계속 실행하는 장기 문제 해결 능력이 여기에 해당합니다.

리팩터링의 핵심 결과물은 바로 이 기능을 Orkas 자체 프로세스 안에서 기본적으로 제공하기 위한 것입니다. 독립적이고 동적으로 로드할 수 있는 프로세스 내 에이전트 런타임이며, 코드에서는 core-agent라고 부릅니다. 또 하나의 채팅 래퍼가 아니라 Orkas가 직접 통제하는 에이전트 엔진입니다.

핵심 아키텍처 결정은 이를 두 계층으로 나누는 것이었습니다:

  • 엔진 계층(독립 패키지): 도구 호출 루프, 스트리밍 이벤트, 컨텍스트 압축, 오류 분류와 재시도, 제공업체 추상화, 샌드박스, 스킬 탐색, 메모리, 자기 진화 등 순수한 에이전트 구동 기능입니다. 엔진은 Orkas의 비즈니스 기능에 대해 아무것도 모릅니다. 비즈니스 데이터 디렉터리를 읽지 않고, 대화 파일 형식을 이해하지 않으며, IPC에는 전혀 관여하지 않습니다.
  • 어댑터 계층(메인 프로세스 내부): 엔진을 Orkas에 연결합니다. 세션 영구 저장, 제공업체 순환, 도구 권한, 스킬 레지스트리, 커넥터, 지식 베이스, 각종 생성 도구를 담당합니다. 엔진 고유 이벤트를 Orkas 자체 이벤트 형식으로 변환하여 비즈니스 계층에는 항상 안정된 인터페이스만 보이게 합니다.

이 엔진/어댑터 경계가 이후 모든 유연성의 뿌리입니다. 엔진은 독립적으로 테스트하고 발전시킬 수 있습니다. 어댑터 계층은 엔진을 오염시키지 않고 Orkas 고유의 복잡성(순환, 대기 시간, 샌드박스, 권한)을 안전하게 흡수합니다. 팀의 아키텍처 검토에서는 한 문장으로 정리했습니다. 이것은 필요한 이유가 있는 복잡성이다. 합치지 말자.

실제로 어떤 기능인가

런타임을 직접 통제하는 것은 과시를 위해서가 아닙니다. 에이전트가 데스크톱에서 실제로 "직접 일을 처리"하게 하기 위해서입니다. 기능은 대략 네 그룹으로 나뉩니다.

  • 정밀한 파일 조작과 로컬 검색. read_file은 문자 범위별 읽기를 지원하고 PDF / Office 문서에서 텍스트를 자동 추출합니다. edit_file은 정확한 "이전 문자열 → 새 문자열" 치환을 수행하며 쓰기 전에 반드시 읽도록 합니다. write_file은 결과물을 저장하고 기록을 남깁니다. stat_file은 크기를 확인합니다. search_files는 이름/glob으로 위치를 찾고, grep_files는 파일 전반의 내용을 검색합니다. 이 기능을 통해 에이전트는 큰 덩어리를 통째로 입력받고 출력하는 데 그치지 않고, 실제 작업 공간에서 엔지니어처럼 "코드를 살펴보고 파일을 수정"할 수 있습니다.
  • Bash 및 시스템 도구. 샌드박스 안의 셸 실행기로, 백그라운드 실행 모드(긴 작업은 현재 턴에서 분리되고 로그는 파일에 저장)와 위험 작업에 대한 위험도별 승인 절차를 갖춥니다. 데스크톱 에이전트의 힘은 상당 부분 시스템 도구 체인을 직접 제어할 수 있다는 데서 나옵니다.
  • 여러 작업자의 병렬 실행. 한 턴 안에서 독립적인 읽기 전용 도구가 동시에 실행됩니다. 작업 수준에서는 Commander가 독립적인 하위 작업을 여러 작업자에게 병렬로 나누어 맡길 수도 있습니다(섹션 3 참조). 안전한 곳에서 병렬화하는 것이 "장기 작업"의 실제 소요 시간을 허용 가능한 수준으로 줄이는 핵심입니다.
  • 장기 추론과 작업 해결. 수십 턴을 연속 실행하고, 자체 컨텍스트를 관리하고, 오류에서 복구하고, 제자리 반복에 갇히지 않는 루프. 이것이 "복잡한 업무 완수"와 "질문에 답하기"를 가르는 기준입니다.

실제 운영 수준으로 만든 엔지니어링 방법

"직접 루프를 작성한다"는 것은 고생을 자초하는 것처럼 들리며 실제로 유지보수 비용도 듭니다. 하지만 그 대가로 에이전트 전체 수명 주기를 정밀하게 통제할 수 있습니다. 이 통제는 추상적이지 않습니다. 위 기능들이 실제 운영에서 "제대로 버티는지"에 각각 대응하는 구체적인 개선 사항입니다.

  • 실제 컨텍스트 창 + 80%에서만 압축. 엔진은 각 모델의 실제 컨텍스트 창(100만 토큰 창 모델 포함)을 읽고 사용량이 80%에 도달할 때만 압축을 실행합니다. 보수적으로 60%부터 시작해 유용한 컨텍스트의 40%를 버리지 않습니다. "효과 없는 압축" 방지 장치도 있습니다. 보존할 끝부분만으로 이미 창이 가득 차 있다면(예: 끝부분에 매우 큰 파일 읽기 결과가 있는 경우) 압축으로 공간을 확보할 수 없으므로 경고만 기록하고 건너뜁니다. 쓸모없는 요약 호출을 반복하지 않습니다. 장기 작업이 "앞서 있었던 일을 기억"할 수 있는지는 결국 여기에 달려 있습니다.

  • 인접한 읽기 전용 도구의 병렬 실행. 모델이 한 턴에 파일 읽기, 파일 검색, 웹 조회처럼 독립적인 읽기 전용 도구 여러 개를 호출하면 엔진은 인접한 병렬화 가능 도구를 묶어 동시에 실행합니다. 쓰기 도구는 자연스러운 경계가 되며 선언된 순서를 유지합니다. 도구 호출과 결과는 엄격히 선언된 순서로 반영되므로 동시 실행이 프로토콜을 깨뜨리지 않습니다. 가장 흔한 읽기 전용 도구가 한 번에 순차 실행에서 병렬 실행으로 바뀌고, 전체 묶음의 실제 소요 시간이 눈에 띄게 줄어듭니다.

  • 쓰기 전 읽기 + 낙관적 동시성 제어. 파일을 편집하기 전에 반드시 읽어야 합니다. 엔진은 읽은 파일의 기준 상태를 기록하고 편집할 때 그 상태가 달라지지 않았는지 확인합니다. 여러 작업자가 동시에 같은 파일을 바꾸면 뒤처진 쪽은 서로의 변경 사항을 조용히 덮어쓰는 대신 명확한 "stale" 오류를 받습니다. 여러 작업자가 같은 작업 공간에서 병렬로 작업할 때 없어서는 안 될 보호 장치입니다.

  • 실행 중 개입을 즉시 반영. 에이전트가 작업하는 도중 사용자가 한 줄을 더 입력하면, 엔진은 도구 루프 경계에서 대기 중인 메시지를 현재 턴의 입력에 반영합니다. 별도의 턴으로 실행할 때까지 기다리지 않습니다. 이를 통해 "실행 중 방향 수정"이 자연스러운 상호작용이 됩니다.

  • 루프 감지. 같은 도구 호출이 연달아 반복되면 엔진은 먼저 주의를 주고(3번째) 강제로 멈춥니다(5번째). 호출 특성이 조금이라도 달라지면 횟수를 초기화하므로 페이지네이션이나 폴링 같은 정당한 변형을 잘못 감지하지 않습니다. 모델이 막혀도 더 이상 조용히 토큰을 소모하지 않습니다.

  • 주요 턴 출력의 고정 상한 제거. 주요 턴 출력에 더 이상 작은 상한을 고정하지 않아 긴 보고서나 대규모 편집이 조용히 잘리지 않습니다. 보조 호출(압축, 성찰)에는 여전히 보수적으로 작은 상한을 사용합니다.

매우 "현지화된" 세부 사항도 하나 언급할 만합니다. 중국어와 영어가 섞인 텍스트의 토큰 추정입니다. 일반적인 추정법은 중국어로만 된 대화의 토큰 수를 실제의 2분의 1~3분의 1로 과소 계산합니다. 엔진은 문자 유형에 따라 중국어와 영어 문자를 다르게 처리하여 압축 임계값을 신뢰할 수 있게 합니다. 범용 SDK가 대신 고려해 주지 않는 종류의 문제입니다.

이 개선들을 합치면 "왜 기존 SDK를 쓰지 않는가"에 대한 답이 됩니다. 데스크톱 에이전트의 가장 강력한 기능이 마침 SDK가 노출하지 않는 바로 그 계층에 있기 때문입니다. 이를 실제 운영 수준으로 만들려면 루프를 직접 통제해야 합니다.

2. 모델을 항상 온라인으로 유지하기: 다층 제공업체 래퍼

모델 계층의 목표는 한 문장입니다. 특정 키, 제공업체, 네트워크에서 무엇이 잘못되더라도 사용자의 이번 대화 턴은 가능하다면 반드시 살아남아야 합니다. 이를 위해 어댑터 계층은 엔진의 제공업체 추상화 위에 순환, 대기 시간, 등록, 외부 연동이라는 래퍼들을 쌓습니다.

가장 중요한 설계는 순환기가 실행기 아래에 위치한다는 것입니다. 엔진은 제공업체를 호출하기 전에 사용자의 메시지를 영구 세션에 기록합니다. 엔진 수준에서 재시도/순환을 처리하면 사용자 메시지를 다시 제출하거나 전체 세션 롤백을 구현해야 합니다. 순환기를 엔진 아래에 두면 사용자 메시지는 정확히 한 번만 기록되고 "다른 후보로 재시도"하는 과정은 세션 상태에 완전히 투명해집니다.

순환기의 판단도 절제되어 있으며 기준선은 첫 콘텐츠 이벤트입니다:

  • 모델이 실질적인 콘텐츠(텍스트/도구 호출)를 내보내기 이전에 실패하면 다음 후보로 안전하게 전환할 수 있습니다.
  • 첫 콘텐츠 이벤트가 발생하면 순환을 중단하고 오류가 상위로 전달되게 합니다. 모델이 이미 한 턴 전체를 실행했을 수 있어 다시 수행하면 부수 효과가 반복되기 때문입니다.

오류 분류가 "순환, 순환하지 않음, 재시도"를 결정합니다. 계정 수준 오류인 인증 실패, 잔액 부족, 사용량 제한, 구독 만료에는 대기 시간을 표시하고 순환합니다. 일시적인 네트워크 오류인 연결 재설정 등에는 대기 시간을 적용하지 않고 같은 곳에서 상태를 유지하지 않는 방식으로 몇 차례 재시도합니다. 반면 잘못된 요청, 콘텐츠 정책, 서버 5xx처럼 다른 키로도 똑같이 실패할 오류는 순환 없이 그대로 전달합니다. 대기 시간은 10분짜리 프로세스 내부의 비영구적 힌트입니다. 단기 신호일 뿐이므로 실패할 때마다 디스크에 기록할 가치가 없으며, 프로세스 재시작은 다시 확인하기에 적절한 시점입니다.

제공업체 "목록" 측면에서 리팩터링은 세 종류의 소스를 하나의 통합 추상화로 정리합니다.

  • Orkas 관리형 LLM: 로그인하면 바로 사용할 수 있는 서버 측 프록시이며, 서버가 텍스트/이미지 모델 간 라우팅을 처리합니다.
  • 자체 키 사용: 일반적인 주요 대형 모델 제공업체입니다.
  • 외부 직접 연결 어댑터: 직접 연결이 필요하거나 자체 과금 체계가 있는 여러 모델을 동일한 제공업체 인터페이스에 개별 연동합니다.

상위 계층에는 이 모든 것이 안정적인 하나의 (provider, model) 쌍으로만 보입니다. 순환, 대기 시간, 외부 연동은 모두 어댑터 계층 내부에 숨겨져 있습니다.

3. 그룹 채팅을 오케스트레이션으로: 정적 계획 DAG에서 Commander가 루프에 참여하는 방식으로

리팩터링에서 가장 "사고방식을 바꿔야 하는" 부분입니다.

기존 모델은 정적 계획이었습니다. 모델이 먼저 계획/DAG를 생성하고 실행기는 그래프대로 실행합니다. 새 모델은 그 그래프를 완전히 제거하고 Commander가 루프에 참여하는 동적 그룹 채팅 오케스트레이션으로 대체합니다.

이를 비유하면 그룹 채팅방입니다:

  • 이때 Commander는 보이지 않는 미들웨어가 아니라 채팅방의 진행자입니다.
  • 에이전트 작업자는 채팅방에서 동등한 지위를 갖는 일급 구성원입니다.
  • 모든 상호작용은 비동기 메시지이며 단 하나의 메시지 버스를 통해 대기열에 들어갑니다(병렬 배정을 위한 별도 비공개 경로는 없습니다).

Commander의 "배정"은 본문에 쓴 @somebody가 아닙니다. LLM이 본문에 @AgentA를 쓰는 것은 학습 데이터에서 나온 마크다운일 뿐이며 신뢰할 수 없습니다. 실제 배정 신호는 구조화된 도구 호출이며, 리팩터링 이후에는 의미가 명확한 세 가지 동작으로 정리됩니다.

  • dispatch_to — 에이전트를 보내 작업을 끝까지 수행하고 결과를 돌려받은 뒤 Commander가 종합합니다. 여러 독립 작업을 동시에 나누어 맡길 수 있습니다.
  • run_worker — Commander가 직접 책임지는 하위 작업이며 결과는 동기적으로 반환됩니다. 익명 작업자는 Commander의 "손"(사용자에게 보이지 않음)이고, 이름 있는 작업자는 눈에 보이는 전문가입니다.
  • hand_off_to대화를 넘겨 해당 에이전트가 맡게 합니다. Commander는 물러나고 에이전트가 사용자에게 직접 답하며, 이번 턴에는 추가 종합이 없습니다.

오케스트레이터나 하위 에이전트 트리 대신 그룹 채팅인 이유

멀티 에이전트를 그룹 채팅으로 만들면 기존 오케스트레이터/하위 에이전트 트리로는 얻을 수 없는 여러 이점이 생깁니다.

  • 가시성별 분리. 각 메시지는 "볼 수 있는 대상"의 구간에만 추가됩니다. 에이전트 작업자가 시작할 때 자신의 구간만 재생하므로 다른 에이전트의 대량 출력이 자신의 컨텍스트를 오염시키지 않습니다. Commander는 모든 내용을 봅니다.
  • 최소한의 상태. 전체 오케스트레이션의 핵심 상태는 "현재 누가 발언권을 갖고 있는가"와 가벼운 작업 대장뿐입니다. DAG도 복잡한 상태 머신도 없습니다.
  • 자연스러운 재생과 동기화. 메시지는 자연스럽게 타임스탬프순으로 정렬되므로 다시 불러오기와 기기 간 동기화가 모두 메시지 스트림으로 바로 처리됩니다. 모바일의 원격 제어도 정확히 이 스트림을 기반으로 합니다. 모든 에이전트 연산은 데스크톱에서 실행되고, 모바일은 화면을 그대로 표시할 뿐이므로 특별한 오케스트레이션 프로토콜이 필요하지 않습니다.

팀의 아키텍처 검토에서도 이 점을 똑같이 단호하게 말했습니다. 그룹 채팅 버스와 루프에 참여하는 Commander의 조합 자체가 Orkas의 멀티 에이전트 형태입니다. 프로세스 안에 또 다른 병렬 하위 에이전트 배정 경로를 추가하면 오히려 "그룹 채팅 배정 경로는 하나뿐"이라는 불변 조건을 위반합니다.

이번 버전의 새로운 기능: 대화형 인계

이 흐름에서 가장 최근에 추가된 것은 대화형 에이전트 인계입니다.

문제는 구체적입니다. "튜터"형 에이전트가 한 턴 동안 사용자를 가르친 뒤 사용자는 계속 후속 질문을 하고 싶지만, 시스템이 발언권을 강제로 Commander에게 돌려줍니다. 사용자는 매번 그 에이전트를@로 다시 지정해야 합니다.

해결책은 서버가 권한을 갖는 발언권 + 모델이 결정하는 수신 대상입니다:

  • 발언권은 다시 불러와도 보존되는 영구 상태 필드가 되며, 기존 상태 변경 이벤트를 통해 모든 클라이언트에 자동 동기화 됩니다. 새로운 이벤트 유형은 필요하지 않습니다.
  • Commander가 hand_off_to를 사용하여 대화형 에이전트에게 발언권을 넘기면, 사용자가 이후에 "@없는" 메시지를 보낼 때도 해당 에이전트에게 바로 전달됩니다. 에이전트가 스스로 돌려주거나 사용자가 Commander를 다시 지정할 때까지 유지됩니다.
  • 에이전트는 <handback /> 마커로 제어권을 돌려줍니다. 파싱 시 실제 일치를 엄격히 확인하므로 본문에 우연히 나타난 <handback를 인계로 잘못 읽지 않습니다.
  • 돌려받는 시점에 미완료 작업 대장이 있으면 Commander가 대장에서 이어 받아 계속 진행합니다.

이와 함께 사용 경험도 개선됩니다. Commander 루프 말풍선입니다. 한 턴 안에서 Commander의 "배정 → 결과 읽기 → 다시 배정" 루프는 이전에 하나의 말풍선으로 뭉쳐졌고, 다시 불러오면 순서가 어긋나 맨 아래로 이동하기도 했습니다. 리팩터링은 한 턴을 보이는 배정 경계마다 여러 구간으로 나눕니다. 각 구간은 증가하는 타임스탬프를 갖는 독립 메시지입니다. 이제 사용자는 처음으로 Commander가 "오케스트레이션 루프를 도는" 모습을 볼 수 있으며, 다시 불러왔을 때의 순서도 올바릅니다.

마지막으로 전반에 걸쳐 작동하는 두 가지 안전장치가 있습니다. 그룹 중단은 모든 실행 주체의 유일한 중지 경로입니다 (사용자가 중지를 누르는 순간 모든 작업자에 중단 신호가 전달되고, 대체 매칭으로 익명 하위 작업자까지 포함합니다). 또 하나는 앞서 언급한 실행 중 개입을 통한 방향 수정으로, 실행 도중 사용자가 덧붙인 말을 현재 턴에 반영합니다.

4. 닫힌 카탈로그에서 개방형 호스트로

앞의 세 가지 방향이 기반을 튼튼히 하는 것이었다면, 이번 방향은 모든 문과 창을 활짝 여는 것입니다. Orkas를 닫힌 카탈로그에서 개방형 호스트로 바꿉니다. 동시에 보안 경계는 한 치도 양보하지 않고 지킵니다.

리팩터링은 여러 "닫힌" 병목을 체계적으로 해체했습니다.

  • 외부 패키지. 사용자가 저장소 주소를 제공하면 Orkas는 이를 로컬에서 호스팅하며 폴더에 그대로 복제합니다. 정규화하지도, 다시 작성하지도, 클라우드에 동기화하지도 않습니다(타사 의존성 디렉터리가 포함되어 있기 때문입니다). 독립적인 명령줄 도구가 설치/업데이트/시작/중지 수명 주기를 담당하고, "스킬 형태"(스킬 설명 파일 포함)인지 "CLI 형태"(실행 진입점 포함)인지 검사한 뒤 메타데이터를 패키지 디렉터리 밖의 레지스트리에 기록합니다(따라서 나중에 pull로 업데이트해도 충돌하지 않습니다). 의존성 설치는 "한 번 묻고 기억하기" 방식의 두 단계 확인을 거칩니다. 실행 진입점에는 shim을 생성해 bash 도구의 PATH에 추가하므로 모델이 타사 CLI를 직접 호출할 수 있습니다.

  • 여러 루트의 스킬 로딩. 스킬 실행의 단일 진입점은 두 루트만 인식하던 방식에서 사용자 정의 / 마켓플레이스 / 외부 패키지 / 전역의 네 계층으로 바뀌었으며, 우선순위에 따라 해석합니다. 외부 패키지 안의 스크립트는 패키지에 포함된 자체 의존성 환경을 우선합니다. 이 지점은 회귀 위험이 가장 높은 병목이므로 전체 테스트 픽스처 매트릭스로 뒷받침합니다.

  • 전역 스킬 상호운용. Orkas는 사용자 컴퓨터의 다른 에이전트 도구가 이미 관리하는 전역 스킬 디렉터리를 직접 읽어 스킬 수준에서 상호운용합니다. 사용자가 한곳에서 쌓은 스킬을 Orkas에서도 사용할 수 있습니다. 사용자가 그 디렉터리에 스킬을 넣은 행위 자체를 승인으로 보므로 기본 활성화하되 전체 스위치를 남겨 둡니다. 이런 타사 스킬 설명은 신뢰할 수 없는 프롬프트 인젝션의 진입점이므로 "개방 계층" 로더를 거치고 Commander에게만 보이며 구조적으로 에이전트의 스킬 허용 목록에 들어갈 수 없습니다.

  • 사용자 설정 MCP. 커넥터는 더 이상 하드코딩된 카탈로그가 아닙니다. 사용자는 원격 HTTP 형태(낮은 위험)나 로컬 하위 프로세스 형태(높은 위험)의 MCP 서버를 자유롭게 추가할 수 있습니다. 양식 자체가 동의를 받는 화면이며 사용자가 직접 입력한 명령을 그대로 보여 줍니다. 비밀 정보를 포함한 전송 설정은 전부 암호화 저장소에 들어갑니다. 사용자 정의 인스턴스에는 항상 고정 접두사가 붙어 카탈로그의 공식 커넥터를 사칭할 수 없습니다.

  • 역방향 브리지: 컴퓨터의 외부 에이전트도 Orkas를 인식하게 하기. 가장 흥미로운 부분입니다. 사용자 컴퓨터에 이미 있는 외부 에이전트 도구는 이전에는 Orkas에 블랙박스였습니다. 이제 Orkas가 이 도구에 작업을 배정할 때 브리지 채널을 주입하여 반대 방향으로 Orkas의 스킬을 나열/읽기/실행하고, 커넥터를 호출하고, 지식 베이스를 검색하게 합니다. 브리지는 로컬 프로세스 간 채널로 실행되며 네트워크 포트를 열지 않습니다. 실행마다 고유한 일회용 자격 증명으로 인증하고 실행이 끝나는 즉시 이를 폐기합니다. 외부에 부수 효과를 일으키는 모든 커넥터 호출은 사용자 확인 대화상자를 거칩니다. 도구 이름으로 읽기/쓰기를 추정하는 방식(지나치게 느슨해질 수 있음)이 아니라 (에이전트, 커넥터) 조합마다 한 번 확인하며, "항상 허용"을 선택할 수 있습니다.

  • 비정형 코딩 작업에 대한 대응. Commander의 의사 결정 트리에 분기가 추가됩니다. 일치하는 에이전트/스킬/커넥터가 없을 때 bash와 짧은 스크립트로 직접 해결할 수 있는지 평가하고, 이번 턴에 수행한 뒤 결과를 검증하며 필요하면 사용자 정의 스킬로 정리할 것을 제안합니다. 백그라운드 bash 실행(긴 작업은 현재 턴에서 분리되고 로그는 파일에 저장)과 사용자가 허용한 디렉터리가 함께 지원됩니다.

개방하되 방치하지 않기

문과 창을 열 때 가장 걱정되는 것은 외풍입니다. 이번 리팩터링의 원칙은 다음과 같습니다. "위험한 동작"의 실행 생성 통제 지점은 단 하나도 건드리지 않습니다. MCP는 정확히 한 곳에서 시작하고, 스킬 실행은 정확히 하나의 실행기를 거치며, bash는 정확히 하나의 샌드박스 실행기를 거칩니다. 그 위에 여러 겹의 방어 계층을 쌓습니다.

  • 파일 조작은 항상 경로 샌드박스(작업 공간 + 현재 첨부 파일 + 사용자가 명시적으로 허용한 디렉터리)를 통과합니다. 자격 증명 디렉터리, 시스템 디렉터리, Orkas 자체 디렉터리는 허용 대상으로 지정할 수 없습니다.
  • 위험한 bash(데이터 유출, 파괴적 삭제, 권한 상승, 민감한 경로)는 권한 확인을 띄웁니다. 결정은 "이번 한 번만 / 이번 실행 동안 / 거부"로 나뉘며, 로그에는 범주와 길이만 기록하고 명령문 자체는 절대 기록하지 않습니다.
  • 외부 패키지 설치에서는 심볼릭 링크 항목이 포함된 패키지를 안전 우선 원칙에 따라 무조건 거부합니다. 이는 심볼릭 링크를 이용해 샌드박스 밖의 민감한 파일을 허용 범위 안으로 읽어 들이는 것을 막기 위해서입니다. 복제 원본은 프로토콜 허용 목록으로 제한됩니다.
  • 자격 증명이 포함된 모든 전송 설정/비밀 정보는 저장 시 암호화하고, 브리지 자격 증명은 실행마다 격리합니다.
  • 오픈 소스 / 호스팅 배포판은 제거 규칙에 따라 호스트 전용 기능을 제외합니다.

한 문장으로 말하면, 모든 명시적 사용자 행동(설치 / 권한 부여 / 양식 제출 / 확인 클릭)이 동의의 증거이며, 모든 동의는 그에 맞는 경계 안으로 제한됩니다.

5. 세션을 거치며 더 똑똑해지기: 메모리와 자기 진화

기반 개편에서는 "쓸수록 에이전트를 더 똑똑하게 만드는" 두 하위 시스템도 다시 만들었습니다. 두 시스템 모두 같은 엔지니어링 원칙을 따릅니다. 기본 비활성화, 범위 제한, 관찰 가능성입니다.

세션 간 메모리는 하이브리드 검색을 사용합니다. 벡터 의미 검색 + 키워드 검색(BM25)을 RRF(역순위 융합)로 합쳐 어느 한 채널만 실패하는 상황에 대비하며, 전체 텍스트 색인을 갖춘 로컬 저장소에 저장합니다. 메모리는 에이전트 자체 메모와 사용자 선호 프로필 두 종류입니다. 각각 글자 수 상한이 있고 쓰기 전에 인젝션 위협을 검사하며, 매 턴 시작 시 시스템 프롬프트에 고정된 상태로 주입됩니다. 전체 메모리 시스템의 목적은 에이전트가 현재 사용자를 더 잘 이해하도록 하는 것뿐입니다. 데이터는 항상 로컬에 남으며 사용자는 설정에서 언제든 조회, 편집, 내보내기할 수 있습니다.

자기 진화는 에이전트 전용 스킬 라이브러리(플랫폼의 공유 스킬 라이브러리와 별도 저장)에 메타인지 성찰 계층을 더한 것입니다. 엔진은 여러 가중 신호를 바탕으로 성찰 여부를 결정합니다. 사용자 교정(가장 높은 가중치), 사소하지 않은 오류에서의 복구, 작업 복잡도, 알려진 약점의 발현 또는 극복, 스킬의 비효율 등이 해당합니다. 가중 신호가 임계값을 넘을 때만 성찰을 실행합니다. 성찰 자체는 백그라운드 주기 작업 (약 12시간마다 한 차례, 수 시간의 대기 시간, 수일 단위의 대체 실행)으로, 저렴한 소형 모델이 최근 활동 요약을 읽고 스킬을 만들거나 수정할지, 에이전트의 "역량 프로필"을 갱신할지 결정합니다.

가장 중요한 안전 원칙: 자기 진화는 에이전트가 명시적으로 연결된 세션에만 활성화됩니다. 기본 Commander 세션은 진화하지 않습니다. 성찰에는 이중 토큰 상한(횟수 + 총량)이 있고, 한 에이전트의 실패가 다른 에이전트를 막지 않으며, 실행당 비용은 극히 낮게 유지합니다. 에이전트를 더 똑똑하게 만들되 통제 밖으로 나가게 두지는 않습니다.

엔지니어링 철학: 필요한 복잡성을 단순화로 없애지 않기

팀은 리팩터링 중 여러 차례 아키텍처 검토를 진행했고, 반복해서 나온 한 가지 결론은 따로 강조할 가치가 있습니다. "구조의 비대화"와 "필요한 복잡성"을 구분하고 전자만 손보세요.

  • 동기화 엔진의 여러 병합 전략, 직접 만든 에이전트 루프, 다층 제공업체 래퍼, 모바일 원격 제어의 경계는 복잡해 보이지만 각 계층에는 존재 이유가 있습니다(여러 기기 간 최종 일관성, 깊은 통합, 다중 키 순환, 제품 차원에서 정한 클라이언트 경계). 이를 억지로 "단순화"하면 데이터가 유실되고 계층 구분만 흐려집니다.
  • 실제로 손봐야 하는 것은 "만능 모듈"과 국소적인 중복입니다. 비대해진 그룹 채팅 버스에서 상태 없는 순수 함수(프롬프트 조립, Commander 도구, CLI 턴)를 추출하고, 여러 번 복제된 "확인 대화상자" 패턴을 하나의 공유 컴포넌트로 합치는 것입니다.

이런 판단을 뒷받침하는 것은 프로젝트 제약 문서에 명시된 엄격한 원칙입니다. 경계(단일 프로세스, IPC만을 통한 통신, 런타임은 동적 로딩만 허용), 계층화(각 계층의 의존 방향), 단일 진실 공급원(범주, 텔레메트리 분류 체계, 도메인), 프롬프트에 영향을 주는 모든 커밋의 필수 "프롬프트 감사"가 해당합니다. 기반을 무너뜨리지 않고 개편할 수 있게 하는 것은 영리한 설계가 아니라 이런 불변 조건을 지속적으로 지키는 일입니다.

마무리

네 가지 방향을 합치면, 이번 전면 리팩터링은 Orkas의 에이전트 기반을 다음과 같이 바꿉니다. 직접 통제하고, 제공업체에 종속되지 않으며, 동적으로 오케스트레이션하고, 외부에 개방되어 있고, 스스로 진화할 수 있는 기반입니다:

  • 엔진/어댑터의 두 계층으로 구성된 프로세스 내 런타임이 파일 조작, 로컬 검색, 시스템 도구, 여러 작업자의 병렬 실행, 장기 문제 해결이라는 코딩 에이전트의 모든 강점을 데스크톱에 기본 제공하고 각각을 실제 운영 수준으로 만듭니다.
  • 다층 모델 계층이 키/제공업체/네트워크 문제 속에서도 가능한 한 대화를 유지합니다.
  • Commander가 루프에 참여하는 그룹 채팅 방식의 멀티 에이전트 오케스트레이션이 "정적 계획"을 "동적 의사 결정"으로 바꾸고 처음으로 에이전트 간 인계를 자연스럽게 만듭니다.
  • 생태계는 닫힌 카탈로그에서 개방형 호스트로 이동하며 외부 패키지, 전역 스킬, 사용자 정의 MCP, 역방향 브리지를 모두 개방합니다. 동시에 실행 생성 통제 지점은 조금도 흔들리지 않습니다.
  • 그리고 기본 비활성화, 범위 제한, 관찰 가능성을 갖춘 메모리와 자기 진화를 제공합니다.

기능은 하나씩 추가할 수 있지만 기반은 제대로 한 번 개편할 가치가 있습니다. 끝내고 나면 그 위에 무엇을 만들든 더 빨라집니다. 바로 그것이 이번 리팩터링이 추구한 결과였습니다.