Flowork를 위한 샌드박스형 AI 앱 구축: 개발자 완전 가이드
요약
Flowork 프레임워크에서 인간과 AI 에이전트가 동일한 상태를 공유하며 상호작용할 수 있는 샌드박스형 AI 앱 구축 가이드를 제공합니다. GUI 모드와 에이전트 모드를 동시에 지원하는 '하나의 상태, 두 개의 드라이버' 원칙을 통해 개발 효율성을 높이는 방법을 설명합니다.
핵심 포인트
- GUI와 에이전트 모드가 동일한 헤드리스 로직을 공유하여 일관성 유지
- iframe 기반의 샌드박싱 모델로 보안 및 격리 환경 보장
- manifest.json, core.py, ui/index.html의 3가지 핵심 파일 구조
- 매니페스트에 선언된 작업이 자동으로 GUI 버튼과 에이전트 도구로 변환
Flowork의 앱은 **프레임워크 내부에서 실행되는 독립형 프로그램 (self-contained programs)**입니다. 각 앱은 클릭 가능한 화면인 동시에 에이전트가 호출할 수 있는 도구 세트 역할을 합니다. 이러한 이중적 특성 덕분에 로직을 한 번만 작성하면 인간과 AI 에이전트가 동일한 상태 (state)를 통해 이를 실행할 수 있습니다. quant desk와 notepad가 그 예시입니다.
앱 모델의 이해
모든 앱은 동시에 두 가지 드라이버 모드로 존재합니다:
- GUI 모드: 사용자가 샌드박스형 iframe 내의 버튼을 클릭합니다.
- 에이전트 모드: 에이전트가 동일한 작업을 도구 (tool)로서 호출합니다.
두 경로가 하나의 상태를 공유하기 때문에, 두 상호작용 경로 모두 동일한 헤드리스 로직 (headless logic)을 실행합니다. 이 "하나의 상태, 두 개의 드라이버" 원칙은 중복을 제거하고 인터페이스 전반에 걸쳐 일관된 동작을 유지합니다.
앱 설치 및 관리
Apps 메뉴에는 Installed와 Store 두 개의 탭이 있습니다.
앱 설치하기:
.fwpack파일을 업로드합니다.- 앱은 사용자의 기기에서 실제 프로그램을 실행할 수 있으므로, 시스템은 설치가 완료되기 전에 사용자의 동의를 요청합니다.
앱 열기:
- iframe을 통해 격리된 샌드박스 프레임 내에서 앱을 실행합니다.
- 샌드박스형 앱은 Flowork와 직접 통신할 수 없습니다. 대신, 검증된 요청을 보냅니다. 앱이
{op, args}를 보내면 커널 (kernel)이 해당 작업이 앱의 매니페스트 (manifest)에 선언되어 있는지 확인하고, 이를 실행한 뒤 결과를 반환합니다. - 이러한 샌드박싱 모델은 신뢰할 수 없거나 버그가 있는 코드가 호스트를 벗어나거나 손상시키지 못하도록 보장합니다.
삭제하기:
- 앱을 깔끔하게 제거합니다.
디렉토리 구조 및 핵심 파일
앱을 구축하려면 apps/<id>/ 아래에 정확히 세 개의 파일이 포함된 폴더를 생성하십시오:
apps/my-app/
├─ manifest.json kind:"app" + 작업 (ops) 목록
├─ core.py 헤드리스 로직 (stdin/stdout, line-JSON을 통해 통신)
...
manifest.json
앱의 종류 (kind)를 선언하고 모든 작업 (operation)을 나열합니다. 선언된 각 작업 이름은 GUI 버튼 (인간에게 표시됨)인 동시에 에이전트 도구 (AI 에이전트가 호출 가능)가 됩니다.
core.py
헤드리스 (headless) 로직 레이어입니다. 줄 바꿈으로 구분된 JSON (line-delimited JSON)을 사용하여 표준 입력/표준 출력 (stdin/stdout)을 통해 커널 (kernel)과 통신합니다. 사용자가 버튼을 클릭하거나 에이전트가 도구를 호출하면, 이 모듈이 요청을 수신하여 비즈니스 로직을 실행합니다.
ui/index.html
샌드박스형 iframe 내부에서 렌더링되는 사용자 인터페이스 (user-facing) 화면입니다. 커널에 구조화된 요청을 보냄으로써 작업을 호출할 수 있습니다. iframe은 호스트 DOM에 접근하거나 직접적인 네트워크 호출을 할 수 없습니다.
작업 브리지 (The Operations Bridge)
매니페스트 (manifest)에 선언된 모든 작업은 자동으로 다음이 됩니다:
- GUI 버튼: 인간 사용자를 위해 샌드박스형 iframe 내에 생성됩니다.
- 에이전트 도구 (agent tool): 에이전트가 loket (커널의 권한 브로커)을 통해 호출할 수 있습니다.
인간 또는 에이전트가 작업을 트리거하면 다음과 같은 과정이 진행됩니다:
- 요청이 작업 이름 및 인자 (arguments)와 함께 커널로 전달됩니다.
- 커널은 해당 작업이 앱의 매니페스트에 선언되어 있는지 확인합니다.
- 커널은 실행을 위해 요청을
core.py로 라우팅 (routing)합니다. core.py가 이를 처리하고 결과를 반환합니다.- 결과가 호출자 (GUI 또는 에이전트 도구 호출)에게 다시 전달됩니다.
샌드박싱 및 보안 (Sandboxing and Security)
앱은 커널 및 다른 앱으로부터 격리된 WASM 샌드박스 (UI 레이어의 경우 iframe)에서 실행됩니다. 앱은 매니페스트가 특정 권한 (capabilities)을 부여하지 않는 한 파일 시스템이나 네트워크에 직접 접근할 수 없습니다. 샌드박스형 앱에서 커널로 보내는 모든 호출은 다음과 같이 검증됩니다:
- 작업 이름이 매니페스트에 존재해야 합니다.
- 인자 (arguments)에 대한 타입 체크 (type-check)가 수행됩니다.
- 검증을 통과한 경우에만 결과가 반환됩니다.
이 모델은 신뢰할 수 없거나 잘못 작성된 앱이 다음과 같은 행위를 하는 것을 방지합니다:
- 임의의 파일을 읽거나 쓰는 행위.
- 승인되지 않은 네트워크 요청을 보내는 행위.
- 다른 에이전트의 메모리 또는 상태에 접근하는 행위.
- 커널 자체를 충돌시키는 행위.
첫 번째 앱 구축하기
apps/my-app/아래에 **폴더 구조를 생성 (Create the folder structure)**합니다.- 수행할 작업(operations)과 그 시그니처(signatures)를 나열하는 **manifest.json을 작성 (Write manifest.json)**합니다.
- stdin으로부터 JSON 요청을 읽고 stdout으로 결과를 쓰는 로직을 포함하여 **core.py를 구현 (Implement core.py)**합니다.
- 사용자 인터페이스로서 **ui/index.html을 생성 (Create ui/index.html)**하고, 각 작업에 대해 커널(kernel)을 호출하도록 만듭니다.
- **.fwpack으로 패키징 (Package as a .fwpack)**합니다 (매니페스트와 세 개의 파일을 압축).
- Apps 메뉴를 통해 업로드 (Upload via the Apps menu) → **설치 (Install)**합니다.
설치가 완료되면 앱은 핫 로드(hot-loaded)됩니다. 커널을 다시 빌드하거나 재시작할 필요가 없습니다. 나중에 앱을 업데이트해야 하는 경우, 기존 앱을 삭제하고 새로운 .fwpack을 다시 설치하면 됩니다.
원칙: 한 번 작성하여 두 번 사용하기 (Write Once, Use Twice)
Flowork 앱 모델의 강점은 "인간용 UI"와 "에이전트용 API"를 위해 별도의 경로를 작성할 필요가 없다는 점입니다. 대신 다음과 같이 작동합니다:
- 매니페스트(manifest)가 앱이 무엇을 할 수 있는지 선언합니다.
- 헤드리스 로직(
core.py)이 모든 케이스를 처리합니다. - UI 레이어는 얇게 유지됩니다. 즉, 인간이 클릭할 것과 동일한 작업(operations)을 호출합니다.
- 에이전트는 동일한 작업을 프로그래밍 방식으로 호출합니다.
이러한 접근 방식은 앱을 추론, 테스트 및 유지 관리하기 더 쉽게 만듭니다. 로직의 버그를 수정하면 모든 곳에서 수정되며, 새로운 작업이 추가되면 인간과 에이전트 모두에게 즉시 사용 가능해집니다.
Flowork는 오픈 소스입니다 — 두 제품 모두:
- 🤖 Flowork Agent (셀프 호스팅 에이전트 OS): https://github.com/flowork-os/Flowork_Agent
- 🛣️ Flow Router (주권적 LLM 게이트웨이): https://github.com/flowork-os/flowork_Router
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기