2026-07-15
에이전트 도구를 사용한 사람이 아니라, 에이전트 플랫폼을 운영하고 그 위에 자기 계층을 쌓은 사람입니다. Linux 인프라 위에서 런타임을 운영하며 메모리, 디스패치, 검토 가능한 개발 루프, 그리고 사람이 이어받을 문서 체계를 만들었습니다.
운영이 먼저 있었고, 계층은 그 다음에 나왔습니다.
stuck session 한 줄도 배포 중단 사유,
그리고 응답성이 SLO.판단의 규율 — 도구가 시키는 대로 하지 않습니다. 진단 도구의 보안 권고를 우리 배포 맥락에서 검토해 거짓 양성으로 판정하고 적용하지 않았습니다. 설정을 재작성하는 자동 수정 옵션도 쓰지 않습니다. AX 도입이 실패하는 가장 흔한 방식이 /도구의 권고를 이유도 모른 채 따르는 것/이고, 그에 대한 반례를 운영 기록으로 갖고 있습니다.
AGENTS.md
는 영속 기준선, NEXT.md 는 세션 간 인계,
스킬 문서는 실행 계약입니다. 사람이든 에이전트든 같은 규칙을
읽습니다.NixOS로 노트북·서버·ARM 장치를 선언적으로 관리합니다. 컨테이너 서비스, GPU 워크로드, Yocto 임베디드 Linux, glibc와 musl, ARM과 RISC-V를 같은 재현성 원칙으로 다룹니다. 환경이 재현되지 않으면 운영 판단도 재현되지 않습니다.
Claude Code와 Codex를 매일 씁니다. 그러나 이 항목의 답은 사용량이 아닙니다. 하네스가 세션을 넘어 위임·연속성·공유 도구를 보존하도록 entwurf를 만들었고, 40개 이상의 스킬을 설계·운영했습니다. 도구 사용자가 아니라 하네스 운영자입니다.
Go와 Clojure로 API, 단일 바이너리 서비스, IoT 백엔드, 데이터·운영 CLI를 만들었습니다.
경계: Java/Spring 직접 경험을 Go/Clojure 경험으로 바꾸어 쓰지 않습니다. JVM과 GraalVM은 Clojure 서비스의 빌드와 운영에서 다룹니다.
대시보드를 하나 더 만들지 않습니다. 도메인의 주인에게 에이전트를 붙입니다. 운영팀이 실제 상담 데이터를 자연어로 묻고 근거를 개별 대화까지 역추적하는 워크벤치, 장애 증거를 살아 있는 원본에서 회수하는 읽기 전용 워크벤치가 그 사례입니다. 모든 시각은 하나의 시간축으로 정규화하고, 수치는 원 이벤트까지 되짚을 수 있게 둡니다.
문제에 따라 Go HTTP 서비스, Clojure 서버 렌더링, 정적 웹, React/Preact/Lit 컴포넌트를 선택했습니다. 프레임워크 이름보다 배포 단위와 운영 경계를 먼저 정합니다.
PostgreSQL JSONB, pgvector, SQLite, LanceDB, MQTT, AWS IoT, Oracle ARM VM, Docker와 GPU 컨테이너를 실제 시스템에서 다뤘습니다.
andenken은 메모리를 세 축으로 가릅니다 — 응답 전 차단형 리콜, 임베딩 검색, 야간 통합. 일반적인 RAG 스택과 다른 지점이 여기입니다. 현재 구현된 축은 임베딩입니다: LanceDB, Qwen3-Embedding-8B(4096차원), 벡터와 BM25 하이브리드에 점수 정규화, 한↔︎영 교차 질의 확장, 그리고 회수(recall) 추적.
회사에서는 임베딩·리랭킹 서빙과 업무 문서 파이프라인을 운영했습니다.
경계: 파인튜닝 중심이 아닙니다. 정직하게 밝힙니다. 강점축은 임베딩 서빙, 리랭킹, 검색 품질 최적화, 프롬프트·체인 설계 라는 실서비스 최적화 축입니다.
BMAD 직접 사용 경험은 없습니다. 대신 그 방법론이
다루는 문제층 — 역할 분리, 구조화된 계획, 컨텍스트를 실은 인계, 규모별
깊이 조절 — 을 AGENTS/NEXT 문서 계약,
entwurf의 위임, forge-config의 리뷰 게이트로 독립적으로 구현했습니다.
동일하다고 주장하지 않고, 차이를 설명할 수 있는 구현을
제시합니다.
AWS IoT, Oracle Cloud ARM, Cloudflare Zero Trust, Netlify에서 서비스를 개발·운영했습니다.
React 19와 @a2ui/react 기반 A2UI 뷰어,
Preact/TSX 가든 컴포넌트, Lit 웹컴포넌트를 구현했습니다. 같은
A2UI 개념을 서로 다른 렌더러 위에 두 번 구현했다는 것이 실제
증거입니다 (Lit / React).
경계: Tailwind 직접 사용 경험은 없습니다. SCSS 변수와 디자인 토큰을 사용했습니다.
역할과 파일 경계를 먼저 나눠 병렬 에이전트 작업에서도 충돌을 막고, 대화를 durable issue와 리뷰 가능한 기록으로 굳힙니다. 회사에서는 운영·제품·개발 조직이 이어받을 수 있는 형태로 도구를 넘겼습니다.
같은 데이터라도 독자의 행위가 달라지면 문서 표면도 달라져야 합니다. 개발자에게는 재현 명령과 불변식을, 비개발자에게는 일일 판독과 근거 링크를 제공합니다.
에이전트 런타임(OpenClaw)을 2026년 2월부터 6월까지 운영했습니다. Oracle Cloud ARM 인스턴스 위의 Docker, 메신저 채널 다중 연동, 실사용자 트래픽이 걸린 환경입니다.
핵심 조건이 하나 있습니다. 업스트림은 1인이 유지하는 프로젝트이고, 우리 조직에는 업스트림 담당자가 없습니다. 그래서 "버전을 올린다"가 곧 "릴리즈의 의미를 내 환경으로 번역한다"가 됩니다. 이 조건이 아래 두 인시던트의 배경입니다.
두 버전을 한 번에 건너뛴 뒤 응답 지연이 급증했습니다.
stuck session: state=processing age=164s
여기서 실제로 값이 나가는 판단은 롤백 대상 선택입니다. "한 단계 내린다"가 아니라 이미지 생성이 별도 API 키를 요구하지 않는 마지막 판이 어디인가 를 물었습니다. 최신을 고집하지 않는 것과 아무 데나 되돌리는 것은 다릅니다.
그리고 고친 것은 코드가 아니라 규칙입니다.
stuck session 한 줄이면 그것만으로
배포 중단 사유.다음 판으로 재시도했더니 10분 만에 같은 인시던트가 재현됐습니다. 여기서 릴리즈 노트를 읽는 방식이 달라집니다. "무엇이 새로 생겼나"가 아니라 내 증상의 원인을 정면으로 고친 줄이 있는가 를 찾았습니다.
두 줄을 식별했습니다. 광범위한 런타임 프리로드를 실제 설정된 플러그인 id로 한정한 것, 그리고 플러그인 도구 서술자를 캐시한 것. 정확히 인시던트 ①의 근본 원인 가설이 가리키던 지점입니다. 중간 판들을 건너뛰고 그 판으로 직행했습니다.
| 지표 | before | after |
|---|---|---|
| 부팅 | 45.4초 | 7.3초 → 하드닝 후 5.8초 |
| 메모리 | 816 MiB | 246 MiB |
| 핫패스 의존성 스테이징 | 발생 | 0 |
동반 작업으로 운영에서 물러난 컴포넌트를 정리하고, 정체·유령 세션을 72개에서 16개로 줄이고, 컴파일 캐시와 재기동 억제 옵션으로 하드닝했습니다.
이후 판이 플러그인 탐색을 엄격하게 바꾸면서, 오래전에 사라진 컴포넌트를 가리키던 죽은 설정 경로가 hard-fail로 승격되어 크래시 루프가 났습니다. 설정을 통째로 되돌리지 않고 그 줄만 외과적으로 제거해 복구했습니다. 결과는 설정 경고 0건.
진단 도구가 낸 보안 권고를 우리 배포 맥락에서 검토해 거짓 양성으로 판정하고 적용하지 않았습니다. 설정을 재작성하는 자동 수정 옵션도 쓰지 않았습니다. 그 도구는 인시던트 ①의 근본 원인 가설에 등장하는 바로 그 도구입니다.
이유를 모른 채 무조건 따르면 위험하다 는 판단을 기록으로 남겼습니다. *AX 도입이 실패하는 가장 흔한 방식이 도구의 권고를 검증 없이 따르는 것이고, 저는 그 반례를 운영 기록으로 갖고 있습니다.*
운영은 한 제품 설정 안에 머물지 않고 세 계층으로 분리되었습니다.
OpenClaw 운영 (업스트림 추적 · 버전 · 인시던트 · 메모리)
│
├─→ andenken 메모리를 런타임에서 떼어내 독립 계층으로
├─→ entwurf 하네스 간 디스패치와 연속성
└─→ forge-config 검토 가능한 개발 루프 · sweeper
"에이전트 하네스를 쓴 사람"이 아니라 "에이전트 플랫폼을 운영하고, 그 위에 자기 계층을 쌓아 올린 사람"입니다.
andenken은 과거 세션과 공개 지식베이스를 같은 검색면에서 다루는 시맨틱 메모리입니다. 런타임 내부 기능으로 채팅 기록을 가두지 않고, 다른 하네스가 소비할 수 있는 독립 계층으로 꺼냈습니다.
설계의 핵심은 메모리를 세 축으로 가른 것입니다.
| 축 | 하는 일 | 상태 |
|---|---|---|
| active recall | 답변 전 차단형 리콜, 타임아웃 경계 | 하네스 쪽 (이 리포 밖) |
| embedding | 벡터와 BM25 하이브리드, 점수 정규화 | 구현·운영 중 |
| dream | 야간 통합, 기억의 증류 | 미구현 (별도 로드맵) |
구현 스펙은 LanceDB, Qwen3-Embedding-8B(4096차원), 세션과 공개 가든 두 트랙, 한↔︎영 교차 질의 확장(한국어 형태소 분석과 영어 태그 매핑을 별도 CLI로 분리), 그리고 회수 추적입니다. 무엇이 실제로 다시 불려 나왔는가는 기억 통합의 입력이 됩니다.
RAG를 "청킹·임베딩·벡터DB"로 묶어 말하지 않는 이유가 여기 있습니다. 검색은 세 축 중 하나이고, 언제 리콜을 차단형으로 걸 것인가와 무엇을 남기고 무엇을 증류할 것인가가 나머지 둘입니다.
entwurf는 Claude Code, Codex 같은 서로 다른 하네스가 상대의 인증·대화록·런타임을 소유하지 않고, 정체성만으로 서로를 호출하게 하는 얇은 기층입니다.
여기에는 자기 리포로 증명되지 않는 것이 하나 있습니다 — 수용(reception). 자기 저장소는 능력을 보여주지만, 남이 그것을 실제로 썼는지는 보여주지 못합니다.
이 두 줄은 가장 위조하기 어렵고, 회의적인 독자가 가장 먼저 확인하는 줄입니다. 그래서 서류에서 지우지 않습니다.
forge-config는 도메인 오너와의 대화에서 발견된 요구를 셀프호스팅 Forgejo 이슈로 굳히고, 봇이 그것을 해당 도메인 에이전트에게 읽기 전용 1차 리뷰로 넘기고, 결과를 durable store에 남기는 루프입니다.
도메인 오너가 도메인 봇과 대화
→ 요구·버그·반복되는 고통이 감지됨 (봇 또는 sweeper)
→ 라벨 + 소스 컨텍스트를 달아 이슈 생성
→ forgebot이 라벨/웹훅으로 깨어남
→ 해당 owner agent에게 read-only 1차 리뷰 요청
→ reality check · risk · scope · 구현필요여부 · 우선순위 반환
→ forgebot이 리뷰를 기록하고 triage 종료
→ 사람이 정렬된 백로그를 보고 focused batch로 구현을 부른다
문서에 명시적으로 박아둔 non-goal이 셋입니다. 자동 코딩 공장이 아니고, 운영팀용 대시보드 제품이 아니고, 무엇을 구현할지 사람이 정하는 일을 대체하지 않습니다.
forgebot 은 dispatcher이자
recorder이지 implementer가 아닙니다.AX 도입이 실패하는 두 번째 전형이 "에이전트에게 구현을 통째로 맡기는 것"입니다. 호스팅 코딩 에이전트를 타깃으로 삼지 않은 이유를 저는 문서로 설명할 수 있습니다.
sweeper와 auto-fix 레인에서는 보수적 기본값, 변경 전 리뷰, durable report, 마커가 실린 코멘트, 스냅샷 드리프트 가드, 결정적 변경 게이트를 채택했습니다. 템플릿 마커가 스키마, 리포트 id, 세션 키, 이슈 갱신시각, 라이프사이클 라벨, 모델, 설정 커밋을 기록합니다.
목적은 하나입니다 — 세션 메모리와 웹훅 재생(replay)이 현재 Forge 상태를 절대 이기지 못하게. 에이전트가 "내가 아까 처리했다"고 기억해도, 권위는 durable store에 있습니다.
실증 착지: auto-fix v0가 두 리포에서 GREEN입니다. 라벨 감지에서 리포트 생성, 완료 전이까지 돌았고, 재생·멱등성 스모크에서 리포트 중복 생성이 없었습니다. v1에서는 경계가 제한된 워크스페이스 가드 패치를 실제로 수행하고, 매칭 실패를 또 하나의 비치명적 sweep 케이스로 노출하고, 수정 후 회귀 통과까지 확인했습니다.
상류 런타임은 transport, auth, model, gateway, lifecycle을 "봇이 깨어날 때까지" 소유하고, forge-config는 lifecycle protocol, auto-fix semantics, sweeper semantics, validation loop, follow-up 규칙을 소유합니다. 이 경계를 그을 수 있다는 것 자체가 플랫폼 운영자의 표식입니다.
이미 돌아가는 IoT·상담 시스템을 새 플랫폼으로 갈아엎지 않았습니다. 자연어 질의를 기존 DDL, 디바이스 로그, 런타임 미러, 상담 근거로 연결하되 읽기 전용 경계를 유지했습니다.
이것이 우대사항의 "DB·MQ·컨테이너 이해"보다 한 층 위의 답이라고 생각합니다. 도메인의 주인이 자기 데이터를 자기 언어로 물을 수 있게 만드는 일이고, 비개발 영역 AX 전환의 실제 모양입니다.
경계: 고객사와 사내 도구의 식별 가능한 세부는 공개면에 쓰지 않습니다. 여기서는 역할과 구조만 말하고, 검증 가능한 공개 저장소를 그 옆에 둡니다.
Zigbee/Wi-Fi 펌웨어, Go 서버, Flutter 앱을 연결해 양산 제품으로 출하했습니다. 연결형 배포는 AWS IoT를, 폐쇄망은 로컬 백엔드가 같은 프로토콜을 제공하고, 펌웨어는 수정 없이 양쪽을 사용합니다.
이 경험은 이 서류의 중심축이 아닙니다. 다만 AX 계층 아래 의 DB·MQ·프로토콜·디바이스 현실을 이해하고 있다는 배경 신뢰도로 둡니다. 에이전트를 붙일 대상이 무엇으로 만들어졌는지 모르면, 붙이는 방식도 틀립니다.
| 주장 | 확인할 곳 |
|---|---|
| 에이전트 디스패치와 연속성 | entwurf |
| 세션·지식 메모리 | andenken |
| 검토 가능한 개발 루프 | forge-config |
| 임베디드와 엣지 AI | homeagent-config |
| 재현 가능한 Linux 기반 | nixos-config |
| 공개 지식·문서 체계 | Digital Garden |
| 라이브 작업·통계 표면 | Agenda · /api/stats |
| 제3자의 확장 | entwurf #40 |
| 제3자가 받아들인 코드 | ghostel #343 · #510 |
마지막 두 줄이 수용(reception)의 증거입니다. 자기 저장소는 능력을 보여주지만, 저자가 유일한 심판인 닫힌 루프를 의심하는 독자에게는 답이 되지 않습니다.
사람이 손으로 기록한 생활과 저널, 에이전트가 남긴 stamp, 실제 커밋과
노트를 하나의 KST 축에서 읽습니다. 원본(FULL)은 제목과 참조를 품으므로
공개하지 않습니다. 아래는 allowlist로 집계한 공개
판독이고, timeline/project.py 가 FULL과
스냅샷의 짝(바이트 지문)을 검증한 뒤에만 생성합니다. 같은 입력이면 같은
바이트가 나오고, 날짜는 하나도 손으로 적히지 않았습니다.
에이전트를 수십 개 붙여도 지나간 시간은 만들어낼 수 없습니다. 이 축은 산출물이 아니라 하루를 셉니다. 같은 기간을 어느 깊이까지 읽느냐에 따라, 살았지만 아무 산출물도 남기지 않은 날이 보이거나 사라집니다.
| 깊이 | 무엇이 보이나 | 기록의 성격 | 커버리지 |
|---|---|---|---|
| 0 | 산 대로의 하루 — 수면 · 가족 · 독서 · 본짓 | 의도 | 194일 / 194일 |
| 1 | 그날 손으로 적은 것 | 의도 | 133일 / 194일 |
| 2 | 에이전트가 남긴 스탬프 | 잔여물 | 136일 / 194일 |
| 3 | 커밋과 노트 | 잔여물 | 187일 / 194일 |
렌즈를 바꾸면 며칠이 사라지는가. 창은 2026-01-01 이상 2026-07-14 미만(KST)이고, 그 사이의 모든 날 194일이 분모입니다.
| 읽는 렌즈 | 보이는 날 | 사라지는 날 |
|---|---|---|
| 깊이 2·3 — 잔여물만 (에이전트 스탬프 · 커밋 · 노트) | 192일 | 2일 |
| 깊이 1·2·3 — 잔여물 + 손으로 적은 저널 | 193일 | 1일 |
| 깊이 0 포함 — 산 대로의 하루 | 194일 | 0일 |
잔여물이 통째로 침묵한 날. 커밋도 노트도 에이전트 스탬프도 없는데, 산 시간은 있습니다. 산출물만 읽는 판독기에게 이 날들은 공백입니다.
이 판독의 출처. 인용은 내용 지문 하나로 하지 않습니다 — 같은 내용이라도 창이 다르면 다른 판독이고, 소스가 부분적이면 다른 품질이며, 깊이 0을 만든 도구가 다르면 다른 손이 적은 것입니다.
as_of)src_tree)bbcc7d483f4537b9 5d130e1c356c57d1 31353a71
관측 지문 content_sha256
11be45396ace7834 37e1f393d7dc36cd f455332977117322 e3d39da6d8237f7b
수집기 code_sha256 — collector 0.7.0
a847831b2edd8294 6279753e1ec5b3a0 77a50d83a01e2dd5 0308a99ffb6f3ca4
이 지문이 증명하지 않는 것. 해시는 바이트와 내용이 같은지, 바꿔치기가 없었는지를 확인할 뿐입니다. 이 코드가 실제로 돌았음도, 소스가 진실하고 완전함도 증명하지 않습니다. 깊이 0은 폰에서 손으로 export한 1인칭 기록이라 외부에서 원본을 재구성할 길이 없고, 확인할 수 있는 것은 파생의 일관성입니다. 원본(FULL)은 제목과 참조를 품으므로 공개하지 않습니다 — 이 문서에는 집계만 나옵니다. 시간 블록은 시작 날짜에 귀속되며, 하루를 24시간 파티션으로 나눈 것이 아닙니다.
큰 숫자는 장식이 아니라 더 깊은 기록으로 들어가는 입구입니다. 공개 통계는 라이브 endpoint와 함께 제시하고, 프로젝트 수치는 기간·포함정책·검증 링크를 붙입니다.
Timeline projection. 위 「시간축」의 표는 공개 allowlist 산출물
timeline/projection.md에서 왔다. 생성기는 스냅샷과 FULL의 짝을 먼저 검증하고,
같은 입력에서 같은 바이트를 낸다. 제목·참조·시간블록 코멘트는 집계에 들어가지 않으며, LOCAL
axis.html은 임베드하지 않는다. 인터랙티브 컴포넌트는 이 자리에 붙되, 데이터가
먼저다 — 지금 읽고 있는 숫자가 그 데이터다.
주장을 키우는 것보다 어디까지가 내 것이 아닌지 먼저 말하는 것이 신뢰를 만든다고 봅니다.