- Draction: 바탕화면 드롭 오버레이 + 수신 인박스 + 룰/워크플로 실행 엔진
- OpenClaw: 대화 UI/AI/기억(메모리) + “룰 만들기/설명/다음 액션” 인터페이스
실행은 Draction이 책임지고, OpenClaw는 “뇌 + UX”만 담당. OpenClaw가 꺼져도 Draction은 계속 돌아가야 함.
- 바탕화면에 오버레이 이미지(캐릭터/포털) 존재
- 파일을 드롭하면:
- UI에서 “쓱 빨려 들어가는” 애니메이션
- 실제 파일은
~/Draction/Inbox/<date>/...로 move(기본) / copy(옵션)
- 드롭 영역: 기본 128x128px 오버레이 아이콘. 위치는 사용자 드래그로 변경 가능
- 다중 파일: 복수 파일 동시 드롭 가능. 각 파일마다 개별 EVENT_INGESTED 발생
- 폴더 드롭: 폴더 자체를 하나의 단위로 이동. 내부 파일은 개별 이벤트 미발생 (v0.1)
- 드래그 오버 피드백: 파일이 오버레이 위에 올라오면 시각적 하이라이트 (확대/발광)
- 진행 표시: 대용량 파일(>100MB) 이동 시 프로그레스 표시
- Inbox 이벤트 발생 → 룰 매칭 → 워크플로 실행
- 실행 상태:
- 오버레이 상태(먹는중/성공/실패)
- 간단 토스트 + “자세히” 클릭 시 로그 패널
- Draction이 OpenClaw로
EVENT_INGESTED알림 - OpenClaw는:
- “이걸 항상 같은 방식으로 처리할까?” 같은 대화형 룰 제안
- 실행 결과 요약/실패 원인 설명
- 버튼:
룰 저장,이번만,되돌리기,로그 열기,워크플로 수정
- Overlay Window (투명, always-on-top, drop target)
- Inbox Manager (파일 이동/복사, 중복 처리, Undo)
- Rule Engine (Hazel 스타일 조건 트리)
- Workflow Engine (n8n-lite 노드 실행)
- Local API/Bridge Server (OpenClaw 통신용)
- Event Log + Runs DB (SQLite)
- 시작: 로그인 시 자동 실행 (OS Login Item). 포트 충돌 시 기존 인스턴스에 위임
- 단일 인스턴스: lock 파일(
~/Draction/.lock)로 중복 실행 방지 - 종료: 실행 중인 워크플로가 있으면 완료 대기 후 종료 (최대 30초, 이후 강제 종료)
- 충돌 복구: 재시작 시
runsDB에서 status=running인 항목을 FAILED로 마킹 - 상태 파일:
~/Draction/state.json— 마지막 실행 시각, 포트 번호, PID 기록
- Draction Bridge Client (로컬 API에 연결)
- AI Assist
- 자연어 → Rule JSON 생성/수정
- 자연어 → Workflow 초안 생성(선택)
- Explain: 왜 실행됐는지, 왜 실패했는지
- UI
- “최근 ingest 이벤트”
- “이벤트 기반 룰 만들기” 버튼
로컬 전용 HTTP + WebSocket
- Draction이
127.0.0.1:<port>에 서버 오픈 - OpenClaw는 WS로 이벤트 구독
- Draction 최초 실행 시 랜덤 토큰 생성 →
~/Draction/config.json에 저장 - OpenClaw 최초 연결 시:
- Draction 트레이 아이콘에 "연결 요청" 알림 표시
- 사용자가 승인하면 토큰을 OpenClaw에 전달 (1회)
- OpenClaw는 토큰을 자체 설정에 저장
- 이후 모든 요청:
Authorization: Bearer <token>헤더 포함 - 토큰 재발급: Draction Settings에서 "토큰 초기화" → 기존 연결 해제
보안 범위: localhost 바인딩(127.0.0.1) + Bearer 토큰. 외부 네트워크 노출 없음. 나중에 mTLS까지 가고 싶으면 확장 가능하지만, v0.1은 토큰 + localhost 제한이면 충분.
Base: http://127.0.0.1:{port}/api/v1
| Method | Path | 설명 |
|---|---|---|
| GET | /rules |
전체 룰 목록 |
| GET | /rules/:id |
룰 상세 |
| POST | /rules |
룰 생성 (body: Rule JSON) |
| PUT | /rules/:id |
룰 수정 |
| DELETE | /rules/:id |
룰 삭제 |
| PATCH | /rules/:id/enabled |
활성/비활성 토글 |
| Method | Path | 설명 |
|---|---|---|
| GET | /workflows |
전체 워크플로 목록 |
| GET | /workflows/:id |
워크플로 상세 |
| POST | /workflows |
워크플로 생성 |
| PUT | /workflows/:id |
워크플로 수정 |
| Method | Path | 설명 |
|---|---|---|
| GET | /runs |
실행 이력 (쿼리: ?status=failed&limit=20) |
| GET | /runs/:id |
실행 상세 + 노드별 로그 |
| POST | /runs/:id/retry |
수동 재실행 |
| Method | Path | 설명 |
|---|---|---|
| GET | /events |
최근 이벤트 목록 |
| POST | /events/:eventId/undo |
드롭 되돌리기 (성공 시 원본 경로 반환) |
| Path | 설명 |
|---|---|
ws://127.0.0.1:{port}/ws |
이벤트 스트림 구독 |
WS 메시지 포맷:
{ "channel": "events", "payload": { /* EVENT_INGESTED | RUN_* */ } }{
"error": { "code": "RULE_NOT_FOUND", "message": "Rule rule_xxx does not exist" }
}HTTP 상태 코드: 400 (유효성), 401 (인증), 404 (미존재), 409 (충돌), 500 (내부 오류)
{
"type": "EVENT_INGESTED",
"eventId": "evt_...",
"time": "2026-03-04T10:12:00+09:00",
"source": {
"kind": "desktop_drop",
"deviceName": "MacMini",
"ip": "127.0.0.1"
},
"files": [
{
"path": "/Users/me/Draction/Inbox/2026-03-04/a.mov",
"name": "a.mov",
"ext": "mov",
"sizeBytes": 123456789,
"mime": "video/quicktime",
"sha256": "abcdef1234567890..."
}
]
}{
"type": "RUN_STARTED",
"runId": "run_...",
"eventId": "evt_...",
"ruleId": "rule_...",
"workflowId": "wf_...",
"startedAt": "2026-03-04T10:12:05+09:00"
}{
"type": "RUN_FINISHED",
"runId": "run_...",
"eventId": "evt_...",
"ruleId": "rule_...",
"workflowId": "wf_...",
"summary": "Transcoded to H.265 and moved to /nas/media/inbox",
"artifacts": [
{ "kind": "file", "path": "/nas/media/inbox/a.mp4" },
{ "kind": "link", "url": "http://..." }
]
}{
"type": "RUN_FAILED",
"runId": "run_...",
"eventId": "evt_...",
"ruleId": "rule_...",
"workflowId": "wf_...",
"failedNodeId": "n2",
"error": {
"code": "S3_UPLOAD_TIMEOUT",
"message": "Connection timed out after 30s",
"retryable": true
},
"partialArtifacts": []
}{
"id": "rule_video_intake",
"name": "Video Intake",
"enabled": true,
"when": {
"mode": "ALL",
"children": [
{ "field": "file.ext", "op": "in", "value": ["mp4", "mov"] },
{ "field": "source.kind", "op": "eq", "value": "desktop_drop" }
]
},
"then": { "workflowId": "wf_transcode_and_upload" }
}- 매칭 순서: 룰 목록의 등록 순서대로 평가 (FIFO)
- 다중 매칭: 하나의 파일에 여러 룰이 매칭되면 첫 번째 매칭 룰만 실행 (first-match-wins)
- 동시성: v0.1은 직렬 실행. 파일 1개 처리 완료 후 다음 파일 처리
- 우선순위 필드: v0.1에서는 미지원. 등록 순서가 암묵적 우선순위
v0.2 예정:
priority필드 도입, 다중 룰 동시 실행, 충돌 감지
{
"id": "wf_transcode_and_upload",
"nodes": [
{ "id": "n1", "type": "transcode", "params": { "preset": "h265_1080p" } },
{ "id": "n2", "type": "s3_upload", "params": { "bucket": "minio", "prefix": "inbox/" } },
{ "id": "n3", "type": "notify", "params": { "channel": "openclaw", "message": "✅ Done" } }
],
"edges": [
{ "from": "n1", "to": "n2" },
{ "from": "n2", "to": "n3" }
]
}- 기본 정책: 노드 실패 시 워크플로 즉시 중단 (fail-fast)
- 재시도: v0.1에서는 자동 재시도 없음. 수동 재실행만 지원 (
POST /api/v1/runs/:id/retry) - 부분 결과: 실패 전 생성된 artifact는 보존.
partialArtifacts로 조회 가능 - 알림: RUN_FAILED 이벤트를 WS로 전송. OpenClaw 연결 시 UI 토스트 표시
워크플로 실행의 상태 머신(노드별 상태 전이, 재시도 로직 등)은 별도 설계 문서 참조. →
docs/design/workflow-state-machine.md
v0.2 예정: 노드별 retry 정책, fallback 노드, 타임아웃 설정
- 위험 노드(
exec,ssh,delete)는:- 기본 비활성
- 활성화하려면 Settings에서 “위험 기능 허용” 토글 + 2차 확인
- 경로 스코프:
- 기본 허용 루트:
~/Draction/Inbox,~/Draction/Work - 그 밖 경로는 사용자 승인이 필요
- 기본 허용 루트:
- Undo:
- 드롭 후 10초 내 “되돌리기” 가능 (move의 경우 원위치 복원)
- Undo 스택: 최근 5건 유지. 10초 경과 또는 해당 파일의 워크플로 실행 시작 시 Undo 불가
- copy 모드의 경우: Inbox 사본 삭제
- API:
POST /api/v1/events/:eventId/undo(성공 시 원본 경로 반환) - 워크플로 실행 중 Undo 요청 시: 409 Conflict 응답
- OpenClaw에서만 AI 호출 (로컬 Ollama / 클라우드 OpenRouter)
- Draction은 AI를 몰라도 됨
- AI 결과는 항상 Rule/Workflow JSON으로만 전달 + Draction이 스키마 검증
- Overlay 드롭 수신 + 애니메이션
- Inbox move/copy + Undo
- Rule 1단(확장자/사이즈/발신 kind)
- Workflow 5노드만:
- move, copy, rename
- transcode(ffmpeg)
- webhook(or s3_upload 중 택1)
- Runs 로그(성공/실패/시간) + 간단 UI
- WS 구독으로 이벤트 피드 표시
- “이 이벤트로 룰 만들기” 버튼
- AI로 Rule JSON 생성(로컬/클라우드 선택) + Draction에 저장 요청
기술 스택 선택(Electron vs Tauri, 언어 선택 등)은 별도 ADR 문서 참조. →
docs/adr/001-tech-stack.md
- Overlay + Drop → Inbox move + 애니메이션
- Rule 엔진(최소) + Workflow 직렬 실행
- 로컬 API + WS 이벤트
- OpenClaw Bridge(구독 + 표시)
- AI 룰 생성(옵션) + Diff 적용 UX