시스템 구조

careerly ax 가 내부적으로 어떻게 굴러가는지

내부 구조

careerly ax — 내부 시스템 구조

어떻게 굴러가는지: 데이터 플로우, 에이전트 처리 시퀀스, 인프라 토폴로지, 배포 흐름까지 한 페이지에. 동적 정보는 API에서 실시간 갱신, 정적 다이어그램·매핑은 inside-config.ts 한 파일만 손보면 된다.

에이전트/워크플로우/헬스/Qdrant 통계는 실시간.·다이어그램·가이드 링크는 정적.

TL;DR

Slack 멘션 → OpenClaw Gateway(:18789, 호스트 프로세스) → account/채널 룰로 라우팅 → 해당 에이전트의 tmux Claude Code 세션이 turn 처리 → MCP seeso-knowledge 로 Qdrant Cloud 조회 → Slack 회신. 모든 사용자 프롬프트는 ax-prompt-hook 으로 자동 색인.

사람은 ax.careerly.co.kr → Caddy → ax-dashboard (Next.js, Docker :3333) 으로 접근. 대시보드는 호스트의 OpenClaw / 호스트 또는 Cloud 의 Qdrant 를 모두 본다.

라이브 헬스

/api/health/all — 30초 갱신

시스템 아키텍처

inbound (Slack) + HTTP (사람) 두 갈래

호스트
Docker
외부
inbound — Slack 메시지 처리
Slack 사용자
멘션 / 슬래시
외부
OpenClaw Gateway
:18789
turn orchestrator
호스트
에이전트 라우팅
openclaw.json bindings
호스트
Claude Code 세션
tmux + CLI
호스트
MCP seeso-knowledge
uv run python
호스트
Qdrant Cloud
벡터 DB (14+ 컬렉션)
외부
HTTP — 대시보드 / 사람 접근
사용자 브라우저
ax.careerly.co.kr
Caddy
HTTPS reverse proxy
호스트
ax-dashboard
:3333
Next.js 16
Docker
dashboard 컨테이너는 OPENCLAW_HOST=http://172.17.0.1:18789 으로 호스트 게이트웨이 호출. ~/.openclaw 는 :ro 마운트.

에이전트 처리 시퀀스

Slack 메시지가 응답이 되기까지

  1. 1.
    사용자가 Slack 채널에서 봇 멘션 (`requireMention: true` 정책).
    openclaw.json → channels.slack.accounts.*.channels
    external
  2. 2.
    Slack socket mode → OpenClaw Gateway가 이벤트 수신 (호스트 :18789).
    openclaw.json → gateway.port=18789, gateway.bind=lan
    host
  3. 3.
    Gateway가 bindings 룰로 account/channel → agentId 라우팅.
    openclaw.json → bindings[]
    host
  4. 4.
    해당 에이전트의 tmux Claude Code 세션에 프롬프트 전달.
    ~/.openclaw/agents/{id}/agent/soul.md
    host
  5. 5.
    Claude Code가 추론 중 필요시 MCP 도구 호출 (seeso-knowledge.search 등).
    openclaw.json → mcp.servers.seeso-knowledge
    host
  6. 6.
    MCP가 Qdrant Cloud로 임베딩 검색 → 결과 반환.
    data-ontology/mcp-server (uv run python)
    external
  7. 7.
    Claude 응답 생성 → OpenClaw가 Slack chat.postMessage 로 회신 (streaming=partial).
    openclaw.json → channels.slack.accounts.*.streaming
    external
  8. 8.
    ax-prompt-hook이 UserPromptSubmit 이벤트로 프롬프트 캡처 → dashboard /api/prompts → SQLite + Qdrant L0_episode 적재.
    hooks/ax-prompt-hook.js
    host

데이터 플로우

수집 → 색인 → 검색 → 활용

수집
  • · Claude Code 프롬프트 — UserPromptSubmit 훅
    hooks/ax-prompt-hook.js
  • · Slack 메시지 — 정기 수집 잡 (workflows 인벤토리)
  • · Git commits / PR — 정기 수집 잡
  • · 사용자 제출 — /app/data/contribute (UI / URL / 파일)
  • · API 박제 — POST /api/data/decision · /claim
  • · MCP store — Claude 세션이 직접 record_claim / record_decision
색인
  • · OpenAI text-embedding-3-small 로 임베딩
    openclaw.json plugins.qdrant-rag.config
  • · Qdrant Cloud (678c5aa2-…aws.cloud.qdrant.io)
  • · v2 온톨로지: 도메인 × layer 매트릭스 (careerly / seeso / medi / somoon / ax / data-ontology × L0~L5)
  • · 현재 14+ 컬렉션 — /api/data/stats 에서 라이브 카운트
검색
  • · MCP seeso-knowledge — search / get_recent / walk / related_to / link / record_*
    openclaw.json mcp.servers.seeso-knowledge
  • · Dashboard API — /api/data/search · /walk · /recent · /collections/[id]
  • · refs[] 그래프 traversal — 한 hop씩 walk
활용
  • · 에이전트 추론 중 MCP 호출 (인-루프)
  • · /app/data — UI 탐색 (도메인·layer별 dive)
  • · /app/board — 작업별 컨텍스트로 참조
Qdrant 컬렉션 — 라이브

에이전트 인벤토리

/api/openclaw/agents — 30초 갱신

설정 위치 ~/.openclaw/openclaw.json (agents.list / bindings)
에이전트별 soul ~/.openclaw/agents/{id}/agent/soul.md

워크플로우 인벤토리

/api/workflows/inventory — 60초 갱신

상세는 /app/workflows.

가드레일 — careerly-safeguard-v2

에이전트 사고 방지 3중 레이어 (Week 1 observe)

careerly-safeguard-v2Week 1 — observe25/25 PASS · FP 0실 worktree e2e ✓main 384a983
FAIL 도 차단하지 않고 코멘트만. 1주 뒤 retro → enforce 전환 결정.
검증 내역: 합성 dry-run 11/11 · 합성 e2e 11/11 · 실 worktree e2e 3/3 · false-positive 0. main HEAD = 384a983 (fix(safeguard): Stop hook worktree path whitelist).
Task 4e95d077: L2 BLOCK (INC-002 AKIA) + L2 자가 수정 루프 + L3 Stop hook (worktree fix) — 실 worktree 환경
3개 레이어 — prompt → hook → reviewer
L1
사전 가드레일
prompt-level 컨텍스트
에이전트가 작업 시작 시 자동으로 로드. 과거 인시던트 20건이 규칙으로 박제돼 있다.
  • · careerly/CLAUDE.md
  • · .claude/incidents.md (INC-001~020)
L2
Hooks
settings.json + scripts (9 룰)
Bash·Write·Edit·git push 직전에 정적 검사. stderr 로 에이전트에 피드백 → 자가 수정 루프.
  • · careerly/.claude/settings.json
  • · .claude/scripts/*
  • · PreToolUse / PostToolUse / Stop
L3
Reviewer sub-agent
Sonnet, read-only
Stop 훅이 호출. diff/스택 변경 종합 검토 후 리스크 코멘트만. write 권한 없음.
  • · careerly/.claude/agents/careerly-reviewer.md
9 룰 — 위반 시 동작
ID검사 내용레이어동작
INC-002.env AKIA / OIDC 토큰 노출L2BLOCK
INC-003git author bartkim0426 (SeeSoRuFree 아님)L2BLOCK
INC-004prod DB endpoint 접근L2BLOCK
INC-005ASG instance ID i-XXX 직접 사용L2BLOCK
INC-006git push --force mainL2BLOCK
INC-007migration 번호 충돌L2WARN
INC-013requirements 누락L2WARN
PROTECTEDsettings.json / incidents.md / agents/ / workflows/ 수정L2BLOCK
StopStop hook reviewer nudge (worktree 환경 인식 ✓)L3NUDGE
BLOCK도구 호출 중단WARN경고만, 진행 허용NUDGE메시지만 (observe 단계)
자동 리액션 루프 — 영상의 핵심
에이전트 시도
Bash / Edit / git push
Hook BLOCK
stderr 로 사유 전달
에이전트 자가 수정
메시지 읽고 재시도
Hook stderr → 봇이 메시지 보고 자가 수정 → 다시 시도. 영상의 핵심 메커니즘.
자체 보호 + 우회 — 지식 부패 방지 사이클
Stop hook worktree fix (commit 384a983) 자체가 PROTECTED 차단을 받았다
safeguard-stop-reviewer.sh 수정은 가드레일 본체 변경 → PreToolUse 가 PROTECTED 로 차단. dev-bot 이 override-log.jsonl 에 사유 ("e2e 검증에서 발견된 worktree path 누락 — 가드레일 자체 정확도 향상") append → 60s 윈도우 안에서 통과 → 정상 commit + push. 영상의 "가드레일이 자기 자신 보호 + 정당 우회는 영구 로그" 사이클이 실제 작업 도중 발동된 메타 사례.
우회 메커니즘: .claude/override-log.jsonl 에 사유 append → 60s skip. 모든 우회는 영구 로그.
가드레일 메트릭 — 블로그 권고 #54~#58 (3-6개월 리뷰 사이클)
Blog Best Practices Map
블로그 89 권고 매핑
67
/ 89 구현
8 카테고리. 아래 매트릭스에서 카테고리별 ✓/△/✗ 확인.
카테고리별 매핑 — 우리 시스템과 블로그 권고의 cross-check
범위카테고리구현상태
#1~#10
기본 설정 + 컨텍스트
Setup & context
주요 권고: CLAUDE.md / AGENTS.md / starting context 모두 적용.
  • · careerly/CLAUDE.md, AGENTS.md
  • · ax-poc inside-config.ts (정적 사실)
  • · ax 보드 task systemGuide (#50 매핑)
9/10✓ 구현
#11~#22
권한 + 도구 제어
Permissions & tools
permissions.deny + Bash whitelisting 활성. ide MCP 격리 부족분.
  • · careerly/.claude/settings.json (permissions.deny)
  • · Task #2 (settings PR — blog #7,#13)
10/12✓ 구현
#23~#35
Hooks (PreTool/PostTool/Stop)
Hooks
Layer 2 가드레일 = 영상의 핵심. exit 2 BLOCK + stderr 자가수정 루프.
  • · careerly/.claude/SAFEGUARD_HOOKS.md
  • · careerly/.claude/scripts/* (PreToolUse, PostToolUse, Stop)
  • · 9 룰 (INC-002/003/004/005/006/007/013 + PROTECTED + Stop)
13/13✓ 구현
#36~#49
Sub-agents + 검수 루프
Sub-agents
read-only reviewer + STATUS PASS/WARN/FAIL → 자가 재시도 패턴.
  • · careerly-reviewer (read-only Sonnet)
  • · Stop hook → reviewer 자동 호출
  • · PR 리스크 코멘트 (Week 1 observe)
11/14✓ 구현
#50~#58
Starting context + 리뷰 사이클
Starting context & review cycle
3-6개월 리뷰 사이클 — 이 페이지의 incidents freshness 카드가 시그널.
  • · ax 보드 task → systemGuide 가드레일 reminder (#50)
  • · 이 페이지: incidents.md mtime + override 30d 집계 (#54~#58)
7/9✓ 구현
#59~#68
테스트 + e2e 검증
Testing
가드레일 자체 e2e 는 두텁다. 앱 코드 e2e 는 별도 트랙 (out of scope).
  • · careerly-safeguard 합성 dry-run 11/11 + 합성 e2e 11/11
  • · 실 worktree e2e (Task 4e95d077) 3/3
5/10△ 부분
#69~#78
관찰가능성 + 메트릭
Observability
운영 메트릭은 inside 페이지로. 외부 알람 (PagerDuty 등) 미연결.
  • · ax-poc /app/inside (라이브 헬스, 에이전트, 워크플로우, Qdrant, safeguard)
  • · Langfuse (옵션)
  • · override-log.jsonl 집계 (이번 PR)
6/10△ 부분
#79~#89
팀 운영 + 거버넌스
Team operations
팀 단위 거버넌스는 정착 중. 정기 retro 사이클 (#54~#58 매핑 데이터) 으로 보강.
  • · ax 보드 (task → worktree → PR 사이클)
  • · TeamCreate 멀티에이전트 패턴
  • · override-log.jsonl (모든 우회 영구 로그)
6/11△ 부분
소스: claude.com — How Claude Code works in large codebases (89 권고). 매트릭스는 정적 — 새 권고 적용 시 inside-config.ts BLOG_RECOMMENDATIONS 갱신.

인프라 토폴로지

호스트 / Docker / 외부

호스트 프로세스
OpenClaw Gateway
Slack 이벤트 ↔ Claude Code turn orchestrator. PM2가 관리.
host :18789 (token auth)
Claude Code 에이전트 세션
에이전트 id별 tmux 세션 안에서 Claude Code CLI 상주. ~/.openclaw/agents/{id}/agent/soul.md 로드.
tmux ls
Caddy reverse proxy
ax.careerly.co.kr → dashboard:3333. ACME 자동 인증서.
ax-prompt-hook
Claude Code UserPromptSubmit 훅. 프롬프트 → dashboard /api/prompts 로 POST → Qdrant L0_episode 적재.
hooks/ax-prompt-hook.js
seeso-claude-bot
Slack/Claude turn orchestrator 보조 데몬 (BOT_INTERNAL_URL=:3456).
PM2
Docker 컨테이너
ax-dashboard
이 페이지. Next.js 16. compose.yml에 정의된 유일한 서비스.
:3333 → :3000 (container)
외부 서비스
Qdrant Cloud
벡터 DB. v2 멀티레이어 온톨로지 (L0 episode → L5 doctrine, 14+ 컬렉션).
678c5aa2-…aws.cloud.qdrant.io
Slack
Events API + chat.postMessage. socket mode. 4개 워크스페이스 account (careerly / strategy / data / seulchan).
Anthropic API
Claude (Sonnet/Opus) — 에이전트별 model 필드 참고. careerly-reviewer는 claude-sonnet-4-6.
OpenAI API
임베딩 + 일부 에이전트 (openai/gpt-5.5).
Langfuse
관측 (옵션). LANGFUSE_HOST/KEY env로 활성화.
현재 docker-compose.yml에는 ax-dashboard 단일 서비스만 정의돼 있다 (LITE 스택). Qdrant·OpenClaw는 호스트 또는 외부. compose 파일 헤더의 명시: "OpenClaw runs on the HOST (not in Docker)".

배포 플로우

careerly FE / BE + ax-poc dashboard

대상StagingProduction
careerly FEstaging 브랜치 push → Vercel 자동main 머지 → 수동 (SeeSoRuFree author 필수)
careerly BEdevelop push → ASG 자동main → workflow_dispatch (수동 트리거)
ax-poc dashboardDocker compose 재빌드 (현재 Phase 2 로컬 빌드)
상세는 /home/ubuntu/projects/seeso/ax-poc/DEPLOY.md + /home/ubuntu/CLAUDE.md (배포 프로세스 섹션).

기술 스택

apps/dashboard/package.json 기준

next@16.2react@19.2@tanstack/react-query@5.96tailwindcss@4shadcn / @base-ui/reactlucide-reactrecharts@3.8better-sqlite3@12zod@3OpenClaw (host)Qdrant CloudClaude (Sonnet / Opus)CaddyPM2

가이드 & 사용법

페이지별 사용법 + 외부 문서 위치

외부 문서 (마크다운)
프로젝트 README/home/ubuntu/projects/seeso/ax-poc/README.md
에이전트 시스템 README/home/ubuntu/projects/seeso/ax-poc/AGENTS.md
배포 가이드/home/ubuntu/projects/seeso/ax-poc/DEPLOY.md
프로젝트 설정 샘플/home/ubuntu/projects/seeso/ax-poc/ax-config.yaml
도커 컴포즈/home/ubuntu/projects/seeso/ax-poc/docker/docker-compose.yml
워크스페이스 표준/home/ubuntu/CLAUDE.md

이 페이지 유지보수

업데이트 동선

  • 동적 섹션 (에이전트 / 워크플로우 / 헬스 / Qdrant 통계) — API 응답을 그대로 그림. 손댈 필요 없음.
  • 정적 섹션 (다이어그램 박스, 에이전트↔ 슬랙 매핑, 가이드 링크, 인프라 그룹) — src/app/app/inside/inside-config.ts 한 파일만.
  • 새 에이전트 ~/.openclaw/openclaw.json 에 추가하면 인벤토리 자동 반영. slack scope 표기를 원하면 inside-config 의 AGENT_SLACK_BINDINGS 에 한 줄.
  • 새 워크플로우 src/lib/workflows/registry 에 등록하면 인벤토리 + 이 페이지에 자동 반영.
  • 새 가이드 페이지 src/app/app/{section}/guide/page.tsx 만들고 inside-config 의 GUIDE_LINKS 에 추가.
소스src/app/app/inside/page.tsx·_components/*·inside-config.ts